你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32使用HAL库进行脉冲宽度和周期测量

[复制链接]
STMCU小助手 发布时间:2022-4-10 23:06
使用芯片:STM32F103RCT6

思路:定时器设置为1MHZ的计数频率,定时计数器增加一就是增加1us

① 首先设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;
② 然后切换为下降沿捕获,捕获下降沿记录此刻的时间计数值;
③ 最后设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;

对于16bit定时器,最大可计数0xFFFF,也就是65535us,那么:高电平持续的时间 = 定时器溢出计数 * 0xFFFF + 当前计数值
对于32bit定时器,最大可计数0xFFFFFFFF,也就是4294.967295s,这个时间足够测量脉冲宽度的了,那么:高电平持续的时间 = 当前计数值

高电平持续的时间 = ② - ①
周期 = ③ - ①


定时器配置
设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:

8[4}G`FDCF54{JG}]@4O9TB.png
NG9OV6{[MUZ]J)5X}`C8583.png

NTLDI)_~LVR1`A]ZFP5WDCG.png


中断分组设置

6N3V6OFD3XI6X(HW1EPLGIQ.png

代码配置
tim.c中添加如下代码:



  1. __IO uint32_t TIM2_TIMEOUT_COUNT = 0;                        ///< 定时器2定时溢出计数
  2. uint32_t TIM2_CAPTURE_BUF[3]   = {0, 0, 0};                ///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
  3. __IO uint8_t TIM2_CAPTURE_STA = 0xFF;                        ///< 状态标记

  4. /**
  5. * 设置TIM2输入捕获极性
  6. * @param TIM_ICPolarity:
  7. *        TIM_INPUTCHANNELPOLARITY_RISING  :上升沿捕获
  8. *        TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
  9. *        TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获
  10. */
  11. inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
  12. {
  13.     htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
  14.     htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
  15. }

  16. /// 定时器2时间溢出回调函数
  17. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  18. {
  19.     if (htim->Instance == htim2.Instance)
  20.     {
  21.         TIM2_TIMEOUT_COUNT++;                                                                                // 溢出次数计数
  22.     }
  23. }

  24. ///< 输入捕获回调函数
  25. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  26. {
  27.     if (htim->Instance == htim2.Instance)
  28.     {
  29.         switch (TIM2_CAPTURE_STA)
  30.         {
  31.         case 1:
  32.         {
  33.             printf("准备捕获下降沿...\r\n");
  34.             TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
  35.             TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING);                                        // 设置为下降沿触发
  36.             TIM2_CAPTURE_STA++;
  37.             break;
  38.         }
  39.         case 2:
  40.         {
  41.             printf("准备捕获下个上升沿...\r\n");
  42.             TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
  43.             TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);                                        // 设置为上升沿触发
  44.             TIM2_CAPTURE_STA++;
  45.             break;
  46.         }
  47.         case 3:
  48.         {
  49.             printf("捕获结束...\r\n");
  50.             printf("# end ----------------------------------------------------\r\n");
  51.             TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
  52.             HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1);                                                                        // 停止捕获
  53.             HAL_TIM_Base_Stop_IT(&htim2);                                                                                                // 停止定时器更新中断
  54.             TIM2_CAPTURE_STA++;
  55.             break;
  56.         }
  57.         default:
  58.             break;
  59.         }
  60.     }
  61. }

  62. ///< TIM2轮训状态切换
  63. inline void TIM2_Poll(void)
  64. {
  65.     switch (TIM2_CAPTURE_STA)
  66.     {
  67.     case 0:
  68.     {
  69.         printf("# start ----------------------------------------------------\r\n");
  70.         printf("准备捕获上升沿...\r\n");
  71.         TIM2_TIMEOUT_COUNT = 0;
  72.         __HAL_TIM_SET_COUNTER(&htim2, 0);                                                                                        // 清除定时器2现有计数
  73.         memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF));                                                // 清除捕获计数
  74.         TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);                                        // 设置为上升沿触发
  75.         HAL_TIM_Base_Start_IT(&htim2);                                                                                                // 启动定时器更新中断
  76.         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);                                                                        // 启动捕获中断
  77.         TIM2_CAPTURE_STA++;
  78.         break;
  79.     }

  80.     case 4:
  81.     {
  82.         uint32_t high  = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];
  83.         uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];
  84.         float frq = 1.0 / (((float)cycle) / 1000000.0);
  85.         TIM2_CAPTURE_STA++;

  86.         printf("\r\n\r\n");
  87.         printf("################################# START #########################################\r\n");
  88.         printf("高电平持续时间:%dms\r\n", high / 1000);
  89.         printf("周期          :%dms\r\n", cycle / 1000);
  90.         printf("频率          :%fHz\r\n", frq);
  91.         printf("################################## END ##########################################\r\n\r\n");
  92.         break;
  93.     }

  94.     default:
  95.         break;
  96.     }
  97. }
复制代码

main.c:

  1. int main()
  2. {
  3.     HAL_Init();
  4.     SystemClock_Config();
  5.     MX_GPIO_Init();
  6.     DEBUG_UART_Init();
  7.     MX_TIM2_Init();
  8.     printf("================================ 系统运行! ================================  \r\n");
  9.     while(1)
  10.     {
  11.         TIM2_Poll();
  12.         DEBUG_UART_RecvHandler();
  13.     }
  14. }
复制代码


说明:串口一接串口调试助手,勾选发送新行,向单片机发送任意字符以此来启动输入捕获。



收藏 评论0 发布时间:2022-4-10 23:06

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版