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

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

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

输入捕获

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

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

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

测量高电平时间

CuebMX配置


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

代码部分

  • main.c
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 */
}
  • tim.c
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. 系统正常运行,检测到第一个上升沿,进入HAL_TIM_IC_CaptureCallback(),执行以下代码

清除定时器计数值,设置下一次触发为下降沿触发。。。

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

记录期间定时器溢出的次数。

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

读取当前定时器计数值,标记捕获高电平持续时间完成

  1. main函数里面计算持续时间,至此完成一次高电平持续时间检测
相关推荐
BreezeJuvenile1 小时前
外设模块学习(5)——DS18B20温度传感器(STM32)
stm32·嵌入式硬件·学习·温度传感器·ds18b20
hollq4 小时前
STM32F103RCT6+STM32CubeMX+keil5(MDK-ARM)+Flymcu实现串口重定向
arm开发·stm32·嵌入式硬件
小鱼儿电子6 小时前
17-基于STM32的宠物饲养系统设计与实现
stm32·嵌入式硬件·物联网·宠物·宠物饲养系统
小莞尔7 小时前
【51单片机】【protues仿真】基于51单片机四层电梯系统
单片机·嵌入式硬件
CFZPL7 小时前
使用江科大串口发送函数发送freertos的vTaskList出现跑飞
单片机
F133168929578 小时前
WD5030A,24V降5V,15A 大电流,应用于手机、平板、笔记本充电器
stm32·单片机·嵌入式硬件·51单片机·硬件工程·pcb工艺
易享电子9 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
爱倒腾的老唐12 小时前
01、如何学习单片机
单片机·嵌入式硬件·学习
点灯小铭12 小时前
基于单片机的夹具压力控制系统设计
单片机·嵌入式硬件·mongodb·毕业设计·课程设计
雾削木18 小时前
stm32解锁芯片
javascript·stm32·单片机·嵌入式硬件·gitee