AS32系列MCU芯片TIM模块的捕获和比较

电子说

1.4w人已加入

描述

一、引言

AS32系列MCU芯片集成4个高级定时器,每个定时器包含一个32位自动重载计数器,该计数器由可编程预分频器驱动,支持递增、递减、中心计数、编码器模式等计数方式。

高级定时器具有6个独立通道,可实现测量输入信号的脉冲宽度、可编程PWM输出、带死区插入的互补PWM等功能。

二、PWM简介

PWM,全称脉冲宽度调制。它是一种用数字信号来模拟模拟电压的技术。简单来说,就是快速地在“开”(高电平)和“关”(低电平)之间切换,通过改变一个周期内“开”的时间比例,来控制平均电压。

2.1****输出比较模式

定时器被配置为PWM模式时,会用到比较寄存器。

周期: 由自动重载寄存器决定。计数器从0计数到这个值,然后归零,这个过程就是一个PWM周期。

占空比: 由比较寄存器决定。它设定了电平翻转的阈值。

工作流程:

1.计数器从0开始向上计数。

2.当计数器的值 小于 比较寄存器的值时,输出高电平(例如)。

3.当计数器的值 达到或超过 比较寄存器的值时,输出翻转为低电平。

4.计数器到达自动重载值后归零,输出重新变为高电平,开始下一个周期。

通过修改比较寄存器的值,就改变了高电平在一个周期内持续的时间,从而改变了 占空比

输出比较可用于:

控制LED亮度: 占空比越大,LED越亮。

驱动舵机: 舵机的角度由PWM脉冲的宽度精确控制。

控制电机速度: 通过改变平均电压来调节直流电机转速。

音频输出: 通过极高频率的PWM,经过滤波后可以生成简单的音频信号。

2.2****输入捕获

输入捕获功能就像一个“高速抓拍机”。当外部引脚上发生一个特定事件(如上升沿)时,它立刻“抓拍”下当前计数器的值,并保存起来。通过分析两次“抓拍”的值,我们就能计算出这个事件的时间参
定时器配置为输入捕获模式时,会用到 捕获寄存器

工作流程:

1.定时器的计数器一直在自由运行。

2.当输入引脚上出现第一个上升沿时,硬件会立即将计数器当前的值复制到捕获寄存器中,并产生一个中断。

3.在中断服务程序里,程序读取这个捕获值(记为t1),并同时将捕获边沿设置为 下降沿

4.当引脚出现下降沿时,硬件再次将计数器的当前值捕获(记为t2)。

5.程序计算 t2 - t1,这个差值就是高电平期间计数器计数的次数,再乘以计数周期,就得到了高电平脉冲的精确宽度。

6.同理,可以再捕获下一个上升沿,计算出整个信号的周期。

输入捕获可用于:

测量脉冲宽度和频率: 例如解码红外遥控信号(NEC协议)、测量超声波测距模块返回的脉冲宽度。

解码编码器信号: 读取旋转编码器的位置和速度。

测量数字信号的占空比。

三、软件设计

本文同时启用定时器HTIM1与HTIM5的通道1与通道2。其中,两个定时器的通道1均配置为PWM输出模式,以生成PWM信号;相应的通道2则工作在输入捕获模式,并采用中断驱动方式,以精确测量PWM信号的频率与占空比。最终,测量数据将通过串口打印输出。引脚连线如下:PD4->PH9, PC9->PD5

MCU芯片

3.1软件分析

HTIM1初始化函数: void User_TIM1_Config(uint32_t arr, uint32_t psc, uint32_t rcr);

硬件使能与准备

  1. GPIOD_CLK_ENABLE(); // 使能GPIOD时钟
  2. HTIM1_CLK_ENABLE(); // 使能HTIM1时钟

定时器时基配置

  1. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
  2. TIM_TimeBaseInitStructure.TIM_Period = arr; // 设定周期
  3. TIM_TimeBaseInitStructure.TIM_Prescaler = psc; // 设定预分频
  4. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = rcr; // 重复计数

输入捕获配置(通道2

  1. TIM_IC_InitStructure.TIM_Channel = TIM_Channel_2; // 使用通道2
  2. TIM_IC_InitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 上升沿捕获
  3. TIM_IC_InitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 直接输入
  4. TIM_IC_InitStructure.TIM_ICFilter = 0x0; // 无滤波器
  5. TIM_IC_InitStructure.TIM_ICPrescaler = 0x0; // 每个事件都捕获

中断与PWM输出配置

中断使能:

  1. TIM_IT_Update://定时器溢出更新中断
  2. TIM_IT_CC2://通道2捕获/比较中断

PWM****输出配置(通道1):

  1. TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
  2. TIM_OC_InitStructure.TIM_Pulse = arr/2; // 初始占空比50%
  3. TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 高电平有效

注:HTIM5配置除GPIO引脚外其余配置通HTIM1,此外HTIM5和HTIM1挂在不同总线下,读者使用时需自行计算外设时钟

在输入捕获模式下,当相应的 ICx 信号检测到跳变沿后,将使用捕获/比较寄存器(TIMx_CCRx)来锁存计数器的值。简单的说就是通过检测 TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。

MCU芯片

从上图可以看出,t1-t2 时间就是需要测量的高电平时间,假如定时器工作在向上计数模式,测量方法是:首先设置定时器通道 x 为上升沿捕获,这样在 t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x 为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。根据定时器的计数频率,就可以算出 t1-t2 的时间,从而得到高电平脉宽。在 t1-t2 时间内可能会出现 N 次定时器溢出,因此还需要对定时器溢出进行处理,防止因高电平时间过长发生溢出导致测量数据不准。CNT计数的次数等于:N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。部分逻辑在中断函数中实现:

  1. void TIM1_IRQ_Handler()
  2. {
  3. static uint32_t TIM1_counter=0;
  4. /* Get the value of TIM_CNT*/
  5. if (TIM1_GetComplete==0)
  6. {
  7. if (TIM_GetITStatus(TIM1, TIM_IT_Update)!= RESET)
  8. {
  9. TIM1_Update_counter++;
  10. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
  11. }
  12. if (TIM_GetITStatus(TIM1, TIM_IT_CC2)!= RESET)
  13. {
  14. TIM1_counter++;
  15. if (TIM1_counter==1)
  16. {
  17. TIM1_Update_counter=0;
  18. TIM1_Value1=TIM_GetCounter(TIM1);
  19. }
  20. if (TIM1_counter==2)
  21. {
  22. TIM1_Value2=TIM_GetCounter(TIM1);
  23. TIM1_counter=0;
  24. TIM1_GetComplete=1;
  25. }
  26. TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
  27. }
  28. }
  29. else
  30. {
  31. TIM_ClearITPendingBit(TIM1, TIM_IT_Update | TIM_IT_CC2);
  32. }
  33. }

计算并输出PWM信号周期和频率的函数

  1. /* Calculate the input frequency and period */
  2. TIM1_Input_Poriod=(10000*TIM1_Update_counter-TIM1_Value1+TIM1_Value2);
  3. TIM1_Input_Poriod = TIM1_Input_Poriod/20;
  4. Printf("TIM1 Input_Poriod: %d usrn", (uint32_t)TIM1_Input_Poriod);
  5. Printf("TIM1 Frequence: %d hzrn", (uint32_t)(1000000/TIM1_Input_Poriod));
  6. TIM1_Update_counter=0;
  7. TIM1_GetComplete=0;
  8. ClearCache();

其中第三行的20 为 HTIM1的时钟频率为20M。

四、开发板验证:

MCU芯片

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分