stm32串口助手打印按键按下时间长短的stm32cubemx_HAL库配置过程

之前有人问了关于检测按键按下时间长短的问题,这里记录一种解决的办法

思路:通过开启按键GPIO的双边沿中断,和TIM1计数来记录按键按下的时间

现在我们来实现一下!!!
对了如果不想积分下载我博客园最下方有网盘链接
https://www.cnblogs.com/hjf-log/p/12542474.html

1、打开MX选择一款IC,这里我用的开发板是stm32f103vet6
在这里插入图片描述

2、在MX中配置SW模式下载
在这里插入图片描述
3、配置外部高速晶振,低速的就是32.768k了RTC用的,这里用不上就不开了
在这里插入图片描述
4、配置好上面必要的步骤后,来看看我们按钮原理图和接到了哪个IO口
在这里插入图片描述
在这里插入图片描述

5、上图一眼就能看出是接到了PE2,而且不按下默认已经和GND连接了,这个也方便我们之后不用内部下拉,那么把PE2配置成中断吧

在这里插入图片描述

6、那么配置PE2要选择双边沿中断,如下图配置
在这里插入图片描述

7、其他的就不用配置成内部上拉或者下拉了
在这里插入图片描述

8、把GPIO的中断打开,顺便把中断降级,别和其他中断冲突了
在这里插入图片描述
在这里插入图片描述
9、配置一下usart1设置成异步
在这里插入图片描述
10、我们先别急配置TIM1先去配置一下时钟树,我们用的8M晶振倍频为72M,这里记住APB2的晶振是72M,我们TIM1用的是APB2
在这里插入图片描述

11、现在我们回去配置TIM1,打开TIM1的时钟
在这里插入图片描述
12、接下来配置TIM1的预分频值和重装载值
这里很重要需要解释一下

我们的晶振是72M也就是一秒记72 00 0000次,72 00 0000Hz

Prescaler预分频值设置7200-1是因为预分频值从0开始

我们把72M除以预分频值7200就是我们定时器速度,速度变为了一秒记10000次

Counter Period重装载值设置为10000,也就是定时器从0开始记了10000次以后就又回归从0开始计算到10000一直循环

我们定时器的速度为1秒记10000次,重装载值也刚好是10000,那么记一次重装载要的时间就是1秒,那么速度刚好是1Hz

比如我们设置重装载值为1000,定时器速度是10000Hz,记一次重装载值的速度只要0.1秒也是10Hz
定时器的10000除以重装载的1000也就是10,就是定时器配置成了10Hz

在这里插入图片描述

13、我们配置好后顺便打开定时器的中断,因为不知道是哪个我们先把两个都打开,之后写完代码在来看看是哪个有效
在这里插入图片描述

14、也要给TIM1的中断降级避免冲突
在这里插入图片描述

15、设置好这些之后我们配置下工程的名称,路径和开发工具在这里插入图片描述

16、把这个打钩代表生成单独的配置文件,不用全部塞在main.c比较好看
在这里插入图片描述

17、我们要先测试一下printf能不能正常打印程序,这里之前已经写过博客,只复制链接不重复介绍了https://www.cnblogs.com/hjf-log/p/12522796.html

18、我们到中断函数中可以看到我们配置的中断函数
在这里插入图片描述

19、我们程序进入中断都会执行对应的callback函数也就是回调函数中,我们进入中断函数就可以看到
在这里插入图片描述

20、我们将callback函数复制到main.c的保护区测试一下,不是main里面

这个效果是按键按下到释放,一共打印2次,因为我们之前配置的是双边沿中断,按下低变高是上升沿,释放是高变低下降沿,打印2次没错,这里就不截图串口助手了
在这里插入图片描述

21、因为我们要使用TIM1定时器,定时器有个初始化代码要放在main中我们可以在下图中找到
在这里插入图片描述

22、把初始化TIM1定时器放在这里在这里插入图片描述

