800元五合一建站,上海企业排行榜,做酒店网站,邢台企业做网站找谁STM32 学习12 输入捕获与触摸按键 一、输入捕获介绍1. 概念2. STM32F1 资源3. 捕获原理 二、输入捕获配置步骤1. 使能时钟、设置端口模式2. 初始化定时器3. 设置捕获参数4. 开启捕获和定时器中断#xff08;溢出中断|更新中断#xff09;6. 编写定时器中断服务函数7. 使能定时… STM32 学习12 输入捕获与触摸按键 一、输入捕获介绍1. 概念2. STM32F1 资源3. 捕获原理 二、输入捕获配置步骤1. 使能时钟、设置端口模式2. 初始化定时器3. 设置捕获参数4. 开启捕获和定时器中断溢出中断|更新中断6. 编写定时器中断服务函数7. 使能定时器 三、代码实现1. catch_utils.h2. catch_utils.c3. main.c 四、触摸按键捕获 一、输入捕获介绍
1. 概念
输入捕获Input Capture是一种用于测量外部信号脉冲宽度或者频率的技术常用于测量传感器输出、编码器信号、脉冲调制信号等。输入捕获通常通过定时器模块来实现输入捕获功能。
2. STM32F1 资源
STM32F1除了基本定时器TIM6和TIM7其它定时器都具有输入捕获功能。
3. 捕获原理
捕获原理是指通过定时器模块捕获外部信号的特定事件例如脉冲的上升沿或下降沿以便测量脉冲宽度或频率。 输入捕获时相应的ICx检测到跳变沿TIMx_CCRx寄存器记录TIMx_CNT计数值下次跳变时对TIMx_CNT值进行比较。
图示如下 注意CNT计数的次数是 N ∗ A R R C C R ∗ x 2 N*ARRCCR*x2 N∗ARRCCR∗x2因为在检测周期里计数可能多次溢出需要记录溢出次数N。 由计数效数*CNT计数周期即捕获到信号持续时间。
二、输入捕获配置步骤
1. 使能时钟、设置端口模式
定时器需要的头文件在 stm32f10_tim.h 文件中。 下面示例使用 PA0/TIM5_CH1 引脚。
RCC_APB1PerihpClockCmd(RCC_APB1Periph_TIM5,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
// GPIO 设置为输入拉低
GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPD;2. 初始化定时器
配置定时器的时钟源、预分频器、计数模式等。
void TIM_TimeBaseInit(TIM_TypeDef *TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);3. 设置捕获参数
开启捕获。
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStrcut);typedef struct{uint16_t TIM_Channel; // 通道uint16_t TIM_ICPolarity; // 捕获极性uint16_t TIM_ICSelection; // 映射uint16_t TIM_ICPRescaler; // 分频系数uint16_t TIM_ICFilter; // 滤波器长度
} TIM_ICInitTypeDef;// 设置通道1
TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);4. 开启捕获和定时器中断溢出中断|更新中断
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
// 捕获通道1
TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1,ENABLE);NVIC_Init()6. 编写定时器中断服务函数
TIM5_IRQHandler7. 使能定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);三、代码实现
1. catch_utils.h
#ifndef __CATCH_UTILS_H__
#define __CATCH_UTILS_H__
#include stm32f10x.h
#include stdio.h// 定时器溢出的次数
static u8 TIM5_Overflow 0;
// 捕获到上升沿
static u8 TIM5_Capture 0;
void catch_gpio_init(u16 period, u16 prescaler);
void catch_timer_enable(void);
#endif
2. catch_utils.c
#include catch_utils.h#define RISING 0
#define FALLING 1/*** brief 捕获初始化
*/
void catch_gpio_init(u16 period, u16 prescaler)
{// GPIO 初始化GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPD;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);// 定时器初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period period;TIM_TimeBaseStructure.TIM_Prescaler prescaler;TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInit(TIM5, TIM_TimeBaseStructure);// 输入捕获初始化TIM_ICInitTypeDef TIM_ICInitStructure;TIM_ICInitStructure.TIM_Channel TIM_Channel_1;TIM_ICInitStructure.TIM_ICPolarity TIM_ICPolarity_Rising;TIM_ICInitStructure.TIM_ICSelection TIM_ICSelection_DirectTI;TIM_ICInitStructure.TIM_ICPrescaler TIM_ICPSC_DIV1;TIM_ICInitStructure.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_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel TIM5_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority 3;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStructure);
}/*** 中断函数
*/
void TIM5_IRQHandler(void)
{// 如果捕获到要翻转一下捕获方向如果捕获到下降沿就设置为上升沿并计算捕获时间并输出if (TIM_GetITStatus(TIM5, TIM_IT_CC1)){if (TIM5_Capture RISING){printf(catch rising irq, 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;// 计算 总时间u16 time TIM_GetCapture1(TIM5);u32 total_time TIM5_Overflow * 0xffff time;printf(catch falling irq, capture time %d, overflow count %d \n, total%dus, time, TIM5_Overflow, total_time);TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);}TIM_ClearITPendingBit(TIM5, TIM_IT_CC1);}else if(TIM_GetITStatus(TIM5, TIM_IT_Update)){TIM5_Overflow;TIM_ClearITPendingBit(TIM5, TIM_IT_Update);}
}
/*** brief 使能定时器
*/
void catch_timer_enable(void)
{TIM_Cmd(TIM5, ENABLE);
}
3. main.c
#include gpio_utils.h
#include rcc_utils.h
#include stm32f10x.h
#include sys_tick_utils.h
#include led_utils.h
#include usart_utils.h
#include stdio.h
#include catch_utils.h// 主函数
int main(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();int i 0;// 捕获初始化catch_gpio_init(0xffff, 72 - 1);catch_timer_enable();while (1) // 无限循环{delay_ms(990);led_lightn(i);i;if(i9){i0;}}
}
四、触摸按键捕获
我的开发板没有带触摸组件所以本实验使用外置的触摸按键模块。 这个触摸按键在感应到触摸时会在SIG引脚输出高电平。 直接把SIG接在 PA0 上即可使用。 但该电路对原KEY_UP按键模块有影响开发板按键按下的时候PA0 获取不到足够高的电平。
运行中串口输出示例