前言:

        这段时间里,我被区区定时器给困住了很久很久,定时器竟然进不去中断!这让我从怀疑智商,到怀疑人生,再到怀疑自己。在这段时间里,我一直没能发现这个问题,直到昨天才是“守得云开见月明”,这竟然是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();初始化函数的后面,代码的排放顺序一定要注意!