打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
STM32F103学习笔记 (九) 输入捕获实验

这个实验是用 TIM5 的通道 1( PA0) 来做输入捕获, 捕获 PA0 上高电平的脉宽(用 WK_UP 按键输入高电平),通过串口打印高电平脉宽时间。

初始化里边先设置上升沿为输入捕捉,进入捕捉中断后,记录TIM5_CNT的值,然后配置捕获信号为下降沿捕获,当下降沿到来时,发生捕获,并记录此时的 TIM5_CNT 值。这样,前后两次 TIM5_CNT 之差,就是高电平的脉宽,
同时 TIM5 的计数频率我们是知道的,从而可以计算出高电平脉宽的准确时间。

相应的配置步骤为:
(1)开启TIM5时钟和GPIO时钟,设置PA0为下拉输入
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能 TIM5 时钟  
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟  

(2)初始化 TIM5,设置 TIM5 ARR PSC。(3)设置TIM5 的输入比较参数,开启输入捕获。(4)使能捕获和更新中断(设置TIM5 DIER 寄存器) (5)设置中断分组,编写中断服务函数 。
  1. if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET){}//判断是否为更新中断  
  2. if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET){}//判断是否发生捕获事件  
  3. TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);//清除中断和捕获标志位  

(6)使能定时器(设置TIM5 CR1 寄存器)
  1. TIM_Cmd(TIM5,ENABLE ); //使能定时器 5  


timer.c中:
  1. //定时器 5 通道 1 输入捕获配置  
  2. TIM_ICInitTypeDef TIM5_ICInitStructure;  
  3. void TIM5_Cap_Init(u16 arr,u16 psc)  
  4. {  
  5. GPIO_InitTypeDef GPIO_InitStructure;  
  6. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  7. NVIC_InitTypeDef NVIC_InitStructure;  
  8. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //①使能 TIM5 时钟  
  9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //①使能 GPIOA 时钟  
  10. 215  
  11. //初始化 GPIOA.0 ①  
  12. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  //PA0 设置  
  13. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入  
  14. GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化 GPIOA.0  
  15. GPIO_ResetBits(GPIOA,GPIO_Pin_0);  //PA0 下拉  
  16. //②初始化 TIM5 参数  
  17. TIM_TimeBaseStructure.TIM_Period = arr;  //设定计数器自动重装值  
  18. TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器  
  19. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // TDTS = Tck_tim  
  20. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式  
  21. TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //初始化 TIMx  
  22. //③初始化 TIM5 输入捕获通道 1  
  23. TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到 TI1 上  
  24. TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  //上升沿捕获  
  25. TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上  
  26. TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //配置输入分频,不分频  
  27. TIM5_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波  
  28. TIM_ICInit(TIM5, &TIM5_ICInitStructure); //初始化 TIM5 输入捕获通道 1  
  29. //⑤初始化 NVIC 中断优先级分组  
  30. NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM3 中断  
  31. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级  
  32. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级 0 级  
  33. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //IRQ 通道被使能  
  34. NVIC_Init(&NVIC_InitStructure);   //初始化 NVIC  
  35. TIM_ITConfig( TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//④允许更新中断捕获中断  
  36. TIM_Cmd(TIM5,ENABLE );  //⑥使能定时器 5  
  37. }  
  38. u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态   
  39. u16 TIM5CH1_CAPTURE_VAL;//输入捕获值  
  40. //⑤定时器 5 中断服务程序  
  41. void TIM5_IRQHandler(void)  
  42. {  
  43. if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获  
  44. {   
  45. if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)  
  46. {   
  47. 216  
  48. if(TIM5CH1_CAPTURE_STA&0X40) //已经捕获到高电平了  
  49. {  
  50. if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了  
  51. {  
  52. TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次  
  53. TIM5CH1_CAPTURE_VAL=0XFFFF;  
  54. }else TIM5CH1_CAPTURE_STA++;  
  55. }  
  56. }  
  57. if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) //捕获 1 发生捕获事件  
  58. {  
  59. if(TIM5CH1_CAPTURE_STA&0X40)  //捕获到一个下降沿  
  60. {   
  61. TIM5CH1_CAPTURE_STA|=0X80;  //标记成功捕获到一次上升沿  
  62. TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);  
  63.  TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获  
  64. }else  //还未开始,第一次捕获上升沿  
  65. {  
  66. TIM5CH1_CAPTURE_STA=0;  //清空  
  67. TIM5CH1_CAPTURE_VAL=0;  
  68. TIM_SetCounter(TIM5,0);  
  69. TIM5CH1_CAPTURE_STA|=0X40;  //标记捕获到了上升沿  
  70.  TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获  
  71. }   
  72. }     
  73. }  
  74.  TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位  
  75. }  


