历史上的今天
返回首页

历史上的今天

今天是:2025年04月15日(星期二)

正在发生

2018年04月15日 | STM32的输入捕获

2018-04-15 来源:eefocus

实验目的:

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


实验步骤:





实验程序:


  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 << 8; //设置分组  

  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.按键那块,处理不是很好,有时会一连打出好几串数字;

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


推荐阅读

史海拾趣

DC Components公司的发展小趣事

随着电子行业的快速发展,技术创新成为企业发展的重要动力。DC Components公司紧跟行业趋势,积极引进先进技术,加大研发投入,不断推出具有竞争力的新产品。这些新产品不仅满足了市场的多样化需求,还为公司的发展注入了新的活力。

Dover Corporation公司的发展小趣事

Dover Corporation自上市以来,一直保持着持续盈利和向投资者发放红利的记录。公司凭借其强大的业务能力和稳健的财务状况,赢得了投资者的信任和支持。这一成绩的取得不仅彰显了Dover在业务运营方面的实力,也为其未来的发展奠定了坚实的基础。

请注意,以上故事框架仅为概述性质,具体细节和数据可能需要根据Dover Corporation的实际情况进行调整和补充。

Harwin公司的发展小趣事

Harbour Industries始终将产品质量视为企业的生命线。为了确保产品质量达到国际一流水平,公司不断引入先进的质量管理体系。1990年代末期,Harbour成功通过了ISO9001产品质量认证。这一认证不仅标志着公司的质量管理体系已经达到了国际标准,也为其在全球市场中的竞争提供了有力保障。此外,Harbour还实行了“过程管理”来确定和控制产品成本,进一步提升了其市场竞争力和盈利能力。

Globaltech Semiconductor Co Ltd公司的发展小趣事

为了保持技术领先地位,Globaltech持续加大研发投入,建立了先进的研发中心和测试实验室。公司不断引进国内外顶尖的研发人才,并与多所知名高校和研究机构建立产学研合作关系。这些努力使得Globaltech在电源管理IC领域取得了多项技术突破,并成功拓展了产品线,涵盖了ESD保护器件、MOSFET等多个领域。这些新产品不仅丰富了公司的产品线,也为客户提供了更加全面的解决方案。

华大北斗(Allystar)公司的发展小趣事

为了保持技术领先地位,Globaltech持续加大研发投入,建立了先进的研发中心和测试实验室。公司不断引进国内外顶尖的研发人才,并与多所知名高校和研究机构建立产学研合作关系。这些努力使得Globaltech在电源管理IC领域取得了多项技术突破,并成功拓展了产品线,涵盖了ESD保护器件、MOSFET等多个领域。这些新产品不仅丰富了公司的产品线,也为客户提供了更加全面的解决方案。

ABCircuits公司的发展小趣事

在电子行业中,产品质量是企业的生命线。ABCircuits深知这一点,因此从成立之初就建立了严格的质量管理体系。公司注重从原材料采购到生产制造的每一个环节的质量控制,确保每一件产品都符合高标准的品质要求。这种对品质的坚持让ABCircuits赢得了客户的信赖和口碑,使其在市场中脱颖而出。

问答坊 | AI 解惑

差分探头你想做吗?

差分探头是可以做出来的....... 进口的差分探头如P5205,市价高达五位数,目前国内还没有一家能完全仿制出来,杭州有一家做出的产品仍末达到同类产品的技术要求,如深圳有一家也想试制,具我所知,花了近二年的时间,投入近二十多万,至今产品仍达不到同类 ...…

查看全部问答>

关于三相整流桥

请教个问题:使用3只整流管和3只可控硅制作的开路式调压器整流器,为什么在高频率下(一般超过1.2K),可控硅就呈现二极管工作状态,不能关断,为什么?请高手指教。谢谢…

查看全部问答>

求助:需要隐蔽的无线监控?

最近要做一个仓库的活儿, 要求摄像机点位隐蔽,还不可以布线, 请大家支招~~…

查看全部问答>

单片机接口设计书程序

单片机接口设计书程序(各种接口实用子程序) 目录 第1章 单片机I/O接口的扩展 111 1.1 单片机应用系统 2 1.1.1 单片机系统概述 2 1.1.2 单片机系统中的功能模块 3 1.2 单片机I/O接口 4 1.2.1 I/O接口功能 5 1.2.2 接口的控制方式 5 1.2.3 I ...…

查看全部问答>

无线网络的一个奇怪问题

在同样的地点,有两台笔记本,其中一台可以接收到无线网络信号,并通过他上网,但是另外一台就很难接收到信号,请问有什么办法解决?…

查看全部问答>

6410加载文件系统后SD卡无法识别

参考6410开发板,能SD卡烧写Uboot和内核,但是加载文件系统后无法识别SD卡,USB1.1可以识别。问题在哪,请高手指点…

查看全部问答>

大家看下,这个程序是不是有点小错误?

我是看天狼星视频的,下面的也是它的代码 /**************ds1302写入一个字节函数 从低位开始写************/void write_ds1302_byte(uchar date){        uchar i;       for( ...…

查看全部问答>

怎么删除430密码

怎么删除430密码…

查看全部问答>

mp3(SD卡+VS1003+TFT)

最近在弄的mp3,文件系统用的是ZNFAT32,可读取1G到16G的SD卡里的mp3数据发送给VS播放,TFT屏显示,TFT屏用的是16位模式显示,导致单片机端口不够用,所以我采用的是双机,也就是一片机子负责歌曲播放,另一块单片机负责显示歌词或歌曲列表,两块单 ...…

查看全部问答>

[原创文章] Nucleo心得+“测试-使用-若干集之三 STM32CubeMX+MDK来做项目”

本帖最后由 damiaa 于 2014-10-1 22:52 编辑 接下来还是搞我最喜欢的MDK,用STM32CUBEMX这个工具生成初始化代码。 明天继续,今天有些晚了。 1,STM32L053X 资料: 2,IO口方面的事情 STM32L053R8T6的IO口如下,共64个 PA 16,PB 16, ...…

查看全部问答>