×
单片机 > 单片机程序设计 > 详情

STM32的输入捕获

发布时间:2020-09-01 发布时间:
|

实验目的:

在串口调试助手上打印出按键按下的时间


实验步骤:





实验程序:


  1. /*******************************timer.c********************************/  

  2. #include "sys.h"  

  3. #include "stm32f4xx.h"  

  4.   

  5.   

  6. extern u8 TIM5CHA1_CAPTURE_STA;  

  7. extern u16  TIM5CHA1_CAPTURE_VAL;  

  8.   

  9.   

  10. /* 

  11. 本示例的作用就是, 

  12. 当按键按下时,每次输入捕获的时间差, 

  13. 然后从串口调试助手中打印出其时间差; 

  14. */  

  15.   

  16.   

  17. /* 

  18. 关于输入捕获的操作可参考寄存器版的步骤 

  19. */  

  20.   

  21.   

  22. /* 

  23. 定时器输入捕获的初始化函数: 

  24. 主要是关于寄存器的相关配置 

  25. */  

  26.   

  27.   

  28. /*初始化定时器5为输入捕获*/  

  29. void TIM5_Init(void){  

  30.       

  31.     /************************* 

  32.     定时器输入捕获的设置:  

  33.     *************************/  

  34.       

  35.     /*将按键KEY_UP复用*/  

  36.     /*1.使能GPIO端口时钟*/  

  37.     RCC->AHB1ENR |= 1;  

  38.     /*这里还需要将其配置成下拉, 

  39.     因为在输入捕获中,将通过上升沿来触发; 

  40.     */  

  41.     GPIOA->PUPDR |= 0X2;  

  42.       

  43.     /*2.使能复用外设时钟*/  

  44.     RCC->APB1ENR |= 1<<3;  

  45.       

  46.     /*3.端口模式配置为复用功能*/  

  47.     GPIOA->MODER |= 0X2;  

  48.       

  49.     /*4.配置GPIOx_AFRL或者GPIOx_AFRH寄存器, 

  50.     将IO连接到所需的复用外设*/  

  51.     GPIOA->AFR[0] |= 0X2;  

  52.       

  53.       

  54.       

  55.     /*设置定时器5的输入捕获*/  

  56.       

  57.     //设置TIM5的分频和自动重装  

  58.     TIM5->PSC = 84-1;  

  59.     TIM5->ARR = 0XFFFF-1;   //芯片手册上写着是16位,  

  60.                               

  61.     //设置滤波/映射/分频  

  62.     TIM5->CCMR1 |= 0X1;  

  63.       

  64.       

  65.     //设置上升沿触发并使能捕获  

  66.     TIM5->CCER |= 0X1;  

  67.       

  68.     //使能更新中断和使能捕获中断  

  69.     TIM5->DIER |= 0X3;  

  70.       

  71.     //使能计数器  

  72.     TIM5->CR1 |= 1;  

  73.       

  74.       

  75.     //设置中断优先级  

  76.     SCB->AIRCR |= 0x5 <

  77.     NVIC->IP[50] |= 0; //设置优先级,具体可分析MY_NVIC_Init()函数;  

  78.       

  79.     //只要涉及中断,最后一定记得使能中断;  

  80.     //若不使能,则中断不会发生  

  81.     NVIC->ISER[1] |= 1<<18;  //使能中断;  

  82.       

  83. }  

  84.   

  85.   

  86.   

  87. /*每次在按键按下时,输入捕获按键, 

  88. 然后每产生两次中断,就在在中断里边 

  89. 算出两次捕获之间的时间差; 

  90. */  

  91. void TIM5_IRQHandler(void){  

  92.       

  93.     /* 

  94.     中断处理函数: 

  95.     */  

  96.       

  97.       

  98.     if((TIM5CHA1_CAPTURE_STA & 0x80) != 0x80){  //说明一次完整的输入捕获还没有结束;  

  99.           

  100.           

  101.           

  102.         if((TIM5->SR & 0X1) == 0X1){  //说明是溢出标志发生  

  103.               

  104.               

  105.             if((TIM5CHA1_CAPTURE_STA & 0x40) == 0x40){  //只有捕获到高电平之后,  

  106.                                                         //我们才累计计数计数器的值  

  107.                 if((TIM5CHA1_CAPTURE_STA & 0x3f)==0x3f){  //说明能累计的计数器已满;  

  108.                                                         //在这里,高电平持续的时间最多为4s  

  109.                     TIM5CHA1_CAPTURE_STA |= 0x80;  

  110.                     TIM5CHA1_CAPTURE_VAL = 0xffff;  

  111.                       

  112.                       

  113.                 }else{  

  114.                   

  115.                     TIM5CHA1_CAPTURE_STA++;  

  116.                 }  

  117.                   

  118.                   

  119.             }  

  120.               

  121.         }  

  122.         if((TIM5->SR & 0X2) == 0X2){  //说明上升沿或下降沿已捕获  

  123.               

  124.               

  125.             if((TIM5CHA1_CAPTURE_STA & 0x40) == 0x40){   //说明下降沿已触发  

  126.                   

  127.                 TIM5CHA1_CAPTURE_STA |= 0x80 ; //说明上升沿和下降沿一个周期的捕获已完成 ;  

  128.                 TIM5CHA1_CAPTURE_VAL = TIM5->CCR1;//保存发生下降沿触发时计数器的值;  

  129.           

  130.                 //设置上升沿触发并使能捕获  

  131.                 TIM5->CCER &= ~(1<<1);  

  132.                   

  133.             }else{     //说明上升沿已捕获  

  134.                   

  135.                 //禁止定时器5的计数器  

  136.                 TIM5->CR1 &= ~(1);  

  137.                   

  138.                 //让计数器的值为0,以便计算从0到下一次下降沿捕获的值之间的计算;  

  139.                 TIM5->CNT = 0;  

  140.                   

  141.                 //设置输入捕获为下降沿触发  

  142.                 TIM5->CCER &= ~(0XF);  

  143.                 TIM5->CCER |= 0X3;  

  144.                   

  145.                 //初始化要计数的值;  

  146.                 TIM5CHA1_CAPTURE_STA = 0;  

  147.                 TIM5CHA1_CAPTURE_STA |= 0X40;  

  148.                 TIM5CHA1_CAPTURE_VAL = 0;  

  149.                   

  150.                 //使能计数器  

  151.                 TIM5->CR1 |= 1;  

  152.               

  153.             }  

  154.               

  155.         }  

  156.           

  157.     }  

  158.       

  159.     /* 

  160.     在中断里边最后记得清中断标志: 

  161.     */  

  162.     TIM5->SR &= ~(0x3);  

  163. }   

  164. /*******************************timer.h*********************************/  

  165. #ifndef _EXTI_H  

  166. #define _EXTI_H  

  167.   

  168.   

  169. void TIM5_Init(void);  

  170.   

  171.   

  172. #endif  

  173. /*******************************test.c***********************************/  

  174. #include "sys.h"  

  175. #include "delay.h"  

  176. #include "beep.h"  

  177. #include "exti.h"  

  178. #include "led.h"  

  179. #include "uart.h"  

  180. #include "usart.h"  

  181.   

  182.   

  183.   

  184. u8 TIM5CHA1_CAPTURE_STA;  

  185. u32  TIM5CHA1_CAPTURE_VAL;  

  186.   

  187.   

  188. int main(void){  

  189.       

  190.     u8 i = 0;  

  191.     long long  temp = 0;  //这里的值比较大,所以选择long long  

  192.       

  193.     Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz    

  194.     delay_init(168);        //初始化延时函数  

  195.     LED_Init();  

  196.     Beep_Init();  

  197.     TIM5_Init();  

  198.     UART_Init();  

  199.       

  200.       

  201.     while(1){  

  202.           

  203.         PFout(9) = 0;  

  204.         delay_ms(500);  

  205.         PFout(9) = 1;  

  206.         delay_ms(500);  

  207.           

  208.         if((TIM5CHA1_CAPTURE_STA & 0x80) == 0x80){  //若一个完整的捕获周期(上升沿和下降沿)  

  209.   

  210.   

  211.             i = TIM5CHA1_CAPTURE_STA & 0x3f;  

  212.             printf("TIM5:%d\r\n",i);  

  213.             //计算累计的时间(高电平到低电平的之间的时间差)    

  214.             temp = (TIM5CHA1_CAPTURE_STA & 0x3f)*0xffff;  

  215.             temp += TIM5CHA1_CAPTURE_VAL;  

  216.   

  217.               

  218.             printf("temp:%lld us\r\n",temp);  //思考printf()函数是如何做的;  

  219.                   

  220.                 //重新初始化  

  221.                 TIM5CHA1_CAPTURE_STA = 0;  

  222.                 TIM5CHA1_CAPTURE_VAL = 0;  

  223.   

  224.         }  

  225.               

  226.     }  

  227. }  





实验分析:

1.定时器的框图及输入捕获框图的放大版



注:通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,

将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。


2.输入捕获的工作流程分析:

<1>


<2>


<3>


<4>


<5>



3.中断处理函数部分的提示



注意事项:

1.只要涉及到中断,在最后一定都要记得使能中断

2.按键那块,处理不是很好,有时会一连打出好几串数字;

更准确的说是按键有时会有些抖动,就相当于按了好几下,但没有滤掉波段较小的那一部分;





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项