23、进入定时器中断也一个callback函数,我们也复制到main.c中,就是下图这个
在这里插入图片描述

24、复制到main.c我们写一段代码测试一下,效果是一秒打印一次test2
在这里插入图片描述

25、我们现在就可以写我们要的功能了,先初始三个函数
在这里插入图片描述

26、修改GPIO中断callback里面的代码,下面也会贴出
在这里插入图片描述

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_2)
    {
        if(i == 0)
        {
            state = 1;
            i=1;
            printf("state:1\r\n");
        }
        else if(i == 1)
        {
            state = 0;
            i = 0;
            printf("按下按键的秒数:%0.2f\r\n",seconds/10);
            seconds = 0;
            printf("state:0\r\n");
        }
    }
}


27、修改TIM1的中断的callback代码
在这里插入图片描述

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM1)
    {
        if(state == 1)
        {
            seconds++;
        }
    }
}

28、将代码烧入IC中,然后按下按键可以看到串口助手效果

打印state:1表示按下,然后放开按键会打印按下的秒数和state:0
在这里插入图片描述

29、这里只精确到了个位的秒数,怎么修改按下的精度呢

我们接下来说一下如何把精度修改为0.1秒

回到MX中,将重装载值修改为1000,就和我们上面说的一样现在定时器为10Hz

原本我们的定时器速度是1Hz,一秒记一次,我们的定时器中断的效果就是每记一次seconds数加1

现在把速度改为10Hz,记一次时间是0.1s,记一次seconds+1那么seconds记到的数单位就是0.1秒

因为原本的seconds定义成了int,之后要修改为float

记10次就seconds加到了10,也就是1秒,所以seconds除以10才是秒数嘛

printf(“按下按键的秒数:%0.2f\r\n”,seconds/10);

我们看看效果
在这里插入图片描述

30、好吧就记录到这里,还有在上面关于开启了两个tim1中断的问题我们来看看是哪个在起作用
在这里插入图片描述

哟注释掉了第一组TIM1_BRK串口助手还能正常打印数据说明这个没用上

我们回到MX关掉中断在重新生成一遍工程就行了
在这里插入图片描述

到此为止啦各位大佬们点个赞吧,需要工程的在博客园有网盘链接,同时上传优快云在评论区放链接

