[其他ST产品] STM32定时器输入捕获测量高电平时间

[复制链接]
1396|12
 楼主| 慢动作 发表于 2023-11-22 12:27 | 显示全部楼层 |阅读模式
输入捕获 54229655d830bc7776.png
输入捕获是STM32通用定时器的一种功能,可以捕获特定引脚的电平变化(上升沿/下降沿)
对于一个变化的信号。只需要测量上升沿与下降沿的时间间隔,即可计算出高电平的时间。
当上述时间间隔过长时,由于定时器计数范围有限,因此可能存在溢出的情况,这点需要注意。解决办法如下:

检测到第一个有效沿时清空定时器计数值,创建一个变量TIM5CH1_CAP_STA,在每次定时器溢出时,TIM5CH1_CAP_STA加1,检测到第二个有效沿时,读取定时器计数值,那么:
时间间隔 = TIM5CH1_CAP_STA*定时器计数值最大值+定时器当前计数值

7224655d8320dea4a.png


 楼主| 慢动作 发表于 2023-11-22 12:38 | 显示全部楼层
测量高电平时间
CuebMX配置
49911655d85d90bffb.png
 楼主| 慢动作 发表于 2023-11-22 12:39 | 显示全部楼层
89524655d85e27fd51.png

其它部分设置,请参照往期内容,这里不做赘述,同时需开启定时器3的中断
 楼主| 慢动作 发表于 2023-11-22 12:39 | 显示全部楼层
代码部分
main.c
  1. extern uint8_t TIM5CH1_CAP_STA;
  2. extern uint16_t TIM5CH1_CAP_VAL;

  3. int main(void)
  4. {
  5.   /* USER CODE BEGIN 1 */
  6.   long long temp = 0;// 定义一个变量用以存储捕获到的时间 long long型是为了防止数据溢出
  7.   /* USER CODE END 1 */

  8.   /* MCU Configuration--------------------------------------------------------*/

  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  10.   HAL_Init();

  11.   /* USER CODE BEGIN Init */

  12.   /* USER CODE END Init */

  13.   /* Configure the system clock */
  14.   SystemClock_Config();

  15.   /* USER CODE BEGIN SysInit */

  16.   /* USER CODE END SysInit */

  17.   /* Initialize all configured peripherals */
  18.   MX_GPIO_Init();
  19.   MX_TIM3_Init();
  20.   MX_USART1_UART_Init();
  21.   /* USER CODE BEGIN 2 */
  22.   HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_3);  // 一定要开启TIM5通道1的捕获中断
  23.   __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);  // 一定要开启TIM5的更新中断
  24.   printf("This is Timer3_Channel_Input_Capture test...\n");
  25.   /* USER CODE END 2 */

  26.   /* Infinite loop */
  27.   /* USER CODE BEGIN WHILE */
  28.   while (1)
  29.   {
  30.       HAL_Delay(500);
  31.     if(TIM5CH1_CAP_STA & 0X80)    // 完成一次高电平捕获
  32.     {
  33.       temp = TIM5CH1_CAP_STA & 0X3F;
  34.       temp *= 65536;            // 溢出总时间
  35.       temp += TIM5CH1_CAP_VAL;  // 总的高电平时间
  36.       printf("High level duration:%lld us\r\n",temp);
  37.       TIM5CH1_CAP_STA = 0;      // 准备下一次捕获
  38.     }
  39.     /* USER CODE END WHILE */

  40.     /* USER CODE BEGIN 3 */
  41.   }
  42.   /* USER CODE END 3 */
  43. }


 楼主| 慢动作 发表于 2023-11-22 12:42 | 显示全部楼层
