STM32 学习12 输入捕获与触摸按键

一、输入捕获介绍1.概念

输入捕获(InputCapture)是一种用于测量外部信号脉冲宽度或者频率的技术,常用于测量传感器输出、编码器信号、脉冲调制信号等。输入捕获通常通过定时器模块来实现输入捕获功能。

2.STM32F1资源

STM32F1除了基本定时器TIM6和TIM7,其它定时器都具有输入捕获功能。

3.捕获原理

捕获原理是指通过定时器模块捕获外部信号的特定事件,例如脉冲的上升沿或下降沿,以便测量脉冲宽度或频率。输入捕获时,相应的ICx检测到跳变沿,TIMx_CCRx寄存器记录TIMx_CNT计数值;下次跳变时,对TIMx_CNT值进行比较。

图示如下:



注意CNT计数的次数是N*ARR+CCR*x2N∗ARR+CCR∗x2,因为在检测周期里计数可能多次溢出,需要记录溢出次数N。
由计数效数*CNT计数周期,即捕获到信号持续时间。

二、输入捕获配置步骤1.使能时钟、设置端口模式

定时器需要的头文件在stm32f10_文件中。
下面示例使用PA0/TIM5_CH1引脚。

RCC_APB1PerihpClockCmd(RCC_APB1Periph_TIM5,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIO设置为输入拉低GPIO__Mode=GPIO_Mode_IPD;
2.初始化定时器

配置定时器的时钟源、预分频器、计数模式等。

voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);
3.设置捕获参数

开启捕获。

voidTIM_ICInit(TIM_TypeDef*TIMx,TIM_ICInitTypeDef*TIM_ICInitStrcut);typedefstruct{uint16_tTIM_Channel;//通道uint16_tTIM_ICPolarity;//捕获极性uint16_tTIM_ICSelection;//映射uint16_tTIM_ICPRescaler;//分频系数uint16_tTIM_ICFilter;//滤波器长度}TIM_ICInitTypeDef;//设置通道1TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);
4.开启捕获和定时器中断(溢出中断|更新中断)
voidTIM_ITConfig(TIM_TypeDef*TIMx,uint16_tTIM_IT,FunctionalStateNewState);//捕获通道1TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);NVIC_Init()
6.编写定时器中断服务函数
TIM5_IRQHandler
7.使能定时器
voidTIM_Cmd(TIM_TypeDef*TIMx,FunctionalStateNewState);
三、代码实现1.catch_
define__CATCH_UTILS_H__include""//定时器溢出的次数staticu8TIM5_Overflow=0;//捕获到上升沿staticu8TIM5_Capture=0;voidcatch_gpio_init(u16period,u16prescaler);voidcatch_timer_enable(void);include"catch_"defineFALLING1/***@brief捕获初始化*/voidcatch_gpio_init(u16period,u16prescaler){//GPIO初始化GPIO_InitTypeDefGPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO__Pin=GPIO_Pin_0;GPIO__Mode=GPIO_Mode_IPD;GPIO__Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);//定时器初始化TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM__Period=period;TIM__Prescaler=prescaler;TIM__ClockDivision=TIM_CKD_DIV1;TIM__CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM5,TIM_TimeBaseStructure);//输入捕获初始化TIM_ICInitTypeDefTIM_ICInitStructure;TIM__Channel=TIM_Channel_1;TIM__ICPolarity=TIM_ICPolarity_Rising;TIM__ICSelection=TIM_ICSelection_DirectTI;TIM__ICPrescaler=TIM_ICPSC_DIV1;TIM__ICFilter=0x00;TIM_ICInit(TIM5,TIM_ICInitStructure);TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);//开启捕获和定时器中断TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);NVIC_InitTypeDefNVIC_InitStructure;NVIC__IRQChannel=TIM5_IRQn;NVIC__IRQChannelPreemptionPriority=2;NVIC__IRQChannelSubPriority=3;NVIC__IRQChannelCmd=ENABLE;NVIC_Init(NVIC_InitStructure);}/***中断函数*/voidTIM5_IRQHandler(void){//如果捕获到,要翻转一下捕获方向,如果捕获到下降沿,就设置为上升沿,并计算捕获时间并输出if(TIM_GetITStatus(TIM5,TIM_IT_CC1)){if(TIM5_Capture==RISING){printf("catchrisingirq,TIM5_Capture=%d\n",TIM5_Capture);TIM5_Capture=FALLING;//关闭定时器TIM_Cmd(TIM5,DISABLE);TIM_SetCounter(TIM5,0);TIM5_Overflow=0;TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);TIM_Cmd(TIM5,ENABLE);}else{//捕获到下降沿TIM5_Capture=RISING;//计算总时间u16time=TIM_GetCapture1(TIM5);u32total_time=TIM5_Overflow*0xffff+time;printf("catchfallingirq,capturetime=%d,overflowcount=%d\n,total=%dus",time,TIM5_Overflow,total_time);TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);}TIM_ClearITPingBit(TIM5,TIM_IT_CC1);}elseif(TIM_GetITStatus(TIM5,TIM_IT_Update)){TIM5_Overflow++;TIM_ClearITPingBit(TIM5,TIM_IT_Update);}}/***@brief使能定时器*/voidcatch_timer_enable(void){TIM_Cmd(TIM5,ENABLE);}
3.
include"rcc_"include"sys_tick_"include"usart_"include"catch_"//主函数intmain(void){GPIO_Configuration();//调用GPIO配置函数//tick初始化sys_tick_init(72);led_all_off();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);USART3_Init(9600);printf("starting");//led初始化custom_led_init();inti=0;//捕获初始化catch_gpio_init(0xffff,72-1);catch_timer_enable();while(1)//无限循环{delay_ms(990);led_lightn(i);i++;if(i9){i=0;}}}
四、触摸按键捕获

我的开发板没有带触摸组件,所以本实验使用外置的触摸按键模块。


这个触摸按键在感应到触摸时,会在SIG引脚输出高电平。直接把SIG接在PA0上即可使用。
但该电路对原KEY_UP按键模块有影响,开发板按键按下的时候,PA0获取不到足够高的电平。

运行中串口输出示例

发布于 2025-02-06
169
目录

    推荐阅读