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

【经验分享】STM32F103定时器输入捕获功能

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:55
  STM32F103单片机的定时器不仅能输出PWM波,而且还能捕获输入的PWM波。可以通过定时器的捕获功能测量输入PWM波的周期和占空比。其中定时器的输入捕获功能如下:

  在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。

  这里就使用捕获模式测量PWM波形的高电平时长,具体实现原理简单的来说就是,当第一个上升沿到来之后,清空计数器,当第一个下降沿到来之后,此时计数器的值就是高电平的值。
设置代码如下:

  1. void TIM5_Cap_Init(u16 arr, u16 psc)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  5.     TIM_ICInitTypeDef TIM_ICInitStructure;
  6.     NVIC_InitTypeDef NVIC_InitStructure;

  7.     //时钟初始化
  8.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  10.     //IO口初始化
  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  13.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  14.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  15.     //TIM5初始化
  16.     TIM_TimeBaseStructure.TIM_Period = arr;
  17.     TIM_TimeBaseStructure.TIM_Prescaler = psc;
  18.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  19.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  20.     TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
  21.     //TIM5输入捕获参数
  22.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;                                 //CC1S=01 选择输入端 IC1映射到TI1上
  23.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;           //上升沿捕获
  24.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //映射到TI1上
  25.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                         //配置输入分频,不分频
  26.     TIM_ICInitStructure.TIM_ICFilter = 0x00;                                                 //IC1F=0000 配置输入滤波器 不滤波
  27.     TIM_ICInit(TIM5, &TIM_ICInitStructure);
  28.     //中断分组初始化
  29.     NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
  30.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  31.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  32.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  33.     NVIC_Init(&NVIC_InitStructure);

  34.     TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);
  35.     TIM_Cmd(TIM5, ENABLE);
  36. }


  37. u8  TIM5CH1_CAP_STA = 0;    //输入捕获状态
  38. u16 TIM5CH1_CAP_VAL;                //输入捕获值
  39. void TIM5_IRQHandler(void)
  40. {
  41.     if((TIM5CH1_CAP_STA & 0x80) == 0)
  42.     {
  43.         if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)                          //溢出中断
  44.         {
  45.             if(TIM5CH1_CAP_STA & 0x40)                                                                  //已经捕获到高电平了
  46.             {
  47.                 if((TIM5CH1_CAP_STA & 0x3F) == 0x3F)                                  //高电平太长了
  48.                 {
  49.                     TIM5CH1_CAP_STA |= 0x80;                                                  //标记成功捕获了一次
  50.                     TIM5CH1_CAP_VAL = 0xFFFF;
  51.                 }
  52.                 else
  53.                     TIM5CH1_CAP_STA++;
  54.             }
  55.         }
  56.         if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)                                  //捕获中断
  57.         {
  58.             if(TIM5CH1_CAP_STA & 0x40)                                                                  //下降沿捕获
  59.             {
  60.                 TIM5CH1_CAP_STA |= 0x80;                                                          //标记成功捕获一次高电平脉宽
  61.                 TIM5CH1_CAP_VAL = TIM_GetCapture1(TIM5);
  62.                 TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);         //设置上升沿捕获
  63.             }
  64.             else                                                                                                            //上升沿捕获
  65.             {
  66.                 TIM5CH1_CAP_STA = 0;                                                                  //清空
  67.                 TIM5CH1_CAP_VAL = 0;
  68.                 TIM_SetCounter(TIM5, 0);
  69.                 TIM5CH1_CAP_STA |= 0x40;                                                          //标记捕获到了高电平
  70.                 TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling); //设置下降沿捕获
  71.             }
  72.         }
  73.     }
  74.     TIM_ClearITPendingBit(TIM5, TIM_IT_Update | TIM_IT_CC1);
  75. }
复制代码

  这里使用定时器5的通道1来进行捕获,首先设置通道1为上升沿捕获,当上升沿触发中断之后,清空计数器的值,然后将中断设置为下降沿中断。当下一次下降沿中断触发后,此时的时间就是PWM波的高电平时间,接着再将中断设置为上升沿中断,等待下一次高电平的触发。

  每次捕获成功时,在主函数中将高电平时长打印出来。

  1. extern u8  TIM5CH1_CAP_STA;            //输入捕获状态
  2. extern u16 TIM5CH1_CAP_VAL;                //输入捕获值
  3. int main(void)
  4. {
  5.     u32 temp = 0;
  6.     delay_init();                       //延时函数初始化
  7.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  8.     uart_init(115200);
  9.     LED_Init();

  10.     LED0 = 1;
  11.     LED1 = 1;
  12.     delay_ms(500);
  13.     LED0 = 0;
  14.     LED1 = 0;

  15.     TIM3_PWM_Init(3600-1,0);             //不分频。PWM频率=72000000/3600=20Khz   PB5输出PWM
  16.         
  17.     TIM5_Cap_Init(0xffff, 72 - 1);                //以1Mhz的频率计数  PA0

  18.     printf("Input Capture test!!!\r\n");
  19.     while(1)
  20.     {
  21.         delay_ms(10);
  22.         TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);

  23.         if(TIM_GetCapture2(TIM3)==3600)
  24.             TIM_SetCompare2(TIM3,0);        

  25.         if(TIM5CH1_CAP_STA & 0X80)                                 //成功捕获到了一次上升沿
  26.         {
  27.             temp = TIM5CH1_CAP_STA & 0X3F;
  28.             temp *= 65536;                                                 //溢出时间总和
  29.             temp += TIM5CH1_CAP_VAL;                         //得到总的高电平时间
  30.             printf("HIGH:%d us %d ms %d s\r\n", temp,temp/1000,temp/1000000);         //打印总的高点平时间
  31.             TIM5CH1_CAP_STA = 0;                                 //开启下一次捕获
  32.         }
  33.     }
  34. }
复制代码


定时器3用来产生一个PWM波,然后通过定时器5的捕获功能来测量PWM波的高电平时间。


收藏 评论0 发布时间:2022-3-19 20:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

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