其中重要的是TIM5 的中断服务函数,TIM5CH1_CAPTURE_STA,是用来记录捕获状态:


设置 TIM5_CH1 捕获上升沿,这在TIM5_Cap_Init 函数执行的时候就设置好了,然后等待上升沿中断到来, 当捕获到上升沿中断,此时如果 TIM5CH1_CAPTURE_STA 的第 6 位为 0, 则表示还没有捕获到新的上升沿, 就先把TIM5CH1_CAPTURE_STA、 TIM5CH1_CAPTURE_VAL 和 TIM5->CNT 等清零,然后再设置TIM5CH1_CAPTURE_STA 的第 6 位为 1, 标记捕获到高电平, 最后设置为下降沿捕获,等待下降沿到来。如果等待下降沿到来期间,定时器发生了溢出,就在 TIM5CH1_CAPTURE_STA里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成(虽然此时还没有捕获到下降沿)。当下降沿到来的时候,先设置 TIM5CH1_CAPTURE_STA 的第 7 位为 1,标记成功捕获一次高电平,然后读取此时的定时器值到 TIM5CH1_CAPTURE_VAL 里面,最后设置为上升沿捕获,回到初始状态。

main.c:
  1. <span style="font-size:14px;">extern u8 TIM5CH1_CAPTURE_STA; //输入捕获状态   
  2. extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值  
  3. int main(void)  
  4. {  
  5. u32 temp=0;  
  6. delay_init();   //延时函数初始化   
  7. NVIC_Configuration();  //设置 NVIC 中断分组 2  
  8. uart_init(9600);  //串口初始化波特率为 9600  
  9. LED_Init();  //LED 端口初始化  
  10. TIM3_PWM_Init(899,0); //不分频。 PWM 频率=72000/(899+1)=80Khz  
  11. TIM5_Cap_Init(0XFFFF,72-1); //以 1Mhz 的频率计数  
  12.  while(1)  
  13. {  
  14. delay_ms(10);  
  15. TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);  
  16. if(TIM_GetCapture2(TIM3)==300)  
  17. TIM_SetCompare2(TIM3,0);  
  18. if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿  
  19. {  
  20. temp=TIM5CH1_CAPTURE_STA&0X3F;  
  21. 218  
  22. temp*=65536;//溢出时间总和  
  23. temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间  
  24. printf("HIGH:%d us\r\n",temp); //打印总的高点平时间  
  25. TIM5CH1_CAPTURE_STA=0; //开启下一次捕获  
  26. }  
  27. }  
  28. }</span>  


如果用杜邦线把PB5和PA0连起来,就会看到串口助手里以固定的时间宽度输出。












本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
电机控制基础2——定时器捕获单输入脉冲原理
嵌入式单片机学习之串口接收数据实例
九九的STM32笔记(一)TIM模块定时器向上溢出 & 输出比较 (www.ourdev....
STM32高级控制定时器1学习 walkdream.com
STM32通用定时器(TIM2-5)基本用法
STM32开发板上音频播放程序的设计之二 -- nthq2004's Blog
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服