STM32单片机中断及其应用

STM32单片机中断及其应用

  • 中断概述
  • 外部中断配置
  • CubeMX相关配置及实现
  • 固件库相关程序配置及其实现

CubeMX新建工程,LED的IO口配置略,详细配置请参考:
STM32 CubeMX新建工程+GPIO的研究

中断概述

  • 什么是中断?
      中断是指计算机程序运行过程中,出现某些意外情况需要处理时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行
  • 什么是EXTI?
      外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
    STM32单片机中断及其应用_第1张图片
      EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。
      产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
  • 什么是优先级?
     1. 多个意外事情需要处理时,不同时间的优先程序
     2. 先判断抢占优先级,数字越小,优先级越高;
     3. 若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高;
     抢占优先级和响应优先级的区别:
      1. 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
      2. 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
      3. 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
      4. 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行
  • 什么是优先级分组?
      Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
      第0组:所有4位用于指定响应优先级
      第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
      第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
      第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
      第4组:所有4位用于指定抢占式优先级
    STM32单片机中断及其应用_第2张图片
  • 什么是中断服务程序
      每个中断源都有对应的处理程序,这个处理程序称为中断服务程序

外部中断配置

  • 配置相关的RCC时钟及复用
  • 初始化用来中断的IO口
  • 初始化EXTI
  • 配置NVIC(中断优先级)
  • 编写中断服务函数

CubeMX相关配置及实现

  • 时钟配置

    1. 采用外部高速时钟
    2. 时钟树配置
      STM32单片机中断及其应用_第3张图片
  • 初始化EXTI及IO口

    1. EXTI及IO口初始化
      STM32单片机中断及其应用_第4张图片
      2.相关参数配置
      STM32单片机中断及其应用_第5张图片
  • 配置NVIC中断优先级
    STM32单片机中断及其应用_第6张图片
     STM32默认使用的规则是 NVIC_PriorityGroup_0

  • 编写中断服务函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin)
	{
		case KEY1_Pin: HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); break;
		case KEY2_Pin: HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin); break;
	}
}

固件库相关程序配置及其实现

  • 初始化相关的RCC时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能APB2上挂载的GPIOA端口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	//使能复用功能时钟
  • 初始化用来中断的IO口
	GPIO_InitTypeDef GPIO_InitStructure;	//GPIO结构体变量定义
	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;		//引脚
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;	//上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度
	
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化
  • 初始化EXTI
	EXTI_InitTypeDef EXTI_InitStructure;					//EXTI结构体变量定义
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;				//触发线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;				//使能
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		//外部中断
	EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Falling;	//下降沿触发
	
	EXTI_Init(&EXTI_InitStructure);							//初始化EXTI
  • 配置NVIC(中断优先级)
	NVIC_InitTypeDef NVIC_InitStructure;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//外部中断源配置
	
	// KEY NVIC中断优先级配置 
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
  • exti初始化函数定义
void exti_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	//IO口结构体变量
	EXTI_InitTypeDef EXTI_InitStructure;	//EXTI结构体变量定义
	NVIC_InitTypeDef NVIC1_InitStructure;	//KEY1 NVIC 结构体定义
	NVIC_InitTypeDef NVIC2_InitStructure;	//KEY2 NVIC 结构体定义
	
	//时钟相关配置
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//初始化GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);			//使能复用功能时钟
	
	//中断引脚IO口配置
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//EXTI 相关配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0 | GPIO_PinSource1);//外部中断源线配置
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Falling;	//下降沿触发
	EXTI_Init(&EXTI_InitStructure);
	
	// KEY1 NVIC中断优先级配置 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2
	NVIC1_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC1_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC1_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC1_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC1_InitStructure);
	
	//KEY2 中断优先级配置
	NVIC2_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC2_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC2_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC2_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC2_InitStructure);
}
  • 编写中断服务函数
//外部中断0服务程序  KEY1
void EXTI0_IRQHandler(void)
{
	delay_ms(10);
	if( KEY1 == 0 )	 	 
		LED1 = !LED1;
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  
}

//外部中断1服务程序 KEY2
void EXTI1_IRQHandler(void)
{
	delay_ms(10);
	if(KEY2 == 0)	  
		LED2 = !LED2;
	EXTI_ClearITPendingBit(EXTI_Line1);  //清除LINE1上的中断标志位  
}

你可能感兴趣的:(stm32单片机,stm32,c语言)