<think>好的,我现在需要帮助用户了解如何使用STM32的定时器输入捕获功能来计算按键按下的时间。用户可能是一位嵌入式开发者,正在学习STM32的外设应用,特别是定时器部分。他们可能已经有一定的STM32基础,但对输入捕获的具体实现不太熟悉。 首先,我需要回顾输入捕获的基本原理。输入捕获用于测量信号的边沿时间间隔,比如按键按下和释放的时间。当检测到边沿时,定时器的当前计数值会被记录到捕获寄存器中,从而计算出时间差。用户的问题是如何将此应用于按键时间检测,可能需要示例代码和配置步骤。 接下来,我需要考虑如何配置STM32CubeMX。包括选择定时器、配置输入捕获通道、设置预分频器和自动重载值。预分频器影响定时器的计数频率,自动重载值决定最大计数周期。例如,如果系统时钟是84MHz,预分频器设为83,那么计数频率是1MHz,每个计数代表1微秒。自动重载值设为0xFFFF,这样定时器可以计数到65535微秒,即65.535毫秒,超过这个时间需要考虑溢出。 然后,考虑按键的连接方式。按键通常连接到GPIO,这里需要配置为输入模式,并启用中断。但使用输入捕获的话,可能需要将按键连接到定时器的输入捕获通道对应的引脚,比如TIM2_CH1。这样,按键的电平变化会触发捕获事件。 在代码部分,需要编写中断处理函数,处理捕获事件和溢出。当按键按下(下降沿)时,记录第一个捕获值;释放时(上升沿)记录第二个捕获值。两者的差值乘以计数周期就是按下时间。同时,要考虑定时器溢出的次数,否则长时间按下会导致计算错误。 参考用户提供的引用内容,特别是引用[3]中的示例代码,可能需要类似的结构,但需要调整为按键检测。引用[4]提到输入捕获预分频器,这里可能设置为不分频,每次边沿都捕获。 另外,用户可能对如何计算时间有疑问。例如,如果预分频器设置为83,定时器时钟为1MHz,每次计数是1us。时间计算为(capture2 - capture1) * 1us + overflow_count * 65535us。需要注意的是,当capture2小于capture1时,说明发生了溢出,需要加上65535。 最后,示例代码需要包括初始化和中断处理。在HAL中,输入捕获的中断回调函数是HAL_TIM_IC_CaptureCallback,需要在此函数中处理边沿变化,并计算时间。同时,溢出中断需要单独处理,在TIM的全局中断服务函数中增加溢出计数。 可能用户的问题还包括如何处理消抖,这可能需要在软件中增加去抖动逻辑,比如在捕获后延迟检测,或者在中断中多次采样确认状态。但示例代码可能不包含这部分,需要用户自行添加。 总结步骤:配置CubeMX,初始化定时器和输入捕获,编写中断处理函数,计算时间差,处理溢出。确保代码能够正确捕获上升沿和下降沿,并累计溢出次数以准确计算长时间按下。</think>### STM32定时器输入捕获计算按键时间示例 #### 1. 原理说明 输入捕获通过记录信号边沿触发时的定时器计数值,计算时间间隔。按键按下(下降沿)和释放(上升沿)时分别触发捕获,时间差即为按键按下的持续时间[^1]。定时器溢出时需记录溢出次数以处理长时间按下[^3]。 #### 2. CubeMX配置步骤 1. **选择定时器**(如TIM2) - 时钟源:内部时钟 - 通道配置:输入捕获模式(对应按键引脚,如PA0对应TIM2_CH1) 2. **参数配置** - Prescaler(预分频器):设为83(若主频84MHz,则分频后为1MHz,1计数=1μs)[^4] - Counter Period(自动重载值):65535(0xFFFF) - 输入捕获极性:先配置为下降沿触发(检测按键按下) 3. **启用中断** - 勾选`TIM2全局中断`和`输入捕获中断` #### 3. 代码实现(HAL) ```c // 变量定义 volatile uint32_t capture1 = 0, capture2 = 0; volatile uint16_t overflow_count = 0; volatile uint8_t edge_flag = 0; // 0:等待下降沿 1:等待上升沿 // 定时器溢出中断处理 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { overflow_count++; // 溢出次数+1 } } // 输入捕获中断回调 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if (edge_flag == 0) { // 捕获下降沿(按键按下) capture1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改为上升沿触发 edge_flag = 1; overflow_count = 0; // 重置溢出计数 } else { // 捕获上升沿(按键释放) capture2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改回下降沿 edge_flag = 0; // 计算时间(单位:μs) uint32_t time_diff = (capture2 > capture1) ? (capture2 - capture1) : (0xFFFF - capture1 + capture2); time_diff += overflow_count * 65536; // 溢出补偿 printf("按键按下时间: %lu μs\n", time_diff); } } } // 主函数初始化 int main(void) { HAL_Init(); MX_TIM2_Init(); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动捕获和中断 HAL_TIM_Base_Start_IT(&htim2); // 启动定时器溢出中断 while (1) { /* 主循环 */ } } ``` #### 4. 关键点说明 1. **消抖处理**:可添加软件延时(如10ms)过滤抖动[^3] 2. **长按检测**:若按键持续按下超过65.535ms,溢出计数器会累加 3. **引脚配置**:需确保按键连接到TIM2_CH1对应引脚(如PA0) #### 5. 优化建议 - 使用`HAL_Delay()`或硬件消抖电路减少抖动干扰 - 增加临界区保护(如关闭中断)防止变量访问冲突 - 通过DMA传输捕获值提升效率(适合高频信号)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值