tim.c
  1. /* TIM5CH1_CAP_STA 各数据位说明
  2. ** bit7   捕获完成标志
  3. ** bit6   捕获到高电平标志
  4. ** bit5~0 捕获高电平后定时器溢出的次数*/
  5. uint8_t TIM5CH1_CAP_STA = 0;                        // 输入捕获状态
  6. uint16_t TIM5CH1_CAP_VAL;                           // 输入捕获值
  7. // 中断服务函数里面会自动调用这个回调函数,这个是定时器更新中断处理的函数
  8. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  9. {
  10.     if(htim->Instance == TIM3)                      // 判断定时器5是否发生中断
  11.     {
  12.         if((TIM5CH1_CAP_STA & 0X80) == 0)           // 还未成功捕获
  13.         {
  14.             if(TIM5CH1_CAP_STA & 0X40)              // 已经捕获到高电平
  15.             {      
  16.                 if((TIM5CH1_CAP_STA & 0X3F) == 0X3F)// 高电平时间太长了,做溢出处理
  17.                 {   
  18.                     TIM5CH1_CAP_STA |= 0X80;        // 标记为完成一次捕获
  19.                     TIM5CH1_CAP_VAL = 0XFFFF;       // 计数器值
  20.                 }
  21.                 else
  22.                 {
  23.                     TIM5CH1_CAP_STA++;              // 若没有溢出,就只让TIM5CH1_CAP_STA自加
  24.                 }               
  25.             }   
  26.         }
  27.     }
  28. }

  29. // 定时器输入捕获中断处理回调函数,该函数在 HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) 中会被调用
  30. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  31. {
  32.     if((TIM5CH1_CAP_STA & 0X80) == 0)               // 还未成功捕获
  33.     {
  34.         if(TIM5CH1_CAP_STA & 0X40)                  // 捕获到一个下降沿
  35.         {      
  36.             TIM5CH1_CAP_STA |= 0X80;                // 标记成功捕获到一次高电平脉宽
  37.             TIM5CH1_CAP_VAL = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_3); // 获取当前的计数器值
  38.             TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_3);                   // 清除原来的设置      
  39.             TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3, TIM_ICPOLARITY_RISING);// 设置上升沿捕获
  40.         }
  41.         else
  42.         {
  43.             TIM5CH1_CAP_STA = 0;                    // 清空自定义的状态寄存器
  44.             TIM5CH1_CAP_VAL = 0;                    // 清空捕获值
  45.             TIM5CH1_CAP_STA |= 0X40;                // 标记捕获到上升沿
  46.             __HAL_TIM_DISABLE(&htim3);              // 关闭定时器
  47.             __HAL_TIM_SET_COUNTER(&htim3, 0);       // 计数器值清零
  48.             TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3);    // 一定要先清除原来的设置  !!         
  49.             TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3,TIM_ICPOLARITY_FALLING);   // 设置下降沿捕获
  50.             __HAL_TIM_ENABLE(&htim3);               // 使能定时器        
  51.         }   
  52.     }
  53. }
 楼主| 慢动作 发表于 2023-11-22 12:42 | 显示全部楼层
串口重定向部分代码,这里不做展示,往期内容中有…下面来讲一下代码流程

系统正常运行,检测到第一个上升沿,进入HAL_TIM_IC_CaptureCallback(),执行以下代码

34074655d86c072276.png 清除定时器计数值,设置下一次触发为下降沿触发。。。
 楼主| 慢动作 发表于 2023-11-22 12:43 | 显示全部楼层
2.等待下一次下降沿触发,期间定时器一直计数,过程中可能存在定时器溢出,溢出进入HAL_TIM_PeriodElapsedCallback(),执行以下代码 89053655d86daa7c0e.png
 楼主| 慢动作 发表于 2023-11-22 12:43 | 显示全部楼层
记录期间定时器溢出的次数。
 楼主| 慢动作 发表于 2023-11-22 12:47 | 显示全部楼层
检测到第二个下降沿,进入HAL_TIM_IC_CaptureCallback(),执行以下代码

20562655d87e89b9a3.png
 楼主| 慢动作 发表于 2023-11-22 12:48 | 显示全部楼层
读取当前定时器计数值,标记捕获高电平持续时间完成
 楼主| 慢动作 发表于 2023-11-22 12:48 | 显示全部楼层
main函数里面计算持续时间,至此完成一次高电平持续时间检测
 楼主| 慢动作 发表于 2023-11-22 12:48 | 显示全部楼层
EmmaTT 发表于 2024-4-8 14:36 来自手机 | 显示全部楼层
定时器溢出时候会触发中断吗
帛灿灿 发表于 2024-7-16 07:20 | 显示全部楼层

它是由两个尺寸相同、匝数相同的线圈对称地绕制在同一个铁氧体环形磁芯
Bblythe 发表于 2024-7-16 08:23 | 显示全部楼层

镀半孔或c形孔是在板的边缘上镀半个半孔的一半。
周半梅 发表于 2024-7-16 10:19 | 显示全部楼层

这种电路结构的特点是:由四只相同的开关管接成电桥结构驱动脉冲变压器原边。
Pulitzer 发表于 2024-7-16 11:22 | 显示全部楼层

这种技术称为板对板焊接
童雨竹 发表于 2024-7-16 13:18 | 显示全部楼层

模块电源灌封操作之所以重要,主要是由于其涉及到模块电源的防护及热设计
Wordsworth 发表于 2024-7-16 14:21 | 显示全部楼层

得到不同测试条件下的输出电流和电压值,分析数据并进行比较
公羊子丹 发表于 2024-7-16 16:17 | 显示全部楼层

根据电荷守恒:Qinitial=Qfinal
您需要登录后才可以回帖 登录 | 注册

本版积分规则

82

主题

1071

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部