ARM嵌入式开发第八章:通用定时器的PWM输出和捕获模式使用
本文介绍了使用STM32定时器实现PWM输出和输入捕获的详细过程。首先通过CubeMX配置TIM2产生1KHz、50%占空比的PWM信号,然后使用TIM3进行输入捕获测量PWM参数。文章重点讲解了两种捕获方式:1)普通输入捕获模式通过测量下降沿间隔计算频率;2)PWM输入模式通过双通道分别捕获周期和脉宽。实验结果表明,两种方法都能准确测量PWM参数,其中PWM输入模式直接获取周期和占空比,实现更简
一、前言
逐步学习一下正点原子的开发板例程代码,看到了对定时器的使用这一部分。
发现定时器我常用的也就是配置PWM输出或者简单作为计时器之类的使用,项目中前面也用其他单片机使用过计算输入PWM的周期和占空比的使用方式(用来判断电机反馈状态的,不同的PWM频率对应不同的转速和故障状态),也就是下面的输入捕获模式。但用的不多,已经快要忘记了,今天重新捡一下,补充整理一下文档资料。
定时器通用定时器存在多种使用模式,今天计划用正点原子的开发板完成一个通过TIM2配置PWM输出1K频率的PWM信号,然后跳线接到TIM3定时器某通道对应的引脚进行PWM脉冲信号的输入捕获实验。

二、CubeMX初始配置
配置SYS->Debug为SW,防止第一次烧录启动后烧录引脚无法使用造成后续无法正常烧录,当然,当出现上述情况也可以通过修改boot启动方式的办法重新烧录解决。
配置RCC的时钟选择,硬件电路有外部时钟则选择Crystal/Ceramic Resonator,没有则Disable默认使用内部时钟也行。

然后去Clock Congfiguration配置时钟树

时钟频率HCLK一般配置成最大即可,输入后会自动跳转其他倍频和分屏系数的,不需要自己计算。
三、配置1KHz频率50%占空比PWM信号输出
将TIIM2通用定时器配置成PWM输出模式,CubeMX相关配置如图所示:

首先,时钟来源选择内部时钟,即APB1时钟的倍频,具体倍频状态,观察相关时钟树

这里APB1 Timer clocks是专门给APB1时钟树上挂载的定时器外设提供的时钟信号,也就是说,TIM2定时器的时钟信号频率是72MHz。
配置预分频系数为72-1,则计数器每秒累计1M次
配置重装载值为1000,则计数器每累加1000次进行一次重载,如果配置了中断,也会同时触发一次中断。因此每秒将会重载1000次,即脉冲频率为1K。

如图所示:TIM2的通道1配置成了PWM输出模式,其中预分频系数是72-1,重装载值是1000,然后PWM Generation Channel 1菜单项的Pulse对应的占空比,配置500则对应500/1000,50%的占空比,配置成100则对应10%。
四、输入捕获模式捕获PWM的频率

先进行普通的输入捕获模式配置
选择TIM3作为捕获的定时器

先配置时钟来源为内部时钟即APB1的倍频,本例中是72MHz时钟,配置Channel为Input Capture direct mode输入捕获模式。
分屏系数配置成72-1,使时钟频率变为1M,重载值时钟成最大65535即可,然后配置捕获信号为Falling Edge 下降沿捕获,当Channel1引脚检测到下降沿则将当前计数器的值保存在捕获比较寄存器中,而当我们开启定时器中断,捕获事件发生后即可进入中断任务,在中断任务中获取捕获比较寄存器中的数据,与上一次中断获取的数据进行减法操作就能知道两次下降沿的触发间隔。
中断函数代码如图所示:(记得在CUBEMX中启用TIM3定时器中断)
uint32_t freq_last = 0;
uint32_t freq = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
uint32_t val = 0;
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
val = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
if(val < freq_last)
{
freq = val + 65535 - freq_last;
}else
{
freq = val - freq_last;
}
freq_last = val;
}
}
main函数中启动TIM2的PWM输出和TIM3的IC捕获
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);


如图所示:TIM2时钟输出PWM脉冲是计数器累计1000次输出一个脉冲,TIM3与TIM2定时器时钟频率配置相同,所以理论来讲TIM3捕获两个下降沿时钟也应该是1000次计算,freq值为1001与理论基本相符。
五、输入捕获特殊模式PWM输入捕获


PWM输入模式是输入捕获的一种特殊用法,具体原理就是将两个输入通道映射到同一个引脚,一个通道记录周期长度,另一个通道记录高或者电平长度,
实现方式就是子通道1捕获到上升沿后让计数器复位从零开始重新累加,所以下一次通道2捕获的就是高电平持续时长,而通道1捕获触发的则是两次上升沿的时长,即周期长度。
上图展示了配置步骤,逐步实现:
1. 两个ICx被映射至同一个TIx

注意,这里1,2是一组,3,4,是一组,1,2可以被映射到同一个引脚,但1,3或者2,3则不行。
2. 两个ICx边沿触发,但是一个上升沿,一个下降沿,参考上图,选择IC1上升沿,IC2下降沿

3. 配置TIxFP为输入触发信号,从模式为复位模式,这里需要先选择从模式复位模式才行

4. 设置时钟分频系数为72-1,保持和TIM2输出PWM时钟的时钟频率一致,方便对比
整体配置如图所示

还要记得打开TIM3的全局中断

生成代码,启动TIM2的PWM输出和TIM3的IC捕获
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
编写回调函数
uint32_t cycle_len = 0;
uint32_t pulse_len = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
uint32_t val = 0;
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//捕获上升沿
{
cycle_len = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
}
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//捕获下降沿
{
pulse_len = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
}
}
执行情况如图所示:

周期对应cycle_len的变量,其值为1000
高电平对应pulse_len的变量,其值为100,
所以计算PWM频率为1M(TIM3时钟频率,计数器每秒累加1M次)/1000(两上升沿间隔计算器累加值),频率为1000
占空比为99/1000,与10%占空比输出的PWM信号相符,当然这点误差可以接受。
更多推荐



所有评论(0)