0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

详解定时器的输入捕获功能

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-05-06 09:38 次阅读

输入捕获就是用定时器检测引脚上的电平时间,可以检测高电平时间和低电平时间,然后可以算引脚上信号的频率和占空比。

基本思路就是利用定时器的输入捕获功能。

定时器捕获到高电平或低电平就会进入捕获中断

例如:

我们要捕获高电平时间

0 设置定时器计数频率和装载值,一般设置1MHz,65535

1 设置定时器捕获为高电平捕获

2 进入捕获中断后,获取CNT计数值或CCRx值,定时器捕获到电平后会把CNT的值保存到CCRx。

设置成低电平捕获。

3 再次进入捕获中断,获取CNT计数值-上次的CNT值=总高电平时间。

设置成高电平捕获。

4 重复2-3即可完成下一次捕获。当然还要考虑溢出的情况,代码里有处理。

下面我写的一个实例:

1 定时器1 PA8产生PWM信号,可改变占空比,检测高电平时间

2 捕获定时器是定时器2,初始化如上例。

3 仿真改变PA8占空比,查看捕获出的高电平时间。

实测:

查看源图像

duty=1000就是高电平维持1000us,

捕获时间也是对应的1000us,一点误差都没有。

代码如下:

//高电平标志
u8  gao_flag=0;
//高电平时间
u32 gao_timer=0;
//捕获成功标志
u8  buhuo_flag=0;
//溢出次数
u8  yichu_c=0;

//定时器 5 中断服务程序
extern "C" void TIM2_IRQHandler(void)
{
 if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
  {

  
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //这个是溢出中断
  {
   //如果已经得到高电平了,CNT溢出了
   if(gao_flag==1)
   {
    
    yichu_c++;  //溢出加1
    
  
   }
   
  }
  
  
 if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获 1 发生捕获事件
 {
    if(0==gao_flag&&buhuo_flag==0) //说明之前没有捕获到高电平
   {
    gao_timer=TIM2->CCR1;  //获取高电平时间

    yichu_c=0;       //溢出清零
    
    gao_flag=1;   //高电平标志
    
    TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //改成下降沿捕获
   }
   //再一次进入捕获中断说明是捕获到下降沿了
   else
   {
    if(buhuo_flag==0)   //判断是否捕获成功了,如果捕获成功了就不在捕获了
    {
    
     gao_timer=TIM2->CCR1-gao_timer;  //获取捕获到的高电平时间
     gao_timer+=yichu_c*65536;       //加上溢出时间

     TIM2->CNT=0;         //计数清零
     
     gao_flag=0;                   //高电平标志清零
     
     buhuo_flag=1;              //标志捕获成功了
     
     TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //改成上沿捕获
     
     
    }
    
   }

 }
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}

void TIM1_PWM_Init(u16 arr,u16 psc)
{
 GPIO_InitTypeDef     GPIO_InitStrue;
   TIM_OCInitTypeDef     TIM_OCInitStrue;
   TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
   
   
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);        //使能TIM3和相关GPIO时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 使能GPIOB时钟(LED在BP5引脚),使能AFIO时钟(定时器3通道2需要重映射到BP5引脚)
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   
   GPIO_InitStrue.GPIO_Pin=GPIO_Pin_8;     // TIM_CH2
   GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;    // 复用推挽
   GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;    //设置最大输出速度
   GPIO_Init(GPIOA,&GPIO_InitStrue);                //GPIO端口初始化设置
   
 //TIM1->CCMR1&=0xF7F7; //关闭事件更新值
 //TIM1->CCMR1|=0x808; //开启事件更新值

   TIM_TimeBaseInitStrue.TIM_Period=50000;    //设置自动重装载值
   TIM_TimeBaseInitStrue.TIM_Prescaler=71;        //预分频系数
   TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;    //计数器向上溢出
   TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;        //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
   TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrue);        //TIM3初始化设置(设置PWM的周期)
   
   TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM2;        // PWM模式2:CNT>CCR时输出有效
   TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_Low;// 设置极性-有效为高电平
   TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能
 
 TIM_OCInitStrue.TIM_Pulse=100;
 
   TIM_OC1Init(TIM1,&TIM_OCInitStrue);        //TIM3的通道2PWM 模式设置

   TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);        //使能预装载寄存器
   
   TIM_Cmd(TIM1,ENABLE);        //使能TIM3
 TIM_CtrlPWMOutputs(TIM1, ENABLE);  
 
 TIM1->CCMR1&=0xF7F7; //关闭事件更新值
 
}

void capture_init(u16 arr,u16 psc)
{
TIM_OCInitTypeDef TIM2_OCInitStructure;
TIM_ICInitTypeDef TIM2_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能 TIM2 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉

//初始化定时器 2 TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化 TIMx 的时间基数单位

//初始化 TIM2 输入捕获参数

TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到 TI1 上
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_CKD_DIV1; //配置输入分频,不分频
TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
TIM_ICInit(TIM2, &TIM2_ICInitStructure);




//中断分组初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 2 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化外设 NVIC 寄存器
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);



TIM_Cmd(TIM2,ENABLE );  //使能定时器3

}

u16 duty=1000;

int main(void)

