目录
一、STM32的定时器与PWM介绍
STM32的定时器与PWM是嵌入式领域中常见的功能,它们在微控制器中扮演着重要的角色。STM32定时器不仅能够提供计时功能,还能够生成PWM(脉冲宽度调制)信号,这在电机控制、LED调光等众多应用中非常关键。具体分析如下:
通用定时器概述
定时器类型:STM32拥有多种类型的定时器,包括基本定时器(TIM6和TIM7)和通用定时器(如TIM2、TIM3、TIM4、TIM5)。高级定时器(TIM1和TIM8)能够同时产生多达7路的PWM输出。
通道功能:每个通用定时器具备4个独立通道,这些通道可以配置为输入捕获、输出比较、PWM输出以及单脉冲模式输出等功能。
PWM输出能力:STM32最多能同时产生30路PWM输出,这对于需要多路PWM控制的场景非常有用。
PWM工作原理
计数器与自动重装载值:PWM的产生涉及计数器当前值(CNT)、自动重装载值(ARR)以及捕获/比较寄存器值(CCRx)。通过比较计数器的值与捕获/比较寄存器的值来控制PWM信号的高低电平状态。
信号频率与占空比:PWM信号的频率由TIMx_ARR寄存器决定,而占空比则由TIMx_CCRx寄存器确定。这种机制使得PWM成为连接数字世界与模拟世界的桥梁。
PWM通道概览
捕获/比较通道结构:每个通道都包括一个捕获/比较寄存器及其影子寄存器,还有数字滤波、多路复用和预分频器等组件构成其输入部分,比较器和输出控制构成输出部分。
寄存器作用:CCRx寄存器用于设置比较值,CCMRx寄存器用于设定PWM模式,而CCER寄存器则控制输入/捕获输出极性和使能。
PWM输出模式区别
模式选择:通过设置TIMx_CCMRx寄存器的OCxM位来选择PWM模式1或模式2。
有效电平判定:PWM模式决定了在计数器向上或向下计数时,何时输出有效电平。结合CCER寄存器的CCxP位来确定是高电平还是低电平为有效。
PWM计数模式
向上计数模式:在PWM模式1下,当计数器的值小于捕获/比较寄存器的值时,PWM信号参考OCxREF为高,否则为低。
向下计数模式:同样在PWM模式1下,当计数器的值大于捕获/比较寄存器的值时,参考信号OCxREF为低,否则为高。
中央对齐模式:该模式下,根据CMS位的不同设置,比较标志可以在计数器向上计数、向下计数或两者时被置’1’。计数方向位DIR由硬件更新,不应通过软件修改。
二、定时器实验
1.定时器计数控制LED两秒的周期性亮-灭
要求: 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。
配置RCC和系统时钟,选择PB3作为GPIO输出口,output为low。
配置定时器TIM3
在STMCubeMX工程中将TIM3定时器配置为内部时钟,且不分频,并作为时钟源。
将预分频器“Prescaler”设置为36000-1,将计数器定时周期“Counter Period”设置为4000-1,根据公式
T=(TIM_Period+1)x(TIM_Prescaler+1)/TIMxCLK
可知:T=36000x4000/72000000=2s
将“auto-reload preload”设置为“Enable”。
在定时器TIM3参数配置“Configuration”选择配置页的“NVIC Setting”选项中使能定时器TIM3的全局中断。
在生成的代码中main.c中的usercode begin2下添加开启定时器TIM3中断的程序。
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim3);
/* USER CODE END 2 */
在main.c的usercode begin4添加定时器TIM3的中断回调函数。
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==htim3.Instance){
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3);
}
}
/* USER CODE END 4 */
实物效果
定时器2s
2.PWM呼吸灯
要求:采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒。
其他地方与上面的例子一样,不同地方在:
在设置定时器TIM3的通道2为PWM Generation CH2,开启TIM3 global interrupt 中断。
A7端口为TIM3_CH2(不需要配置GPIO端口)。预分频系数Prescaler为72-1,自动重装值ARR为500-1,则PWM的输出频率为72000000/72/500=2000HZ。因为LED为低电平有效,所以将PWM的极性设置为Low。
PWM频率:
Fpwm =Tclk / ((arr+1)*(psc+1))(单位:Hz)
arr 是计数器值
psc 是预分频值
占空比:
duty circle = TIM3->CCR1 / arr(单位:%)
TIM3->CCR1 用户设定值
比如 定时器频率Tclk = 72Mhz arr=499 psc=71 那么PWM频率就是720000/500/72= 2000Hz,即2KHz。
arr=499,TIM3->CCR1=250 则pwm的占空比为50%
改CCR1可以修改占空比,修改arr可以修改频率。
在mian.c程序中添加的代码如下
/* USER CODE BEGIN 1 */
uint16_t pwmVal=0; //PWM占空比
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_12);
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while (pwmVal< 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pwmVal); //修改比较值,修改占空比
// TIM3->CCR1 = pwmVal; 与上方相同
HAL_Delay(1);
}
HAL_Delay(200);
}
/* USER CODE END 3 */
keil中逻辑分析仪的PWM输出波形
实物效果:
PWM呼吸灯