1021 字
5 分钟
STM32 定时器原理和PWM信号的输出
定时器是什么?
定时器是实际上是一个可编程的计数器,定时器通过不断计数,然后触发一定的事件。
定时器的组成
- 时钟源(Clock Source):时钟源为定时器提供了计数的频率(快慢)来源,时钟源可以来自内部总线(APB1,APB2,由芯片上的晶振产生的震动作为频率来源),也可以来自外部的引脚(如定时器的级联(Slave Mode),时钟源是另一个定时器触发事件时产生的电信号)
- 预分频器(Prescaler, PSC):由于时钟源的频率通常比较高(以内部总线为例,一般为72MHz,也就是一秒内计数器会数72000000下),导致定时器能定时的时长会大大变短。为了解决这一问题,延长定时器所能定时的最大时长,需要先用预分频器对时钟源进行分频。预分频器是一个寄存器,当向这个寄存器中写入值N时,预分频器就会把时钟源的频率降到原来的N+1分之一。
- 计数器(Counter, CNT):用来数数的东西,是一个16位或者32位的寄存器,当接收到时钟源的脉冲信号时,计数器中的值会-1(向下计数)或者+1(向上计数)。
- 自动重装载寄存器(Auto-Reload Register. ARR):用来设定CNT触发事件时需要达到的数。
- 触发事件:当CNT达到ARR中设定的值(不管是向下计数还是下上计数模式),会产生一个更新事件,该事件可以用于以下的操作:
- 产生中断:通知CPU执行中断回调函数中的内容
- 触发DMA请求:通知DMA控制器搬运数据
- 触发其他外设:如触发ADC的转换
- 更新寄存器:将预装载的PSC和ARR值传送到它们的“影子寄存器”中,使其在下一个计数周期生效。
- 清零计数器:CNT的值会被清零或重新填满(取决于计数模式),用于下一个周期的计数
定时器的工作流程图解
+-----------+ CK_CNT +-----------+Clock Source (APBx) -->| Prescaler |------------------>| Counter | | (PSC) | (计数时钟) | (CNT) | +-----------+ +-----+-----+ | | (与ARR比较) V +-----------+ |Auto-Reload| | (ARR) | +-----+-----+ | | (计数达到目标) V +----------------+ | Update Event | | (UEV) | +-------+--------+ | +--------------+--------------+ | | | V V V +----------+ +---------+ +----------+ | Interrupt| | DMA Req | | Trigger | +----------+ +---------+ +----------+使用定时器产生PWM信号
原理
通过比较CNT中的值来改变电平高低,实现占空比(高电平与低电平的时间长度的比值)可调的方波(通过设置ARR与CCR来调整)
具体过程
前面我们提到,当CNT的值达到了ARR中设定的值后,就会触发更新时间,重新开始计数,也就是说ARR定义了CNT数数的总时长(周期),PWM信号的特点是高电平与低平在时间上占有一定的比例,而CRR的设置就是用来调整这个比例的,当CNT的值达到CRR设置的值(并且还未达到ARR中设定的值)时,输出引脚的电平状态就会被改变,从而实现了PWM的信号输出。
可以使用HAL库提供的函数在程序运行时对CRR的值进行修改:
// 将占空比改为80% (假设ARR=999, 则CCR=800)__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 800);使用TIM输出PWM信号的配置过程
- 设置时钟(打开TIM引脚,设置时基单元(配置PSC和ARR))
- 设置用于输出PWM电平的引脚:将被用作输出电平的引脚设置为“复用推挽输出”
- 配置PWM输出通道:选择PWM模式(例如
TIM_OCMODE_PWM1)。设置比较值 Pulse (CCR)。这个值决定了PWM的占空比。设置输出极性(TIM_OCPOLARITY_HIGH表示正常模式,即CNT<CCR时为高电平)。 - 使用HAL库函数启动通道输出PWM信号:
HAL_TIM_PWM_Start(TIM地址, 设置用于输出PWM的通道);
STM32 定时器原理和PWM信号的输出
https://suzumiaoya.github.io/posts/stm32-timer/