• STM32定时器输入捕获测量高电平时间


    STM32定时器输入捕获测量高电平时间

    本篇内容要求读者对STM32通用定时器有一点理解,如有不解,请看 夜深人静学32系列15——通用定时器

    输入捕获

    在这里插入图片描述

    • 输入捕获是STM32通用定时器的一种功能,可以捕获特定引脚的电平变化(上升沿/下降沿)
    • 对于一个变化的信号。只需要测量上升沿与下降沿的时间间隔,即可计算出高电平的时间。

    当上述时间间隔过长时,由于定时器计数范围有限,因此可能存在溢出的情况,这点需要注意。解决办法如下:

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

    测量高电平时间

    CuebMX配置

    在这里插入图片描述
    在这里插入图片描述

    其它部分设置,请参照往期内容,这里不做赘述,同时需开启定时器3的中断

    代码部分

    • main.c
    extern uint8_t TIM5CH1_CAP_STA;
    extern uint16_t TIM5CH1_CAP_VAL;
    
    int main(void)
    {
      /* USER CODE BEGIN 1 */
      long long temp = 0;// 定义一个变量用以存储捕获到的时间 long long型是为了防止数据溢出
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_TIM3_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
      HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_3);  // 一定要开启TIM5通道1的捕获中断
      __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);  // 一定要开启TIM5的更新中断
      printf("This is Timer3_Channel_Input_Capture test...\n");
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
          HAL_Delay(500);
        if(TIM5CH1_CAP_STA & 0X80)    // 完成一次高电平捕获
        {
          temp = TIM5CH1_CAP_STA & 0X3F;
          temp *= 65536;            // 溢出总时间
          temp += TIM5CH1_CAP_VAL;  // 总的高电平时间
          printf("High level duration:%lld us\r\n",temp);
          TIM5CH1_CAP_STA = 0;      // 准备下一次捕获
        }
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • tim.c
    /* TIM5CH1_CAP_STA 各数据位说明
    ** bit7   捕获完成标志
    ** bit6   捕获到高电平标志
    ** bit5~0 捕获高电平后定时器溢出的次数*/
    uint8_t TIM5CH1_CAP_STA = 0;                        // 输入捕获状态
    uint16_t TIM5CH1_CAP_VAL;                           // 输入捕获值
    // 中断服务函数里面会自动调用这个回调函数,这个是定时器更新中断处理的函数
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
        if(htim->Instance == TIM3)                      // 判断定时器5是否发生中断
        {
            if((TIM5CH1_CAP_STA & 0X80) == 0)           // 还未成功捕获
            {
                if(TIM5CH1_CAP_STA & 0X40)              // 已经捕获到高电平
                {       
                    if((TIM5CH1_CAP_STA & 0X3F) == 0X3F)// 高电平时间太长了,做溢出处理
                    {   
                        TIM5CH1_CAP_STA |= 0X80;        // 标记为完成一次捕获
                        TIM5CH1_CAP_VAL = 0XFFFF;       // 计数器值
                    }
                    else
                    {
                        TIM5CH1_CAP_STA++;              // 若没有溢出,就只让TIM5CH1_CAP_STA自加
                    }                
                }   
            }
        }
    }
    
    // 定时器输入捕获中断处理回调函数,该函数在 HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) 中会被调用
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
        if((TIM5CH1_CAP_STA & 0X80) == 0)               // 还未成功捕获
        {
            if(TIM5CH1_CAP_STA & 0X40)                  // 捕获到一个下降沿
            {       
                TIM5CH1_CAP_STA |= 0X80;                // 标记成功捕获到一次高电平脉宽
                TIM5CH1_CAP_VAL = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_3); // 获取当前的计数器值
                TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_3);                   // 清除原来的设置      
                TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3, TIM_ICPOLARITY_RISING);// 设置上升沿捕获
            }
            else
            {
                TIM5CH1_CAP_STA = 0;                    // 清空自定义的状态寄存器
                TIM5CH1_CAP_VAL = 0;                    // 清空捕获值
                TIM5CH1_CAP_STA |= 0X40;                // 标记捕获到上升沿
                __HAL_TIM_DISABLE(&htim3);              // 关闭定时器
                __HAL_TIM_SET_COUNTER(&htim3, 0);       // 计数器值清零
                TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3);    // 一定要先清除原来的设置  !!          
                TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_3,TIM_ICPOLARITY_FALLING);   // 设置下降沿捕获
                __HAL_TIM_ENABLE(&htim3);               // 使能定时器        
            }   
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    串口重定向部分代码,这里不做展示,往期内容中有…下面来讲一下代码流程

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

    在这里插入图片描述
    清除定时器计数值,设置下一次触发为下降沿触发。。。

    2.等待下一次下降沿触发,期间定时器一直计数,过程中可能存在定时器溢出,溢出进入HAL_TIM_PeriodElapsedCallback(),执行以下代码

    在这里插入图片描述
    记录期间定时器溢出的次数。

    1. 检测到第二个下降沿,进入HAL_TIM_IC_CaptureCallback(),执行以下代码

    在这里插入图片描述
    读取当前定时器计数值,标记捕获高电平持续时间完成

    1. main函数里面计算持续时间,至此完成一次高电平持续时间检测
      在这里插入图片描述
  • 相关阅读:
    2022 年全年 Java 岗面试题总结 + 一线互联网大厂 Java 岗面经 / 面试题总结!
    Transformer pytorch实现逐行详解
    中石化/中石油 油卡充值接口API文档分享
    Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
    Redis 集群搭建教程
    工资支付系统可行性研究报告
    kafka安装和使用的入门教程
    状态模式(State Pattern)
    精彩回顾 | 云原生系统软件的产业应用
    希尔贝壳入选“北京市人工智能大模型高质量数据集发布(第二批)”合作企业
  • 原文地址:https://blog.csdn.net/weixin_67907028/article/details/134507990