引言
“中斷” 這個概念,指的是在單片機運行過程中,在指定條件發生時,停下當前所有工作,去執行中斷處理函數內的內容。就像我們在教室上課時,突然地震了,不出意外的話我們都需要停下手中學習任務,去進行一系列的避險動作。
這一節我們通過中斷的方式,完成通過按鍵控制LED亮滅的操作。
准備環節
中斷相關知識
STM32的中斷控制器支持19個外部中斷/事件請求。這十九個外部中斷為:
- 線0~15:對應外部IO口的輸入中斷。
- 線16:連接到PVD輸出。
- 線17:連接到連接到RTC時鍾事件。
- 線18:連接到USB喚醒事件。
配置使用時,需要先將IO口與相應中斷線的映射關系建立,再對其進行使用。那映射關系是怎樣的呢?
GPIOx.0 ~ GPIOx.15(x = A,B,C,D,E,F,G)分別對應中斷線0 ~ 15
配置GPIO與中斷線關系的函數是
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
eg:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
把GPIO作為EXTI外部中斷時,需要打開AFIO時鍾。
APIO時鍾何時需要打開,具體可以參考這篇文章:
嵌套向量中斷控制器(NVIC)
初始化完線上中斷和中斷條件等內容,還需要配置中斷分組。配置中斷分組之前,我們需要先確定如何進行分組。這里就需要用到NVIC。
關於NVIC的具體內容可查看這篇博文:嵌套向量中斷控制器(NVIC)詳解。
編碼環節
步驟
- 初始化IO口輸入
- 開啟AFIO時鍾
- 設置IO口與中斷線的映射關系
- 初始化線上中斷、設置觸發條件等
- 配置中斷分組,並使能中斷
- 編寫中斷服務函數
main.c(以下內容均省略頭文件)
int main(void){
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC終端分組2
LED_Init();
KEY_Init();
EXTIX_Init(); //外部中斷初始化
LED1 = 0;
}
exti.h
#ifndef __EXTI_H
#define __EXIT_H
#include "sys.h"
void EXTIX_Init(void); //外部中斷初始化
#endif
exti.c
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure; //外部中斷結構體初始化
NVIC_InitTypeDef NVIC_InitStructure; //中斷分組結構體初始化
KEY_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //開啟AFIO時鍾
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //映射IO口與中斷線
//以下為配置中斷線初始化
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中斷模式
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中斷線
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //中斷線標號
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //觸發方式
EXTI_Init(&EXTI_InitStructure);
//以下為中斷優先級的配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //聲明使用的中斷是哪一個
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //設置搶占優先級為2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //設置子優先級為3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷
NVIC_Init(&NVIC_InitStructure);
}
void EXTI0_IRQHandler(void) //中斷服務函數
{
delay_ms(10); //軟件去抖
if(WK_UP==1)
{
LED0 = !LED0;
LED1 = !LED1;
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除中斷位
}
補充
中斷服務函數
中斷服務函數的名稱是固定的,寫錯會導致無法中斷。
STM32的IO口外部中斷函數只有六個。分別為:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
中斷線0 ~ 4各對應一個中斷服務函數,中斷線5 ~ 9共用 EXTI9_5_IRQHandler
,中斷線10 ~ 15共用 EXTI15_10_IRQHandler
。
中斷服務函數常規格式
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET) //判斷中斷線上的中斷是否發生
{
//這里寫需要執行的服務
EXTI_ClearITPendingBit(EXTI_Line3); //清除中斷標志位
}
}