前言:
这段时间里,我被区区定时器给困住了很久很久,定时器竟然进不去中断!这让我从怀疑智商,到怀疑人生,再到怀疑自己。在这段时间里,我一直没能发现这个问题,直到昨天才是“守得云开见月明”,这竟然是STM32Cubemx上的一个不起眼的小部分,这里写下这篇博客记录一下,同样也是给大家提个醒,避一下坑。
正篇开始:
首先是对GPIO的配置,蓝桥杯嵌入式的原理图如图所示
对应板子左侧的按键,从上到下依次是Reset,KEY0->PB0;KEY1->PB1;KEY2->PB2;KEY3->PA0;
GPIO有八种工作模式,这里可以根据原理图发现,管脚连接了一个VDD,只有当按键按下的时候,才会检测到低电平,平时不按下的话,就是高电平,很容易可以判断出是上拉输入。这里我们就按照图示方法配置。这里只展示了PA0的配置,其余3个管脚配置是一样的。
之后,我们开始配置我们的定时器3。
1、选择时钟源
2、 根据我们的时钟树来配置我们的PSC和ARR(分别是分频系数和预装载值)。因为我们的时钟树这里配置为80MHZ,我们的参数配置也是与80MHZ有关的,所以配置的时钟树如下所示:
3、使能TIM3的中断
4、大坑来了!其实吧,说出来大家可能不信,可能会说,区区一个Application Structure怎么会让你的定时器不好使呢?你这里选个Basic和Advanced的区别不就是文件结构不太一样吗?博主亲自试了,确实是这样,我点击了Basic,他就是好使了,我选择Advanced,他就是定时器进不去中断。至于为啥,我其实也不太懂,但事实确实让我没话说。
到了这一步,我们的STM32Cubemx的配置就完成了,接下来的活,要在Keil MDK里干了。我们打开我们的工程。新建一个interrupt.h和interrupt.c文件
interrupt.c:
#include "interrupt.h"
unsigned int TIM3_count;
struct keys key[4] = {0,0,0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
TIM3_count++;
if(TIM3_count == 1000 )
{
TIM3_count = 0;
}
if(htim->Instance == TIM3)
{
key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta == 0)
{
key[i].judge_sta = 1;
}
}break;
case 1://消抖过程
{
if(key[i].key_sta == 0)
{
key[i].judge_sta = 2;
key[i].single_flag = 1;
}
else
{
key[i].judge_sta = 0;
}
}break;
case 2:
{
if(key[i].key_sta == 1)
{
key[i].judge_sta = 0;
}
}break;
}
}
}
}
}
interrupt.h:
#ifndef __INTERRUPT_H
#define __INTERRUPT_H
#include "main.h"
#include "stdbool.h" //因为只需要表示两个状态所以用bool类型,节省空间
struct keys
{
unsigned char judge_sta; //运行状态
bool key_sta; //按键状态
bool single_flag; //短按键触发标志位
};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif
在main.c里添加开启中断的函数:
HAL_TIM_Base_Start_IT(&htim3);
同时,我们写好我们的按键服务函数:
if(key[0].single_flag == 1)
{
sprintf(text,"key0down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[0].single_flag = 0;
}
else if(key[1].single_flag == 1)
{
sprintf(text,"key1down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[1].single_flag = 0;
}
else if(key[2].single_flag == 1)
{
sprintf(text,"key2down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[2].single_flag = 0;
}
else if(key[3].single_flag == 1)
{
sprintf(text,"key3down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[3].single_flag = 0;
}
补发:
在这里我按照自己的博客去做了一次,只不过这次换成了TIM4,发现又出现了bug,而这个bug是源于代码的位置没有放对,在这里记录一下,也是为了给大家提一下醒。
这里一定要注意,HAL_TIM_Base_Start_IT(&htim4);一定要放在MX_TIM4_Init();初始化函数的后面,代码的排放顺序一定要注意!