【零基础学STM32】CubeMX+HAL配置PWM小灯

【零基础学STM32】CubeMX+HAL配置PWM小灯,第1张

通用定时器的简单应用
  • 项目简介
  • 简单原理介绍
    • 简单寄存器简介
    • PWM波原理
  • CubeMX 配置&相应工程代码
  • 效果展示
  • 出现的问题
  • 补档

项目简介

本次小实验基于STM32F429IGT6开发板,通过对通用定时器的使用,达到以下实验目标:
输出PWM波,使得LED对应亮度,实现半呼吸灯
本文参考书为王维波老师的《STM32Cube高效开发教程 基础篇》最近高级篇已经出版 感兴趣的小伙伴可以支持一波
本文参考链接:野火-高级定时器

简单原理介绍 简单寄存器简介

在F4系列中,通用定时器指的是TIM2-5 & TIM9-14,其中TIM2-5有4个捕获/比较通道,可以实现外部时钟信号驱动,而TIM9-14只有1/2个通道,因为只能使用内部时钟信号。


1个通道的还没有内部触发输入,也就不能使用从模式与其他定时器串联。



以2-5框图为例

定时器内部时钟信号CK_INT,其源来自APB1/APB2,如果设置为从模式,还可以使用别的定时器输出信号作为自己的输入信号。



其中TIM9-11挂载在APB2,TIM12-14挂载在APB1
通过多项选择器,触发控制器输出CK_PSC信号,用于控制定时器复位,使能,计数等等
PSC经过PSC预分频处理(1~65536分频),进入CNT计数器(2-5 32位,9-12 16位,2-5还可以设置递增或递减计数,默认为递增计数),定时器运行时修改PSC分频值,需要下一个UEV事件到来之后才能修改
其上有ARR自动重装载寄存器,用来调控计数周期,有影子寄存器,通过ARPE的0/1来确定是否使用影子寄存器,即0时不适用,ARR写入新值立即生效;1时在UEV事件之后才更新影子寄存器中ARR写入的新值,UEV才生效。



CNT,PSC,ARR构成定时器的时基单元,其控制位有:
TIMx_CR1 ->CEN位使能寄存器,1时经过1周期,CK_CNT工作,0时不工作
TIMx_EGR ->UG通过软件模式产生一次更新时间,在经历一个CK_CNT一个脉冲,产生UEV并自动复位UG,计数器值清零重新计数
更多介绍详见参考手册,这里就不多赘述了

PWM波原理

PWM:脉冲宽度调制,即具有一定占空比的信号,对模拟电压进行数字编码,根据数电的知识,可以用施密特触发器产生(原理相似而已)
原理图如图所示

通过设置捕获/比较寄存器CCR的值和ARR的值,就可以实现占空比的调节
注:书中给出的是CNT 具体极性需要配置输出模式:
PWM模式1- 在向上计数时,一旦TIMx_CNT 无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否
则为有效电平(OC1REF=1)。



PWM模式2- 在向上计数时,一旦TIMx_CNT 有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电

CubeMX 配置&相应工程代码

新建新工程,配置时钟树,HCLK=168MHz
查原理图可知LED接在PB1引脚,所以需要通过PB1引脚输出PWM配置小灯即可。



cube显示PB1引脚PWM通过PWM3通道4配置,故在timers-tim3选择,时钟源选择内部时钟源(因为挂载在APB1,时钟频率=APB1总线频率/PSC+1)APB1此时为84MHz,所以配置PSC=84-1;ARR配置为1000-1,表示1000*1/1M为一个周期1ms。



如图所示

开启TIM2定时器,与TIM3配置几乎相同,开启中断,并配置NVIC抢占优先级为3,(如果你的cubemx也存在默认滴答定时器优先级为15,需要手动调回0,否则会有很多麻烦)。



生成工程即可,一定要全英文路径。



首先开启TIM2,并打开TIM3的PWM波

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim2); 
  HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_4);
  /* USER CODE END 2 */

通过配置中断回调函数
HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
具体代码如下:

/* USER CODE BEGIN PFP */
	int a=0;
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim==&htim2)
	{
	  __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,a);
		a++;
		if(a>999-1) 
		a=0;	
	}
}

注意:a一定要是外部定义的而不是回调函数中定义的,否则会出现没反应的问题
以及:a>999可能会导致小小的溢出,所以减了1,防止溢出
这里默认的是PWM1输出,也就是CNT 效果展示

小灯最开始最亮,最后变最暗,然后瞬间变得最亮。


因为小灯低电平有效所以最开始是最亮的

出现的问题

这个实验过于简单,只需要记住几个关键点就可以完成试验。



最近开学了在家隔离没法返校,本人也是刚入门的菜鸟。


我会基本每天都有新东西更新,如果觉得有点帮助的话请为我点赞哦~
呼吸灯会在下个小实验里面更新更完整的 以及一些pwm的别的用法~

补档

2022.4.1
完善了完整呼吸灯 代码如下:

void PWM_UpAndDowm(void)
{
	if(flag == 1)
	{
		a++;
		if(a>999){
			a= 999;
			flag =0;
		}
	}
	else{
		a--;
		if(a<=0){
			a=0;
			flag =1;
	}
	
}
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,a);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim==&htim2)
	{
		PWM_UpAndDowm();
	}
}

参数都不变 注意的地方是调用和嵌套的先后顺序 以及标志位

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/584494.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存