簡介:
exti--外部中斷/事件控制器,控制器由20個邊沿檢測器組成,每個檢測器都連接了所有端口對應引腳,每個輸入線都可以獨立的配置輸入類型可觸發事件(上升沿/下降沿/雙邊沿觸發)。
功能框圖;
圖中黃色部分表示每個寄存器都有20個輸入線與之相對應
如:中斷屏蔽寄存器
寄存器中有20個外部輸入線的中斷屏蔽標志位。
紅色虛線部分為中斷部分:邊沿檢測電路通過上升/下降沿邊沿觸發選擇寄存器對輸入線輸入的信號進行檢測,當檢測條件滿足時(如:設置上升沿觸發,則信號線來了一個上升沿),邊沿檢測電路輸出1給圖中的3(或門),或門輸出信號傳給圖中4(與門),如果設置了中斷屏蔽寄存器的值為1(表示開發中斷請求),則與門輸出電平1,請求掛起寄存器對應位置1,圖中的5從請求掛起寄存器中取出值給NVIC,從而實現中斷控制。
綠色虛線部分為事件部分:圖中1 2 3與產生中斷一樣。圖3產生的信號此時電平為1與6(與門)另一個輸入信號事件屏蔽寄存器值進行與操作,如果事件屏蔽寄存器的對應位也為1,則輸出電平1給脈沖發生器,脈沖發生器接收到電平1后,產生脈沖從圖中8輸出出去。
中斷/事件線:
exti0~15可以對應多個io引腳,通過AFIO寄存器選擇具體的引腳。
外部中斷初始化結構體:
EXTI_Line:中斷線選擇,可以選擇EXTI0~EXTI19
EXTI_Mode:模式 是產生中斷還是事件
EXTI_Trigger:觸發類型 是上升沿 下降沿還是雙邊沿觸發
EXTI_LineCmd:是 使能還是失能中斷線
實驗:
通過開發板上的四個按鍵對4個LED控制。按下按鍵LED亮,再按下,LED滅
原理圖:
編程思路:
1.初始化4個led端口 和4個按鍵其中key_up配置成下拉輸入,其他按鍵配置成上拉輸入
2.配置中斷優先級
3.配置外部中斷,在里面記得開啟AFIO時鍾
4.編寫中斷程序
exti頭文件:
#ifndef _EXTI_H #define _EXTI_H #include "stm32f10x.h" //上鍵宏定義 #define KEY_UP_CLK RCC_APB2Periph_GPIOA #define KEY_UP_PIN GPIO_Pin_0 #define KEY_UP_PORT GPIOA //左鍵 #define KEY_LEFT_CLK RCC_APB2Periph_GPIOE #define KEY_LEFT_PIN GPIO_Pin_2 #define KEY_LEFT_PORT GPIOE //下鍵 #define KEY_DOWN_CLK RCC_APB2Periph_GPIOE #define KEY_DOWN_PIN GPIO_Pin_3 #define KEY_DOWN_PORT GPIOE //右鍵 #define KEY_RIGHT_CLK RCC_APB2Periph_GPIOE #define KEY_RIGHT_PIN GPIO_Pin_4 #define KEY_RIGHT_PORT GPIOE //LED #define LED_CLK RCC_APB2Periph_GPIOC #define LED_PORT GPIOC #define LED1_PIN GPIO_Pin_0 #define LED2_PIN GPIO_Pin_1 #define LED3_PIN GPIO_Pin_2 #define LED4_PIN GPIO_Pin_3 void EXTI_Config(void); #endif
exti源文件
#include "exti.h" static void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(LED_CLK,ENABLE); //LED1 LED2 LED3 LED4初始化 GPIO_InitStruct.GPIO_Pin=LED1_PIN|LED2_PIN|LED3_PIN|LED4_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽輸出 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(LED_PORT,&GPIO_InitStruct); //默認熄滅 GPIO_SetBits(LED_PORT,LED1_PIN|LED2_PIN|LED3_PIN|LED4_PIN); } static void KEY_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; //開啟四個鍵所對應io端口時鍾 RCC_APB2PeriphClockCmd(KEY_UP_CLK|KEY_LEFT_CLK|KEY_DOWN_CLK|KEY_RIGHT_CLK,ENABLE); //上鍵 GPIO_InitStruct.GPIO_Pin=KEY_UP_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;//下拉輸入模式 GPIO_Init(KEY_UP_PORT,&GPIO_InitStruct); //左鍵 GPIO_InitStruct.GPIO_Pin=KEY_LEFT_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//上拉輸入模式 GPIO_Init(KEY_LEFT_PORT,&GPIO_InitStruct); //下鍵 GPIO_InitStruct.GPIO_Pin=KEY_DOWN_PIN; GPIO_Init(KEY_DOWN_PORT,&GPIO_InitStruct); //右鍵 GPIO_InitStruct.GPIO_Pin=KEY_RIGHT_PIN; GPIO_Init(KEY_RIGHT_PORT,&GPIO_InitStruct); } static void KEY_EXTI_Config(void) { EXTI_InitTypeDef EXTI_InitStruct; //使用外部中斷 端口復用 重映射需要開啟AFIO時鍾 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //上鍵外部中斷配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//外部中斷線配置 EXTI_InitStruct.EXTI_Line=EXTI_Line0;//中斷線 EXTI_InitStruct.EXTI_LineCmd=ENABLE; EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//中斷模式 EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿檢測 EXTI_Init(&EXTI_InitStruct); //左鍵外部中斷配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//外部中斷線配置 EXTI_InitStruct.EXTI_Line=EXTI_Line2;//中斷線 EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿檢測 EXTI_Init(&EXTI_InitStruct); //下鍵外部中斷配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//外部中斷線配置 EXTI_InitStruct.EXTI_Line=EXTI_Line3;//中斷線 EXTI_Init(&EXTI_InitStruct); //右鍵外部中斷配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);//外部中斷線配置 EXTI_InitStruct.EXTI_Line=EXTI_Line4;//中斷線 EXTI_Init(&EXTI_InitStruct); } static void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷優先級分組 //上鍵 NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;//中斷源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); //左鍵 NVIC_InitStruct.NVIC_IRQChannel=EXTI2_IRQn;//中斷源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; NVIC_Init(&NVIC_InitStruct); //下鍵 NVIC_InitStruct.NVIC_IRQChannel=EXTI3_IRQn;//中斷源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; NVIC_Init(&NVIC_InitStruct); //右鍵 NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn;//中斷源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=3; NVIC_Init(&NVIC_InitStruct); } void EXTI_Config(void) { LED_GPIO_Config(); KEY_GPIO_Config(); NVIC_Config(); KEY_EXTI_Config(); } //上鍵中斷 void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED1_PIN)) GPIO_ResetBits(LED_PORT,LED1_PIN); else GPIO_SetBits(LED_PORT,LED1_PIN); EXTI_ClearITPendingBit(EXTI_Line0); } } //左鍵中斷 void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED2_PIN)) GPIO_ResetBits(LED_PORT,LED2_PIN); else GPIO_SetBits(LED_PORT,LED2_PIN); EXTI_ClearITPendingBit(EXTI_Line2); } } //下鍵中斷 void EXTI3_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line3)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED3_PIN)) GPIO_ResetBits(LED_PORT,LED3_PIN); else GPIO_SetBits(LED_PORT,LED3_PIN); EXTI_ClearITPendingBit(EXTI_Line3); } } //右鍵中斷 void EXTI4_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line4)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED4_PIN)) GPIO_ResetBits(LED_PORT,LED4_PIN); else GPIO_SetBits(LED_PORT,LED4_PIN); EXTI_ClearITPendingBit(EXTI_Line4); } }
main 文件:
#include "stm32f10x.h" #include "exti.h" int main(void) { EXTI_Config(); while(1); }