{


  
  serial_init(115200); //串口初始化为 9600
  
  TIM1_PWM_Init(1000,71); //

PAout(1)=1;

  capture_init(0XFFFF,72-1); //以 1Mhz 的频率计数

printf("initrn");



 while(1)
  {
  
  //测试位运算和逻辑运算的速度

  
 PAout(1)=1;

  
  
  
  TIM1->CCR1=duty;
  
   delay_ms(10);
  

 if(buhuo_flag==1)
 {
  printf("HIGH1:%d us rn",gao_timer); //打印总的高点平时间
 
  buhuo_flag=0;  //重新捕获
  
  
 }
 
 PAout(1)=0;
   delay_ms(10);

  }

 
}

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5305

    浏览量

    119914
  • 电平
    +关注

    关注

    5

    文章

    357

    浏览量

    39829
  • 定时器
    +关注

    关注

    23

    文章

    3236

    浏览量

    114396
收藏 人收藏

    评论

    相关推荐

    详解STM32定时器捕获功能

    STM32的定时器是支持信号输入捕获的,何为输入捕获?主要做什么应用?
    的头像 发表于 01-12 17:24 8267次阅读
    <b class='flag-5'>详解</b>STM32<b class='flag-5'>定时器</b><b class='flag-5'>捕获</b><b class='flag-5'>功能</b>

    STM32定时器(三)输入捕获

    STM32的定时器是支持信号输入捕获的,何为输入捕获?主要做什么应用?
    的头像 发表于 07-21 14:58 4022次阅读
    STM32<b class='flag-5'>定时器</b>(三)<b class='flag-5'>输入</b><b class='flag-5'>捕获</b>

    STM32 --通用定时器输入捕获功能 精选资料推荐

    问题:开始的时候没有搞清楚 定时器时基 于 定时器溢出中断导致在计算的时候一直有问题。开始并没有怀疑是配置有问题,因为之前接触过定时器输入捕获
    发表于 08-19 06:34

    从应用方面详解STM32的定时器输入捕获模式

    从应用来说STM32的定时器输入捕获模式前言原理输入捕获初始化程序中断函数和处理函数前言我们知道,STM32的
    发表于 01-06 07:37

    stm32定时器输入捕获

    不同频率、不同占空比的方波信号、PWM信号,同时做为输入捕获功能时,可以测量脉冲宽度、实现电容按键检测等等。 一、输入捕获概念
    发表于 10-13 09:13 2.4w次阅读
    stm32<b class='flag-5'>定时器</b><b class='flag-5'>输入</b><b class='flag-5'>捕获</b>

    基于STM32定时器输入捕获解析

    输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6和TIM7,其他定时器都有输入
    发表于 09-04 11:00 5971次阅读

    stm32 定时器 捕获

    输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6和TIM7,其他定时器都有输入
    发表于 09-08 17:07 2355次阅读

    基于STM32定时器捕获测量脉宽的应用示例

    来实现脉宽测量,我们可以选用一个通道、也可以使用两个通道。使用1个通道时,只需使用定时器基本的输入捕获功能结合中断或DMA即可实现;若使用两个通道时可以将
    的头像 发表于 01-02 18:17 1.3w次阅读
    基于STM32<b class='flag-5'>定时器</b><b class='flag-5'>捕获</b>测量脉宽的应用示例

    华大HC32-(05)-定时器输入捕获

    华大HC32-(05)-定时器输入捕获
    发表于 11-23 18:06 28次下载
    华大HC32-(05)-<b class='flag-5'>定时器</b><b class='flag-5'>输入</b><b class='flag-5'>捕获</b>

    stm32定时器输入捕获配置步骤及实例笔记

    输入捕获的一般配置步骤:初始化定时器和通道对应IO的时钟。初始化IO口,模式为输入:GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_M
    发表于 11-23 18:21 42次下载
    stm32<b class='flag-5'>定时器</b><b class='flag-5'>输入</b><b class='flag-5'>捕获</b>配置步骤及实例笔记

    STM32CubeMX——定时器输入捕获

    通用定时器在基本定时器的基础上增加了一个外部引脚,可以实现输入捕获与输出比较等功能。高级定时器T
    发表于 12-02 14:06 9次下载
    STM32CubeMX——<b class='flag-5'>定时器</b><b class='flag-5'>输入</b><b class='flag-5'>捕获</b>

    STM32定时器输入捕获实验

    概述输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入
    发表于 12-14 18:58 20次下载
    STM32<b class='flag-5'>定时器</b><b class='flag-5'>输入</b><b class='flag-5'>捕获</b>实验

    通用定时器输入捕获实验

    文章目录通用定时器输入捕获实验(寄存版本)1、作用2、过程3、图解4、测试方法5、代码通用定时器
    发表于 01-12 19:53 9次下载
    通用<b class='flag-5'>定时器</b>的<b class='flag-5'>输入</b><b class='flag-5'>捕获</b>实验

    使用通用定时器输入捕获实例

    本文将介绍通过使用通用定时器输入捕获功能来记录按键按下的时间,并通过串口调试工具打印出按键按下的时间。
    的头像 发表于 05-01 09:02 1009次阅读
    使用通用<b class='flag-5'>定时器</b>的<b class='flag-5'>输入</b><b class='flag-5'>捕获</b>实例

    CW32定时器操作讲解——输入捕获

    CW32定时器操作讲解——输入捕获
    的头像 发表于 09-27 16:06 902次阅读
    CW32<b class='flag-5'>定时器</b>操作讲解——<b class='flag-5'>输入</b><b class='flag-5'>捕获</b>