STM32单片机:外部中断和定时器中断

学习32单片机过程中使用的工具:MDK Keil5 + 正点原子精英版(STM32F103ZET6)+ STM32CubeMX + HAL开发

一、外部中断

1、提前在STM32CubeMX中配置引发外部中断的GPIO引脚,引脚的初始输出可以选择上拉输出或者下拉输出,这样这个GPIO的初始状态就是高电平或者低电平。
2、HAL库封装好的ms级延时函数HAL_Delay()是基于系统滴答定时器构建的,在外部中断/定时器中断中引用延时函数HAL_Delay()时,需要确保滴答定时器的抢占优先级高于外部中断/定时器中断的抢占优先级,这样才能使滴答定时器的中断可以嵌套入外部中断/定时器中断中。
3、外部中断不需要启动函数,中断发生方式可以选择上升沿触发、下降沿触发、上升沿/下降沿触发。当选择上升沿/下降沿触发时,按下按键并松开是触发了两次中断,这个要注意。
4、使用按键触发外部中断,比如按键的下降沿触发外部中断时,有时候按下一次按键可能进入多次中断,这是因为按键按下去是有抖动的,需要在软硬件上采取去抖动措施才能消除这种负面影响。
去抖的方法具体可见下面的博客:https://blog.csdn.net/oKuaiLeTongNian/article/details/119827828?spm=1001.2014.3001.5506

二、定时器中断

定时器中断在学习51单片机时已经了解得很清楚了,这里主要注意STM32CubeMX的配置。
① 首选选择定时器TIMx
② 搞明白这个定时器挂载在那一条总线上,该总线上的时钟频率是多少,比如APB1总线的时钟频率是72MHZ
③ 设置该定时器的预分频系数(注意有一个-1操作),使该定时器有一个属于自己的时钟频率
④ 设置该定时器的计数方式:向上计数或向下计数
⑤ 设置该定时器的计数周期

三、外部中断和定时器中断的实例

#include "main.h"
#include "tim.h"
#include "gpio.h"

//这个程序是存档的中断的设置:主要包括外部中断+定时器TIM中断;
//不进入中断的情况下:LED0(对应PB5)常亮,LED1(对应PE5)闪烁;
//外部中断控制LED0,当进入外部中断时LED0灭;定时器中断控制LED1,当进入定时器中断时,LED1常亮。
//中断说明:外部中断使用的是PE4对应按键0,上升沿/下降沿触发中断;注意按键按下再松开,是一个下降沿和一个上升沿。
//中断说明:定时器TIM中断用的是定时器TIM2,挂载在APB1总线上;其中APB1总线的频率为72MHZ,TIM2预分频系数为(72-1),计数周期为(50000-1)
//APB1总线频率是72MHZ,预分频之后定时器TIM2的时钟频率是1MHZ,那么计数一次花费1us;计数50000次就是50ms,所以定时器定时时长就是50ms。
//在中断的回调函数中引用HAL_Delay()函数时,应该使系统滴答定时器的抢占优先级高于中断的抢占优先级

void SystemClock_Config(void);
	/**************** 定义触发外部中断时的回调函数 *****************/
	void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
	{
		if (HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==GPIO_PIN_RESET)			//由按键触发外部中断时,先判断PE4的电位
		{
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);			//如果PE4为低电位,则LED0灭1s
			HAL_Delay(1000);											//优先级设置错误会出现bug
		}
		if (HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==GPIO_PIN_SET)			//反之如果PE4为高电位,则执行一个空语句
		{
		}
	}

	/**************** 定义触发定时器TIM2中断时的回调函数 *****************/
	void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)			//把"htim"这个句柄传入回调函数
	{
		static uint16_t DesignNumTIMInt = 200;							//定义一个静态变量DesignNumTIMInt									
		static uint16_t NumTIMInt = 0;									//静态变量NumTIMInt是进入中断的次数,初始化为0										
		NumTIMInt++;													//每进入一次定时器中断,这个中断次数就+1
		if (NumTIMInt==DesignNumTIMInt)									//进入200次中断之后(50ms*200=10s),让LED1常亮1s
		{
			NumTIMInt=0;											
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET);
			HAL_Delay(1000);
		}
	}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();

    HAL_TIM_Base_Start_IT(&htim2);			//开启定时器TIM2及其溢出中断;注意定时器中断需要提前开启,而外部中断不用。
  while (1)
  {
	/************* 首先实现基本功能:LED0常亮,LED1闪烁 ****************/
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);
	HAL_Delay(100);
	HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);
	HAL_Delay(100);	    
  }
}

你可能感兴趣的:(STM32单片机,单片机,stm32,嵌入式硬件)