用外部中斷EXTI的方式控制LED燈
- EXTI簡介
- EXTI 功能框圖
- 中斷線路流程(紅色虛線)
- 編號 1 是輸入線
- 編號 2 是一個邊沿檢測電路
- 編號 3 電路實際就是一個或門電路
- 編號 4 電路是一個與門電路
- 編號 5 是將 EXTI_PR 暫存器內容輸出到 NVIC
- 事件線路流程(綠色虛線)
- 編號6 電路是一個與門
- 編號 7 是一個脈沖發生器電路
- 編號 8 是一個脈沖信號
- 配置流程和方法
- 配置中斷優先級
- 配置中斷引腳
- 配置中斷
- 撰寫中斷函式
- 撰寫主函式
- 注意事項
EXTI簡介
EXTI(External interrupt/event controller)—外部中斷/事件控制器,管理了控制器的 20個中斷/事件線,每個中斷/事件線都對應有一個邊沿檢測器,可以實作輸入信號的上升沿檢測和下降沿的檢測,EXTI 可以實作對每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,以及觸發事件的屬性,(以上是火哥說的)
EXTI 功能框圖

上圖可以看到很多在信號線上打一個斜杠并標注“20”字樣,這個表示在控制器內部類似的信號線路有 20 個,這與 EXTI 總共有 20 個中斷/事件線是吻合的,所以我們只要明白其中一個的原理,那其他 19 個線路原理也就知道了,
EXTI 可分為兩大部分功能,一個是產生中斷,另一個是產生事件,
中斷線路流程(紅色虛線)
編號 1 是輸入線
EXTI 控制器有 19 個中斷/事件輸入線,這些輸入線可以通過暫存器設定為任意一個 GPIO,也可以是一些外設的事件,輸入線一般是存在電平變化的信號,
編號 2 是一個邊沿檢測電路
它會根據上升沿觸發選擇暫存器(EXTI_RTSR)和下降沿觸發選擇暫存器(EXTI_FTSR)對應位的設定來控制信號觸發,邊沿檢測電路以輸入線作為信號輸入端,如果檢測到有邊沿跳變就輸出有效信號 1 給編號 3 電路,否則輸出無效信號0,而 EXTI_RTSR 和 EXTI_FTSR 兩個暫存器可以控制器需要檢測哪些型別的電平跳變程序,可以是只有上升沿觸發、只有下降沿觸發或者上升沿和下降沿都觸發,
編號 3 電路實際就是一個或門電路
它一個輸入來自編號 2 電路,另外一個輸入來自軟體中斷事件暫存器(EXTI_SWIER),EXTI_SWIER 允許我們通程序式控制就可以啟動中斷/事件線,這在某些地方非常有用,我們知道或門的作用就是有 1 就為 1,所以這兩個輸入隨便一個有有效信號 1 就可以輸出 1 給編號 4 和編號 6 電路,
編號 4 電路是一個與門電路
它一個輸入是編號 3 電路,另外一個輸入來自中斷屏蔽暫存器(EXTI_IMR),與門電路要求輸入都為 1 才輸出 1,導致的結果是如果 EXTI_IMR 設定為 0 時,那不管編號 3 電路的輸出信號是 1 還是 0,最終編號 4 電路輸出的信號都為 0;如果 EXTI_IMR 設定為 1 時,最終編號 4 電路輸出的信號才由編號 3 電路的輸出信號決定,這樣我們可以簡單的控制 EXTI_IMR 來實作是否產生中斷的目的,編號 4 電路輸出的信號會被保存到掛起暫存器(EXTI_PR)內,如果確定編號 4 電路輸出為 1 就會把 EXTI_PR 對應位置 1,
編號 5 是將 EXTI_PR 暫存器內容輸出到 NVIC
實作系統中斷事件控制,
事件線路流程(綠色虛線)
它是一個產生事件的線路,最終輸出一個脈沖信號,產生事件線路是在編號 3 電路之后與中斷線路有所不同,之前電路都是共用的,
編號6 電路是一個與門
它一個輸入來自編號 3 電路,另外一個輸入來自事件屏蔽暫存器
(EXTI_EMR),如果 EXTI_EMR 設定為 0 時,那不管編號 3 電路的輸出信號是 1 還是 0,最終編號 6 電路輸出的信號都為 0;如果 EXTI_EMR 設定為 1 時,最終編號 6 電路輸出的信號才由編號 3 電路的輸出信號決定,這樣我們可以簡單的控制 EXTI_EMR 來實作是否產生事件的目的,
編號 7 是一個脈沖發生器電路
當它的輸入端,即編號 6 電路的輸出端,是一個有效信號 1 時就會產生一個脈沖;如果輸入端是無效信號就不會輸出脈沖,
編號 8 是一個脈沖信號
就是產生事件的線路最終的產物,這個脈沖信號可以給其他外設電路使用,比如定時器 TIM、模擬數字轉換器 ADC 等等,這樣的脈沖信號一般用來觸發 TIM 或者 ADC 開始轉換,
(以上均來源于火哥,講的非常好,不自覺的就摘錄了,有需要的可以留言獲得火哥的教程,)
配置流程和方法
實驗名稱:外部中斷控制LED燈
實驗現象:按下KEY0(PC5)按鍵實作LED狀態翻轉
硬體資源:STM32開發板、按鍵、LED燈
配置中斷優先級
KEY0使用的是PC5,因此使用中斷線EXTI9_5_IRQn,
static void NVIC_config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(NVIC_CLK,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
配置中斷引腳
這里設定的是KEY0(PC5),硬體設計為上拉,
RCC_APB2PeriphClockCmd(KEY0_CLK,ENABLE);
GPIO_InitStruct.GPIO_Pin = KEY0_Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY0_PORT,&GPIO_InitStruct);
配置中斷
//1. 開啟中斷的時鐘
RCC_APB2PeriphClockCmd(EXTI_CLK,ENABLE);
//2. 配置中斷線
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
//3 配置中斷模式并初始化
EXTI_InitStruct.EXTI_Line = EXTI_Line5;
EXTI_InitStruct.EXTI_Mode =EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
撰寫中斷函式
在中斷服務函式中必須清除中斷標志位,
void EXTI9_5_IRQHandler(void)
{
delay_ms(50);
// if(EXTI_GetITStatus(EXTI_Line5) != RESET) //2??üê1ó??a??£??aê2?′??
if(KEY0==0)
{
LED=!LED;
}
EXTI_ClearITPendingBit(EXTI_Line5);
}
撰寫主函式
int main(void)
{
LED_Init();
delay_init();
EXTI_GPIO_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
while(1);
}
注意事項
- 必須配置中斷優先級NVIC_Init,并設定其優先級分組NVIC_PriorityGroupConfig
- 開啟AFIO時鐘和中斷的時鐘要放在配置中斷線GPIO_EXTILineConfig()之前,有次放在了后面,導致程式例外,搞了一個晚上,慘痛的教訓,
- NVIC_IRQChannel如果不會配置,可以去stm32f10x.h中去復制粘貼,
程式已經過除錯驗證
完整程式傳送門:
https://download.csdn.net/download/m0_46195580/13735851
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/238620.html
標籤:其他
