中斷:在主程式執行過程中,出現了特定事件(例如發生已經預知的一些情況),從而轉入中斷程式中,處理完成後再回到主程式中繼續執行。(頻繁的中斷函式會影響主程式的執行,所以中斷函式一邊不處理特別複雜的邏輯)
EXTI(Extern Interrupt)外部中斷
支援的觸發方式:上升沿/下降沿/雙邊沿/軟體觸發
支援的GPIO口:所有GPIO口,但相同的Pin不能同時觸發中斷
通道數:16個GPIO_Pin,外加PVD輸出、RTC鬧鐘、USB喚醒、乙太網喚醒(0-15:對應GPIO_PIN 0-15中斷;16:PVD輸出;17:RTC鬧鐘事件;18:USB喚醒事件;19:連線到乙太網喚醒事件(只適用於互聯型產品))
觸發響應方式:中斷響應/事件響應
注意EXTI9_5和EXTI15_10這幾個中斷在兩個通道里,需要透過標誌位判斷。
EXTI中斷髮生流程:EXTI監測指定GPIO口的電平訊號,當其指定的GPIO口產生電平變化時,EXTI將立即向NVIC發出中斷申請,經過NVIC裁決後即可中斷CPU主程式,使CPU執行EXTI對應的中斷程式。
NVIC(Nested vectoredinterrupt controller)巢狀向量中斷控制器
NVIC提供了靈活、高效、可擴充套件的中斷處理機制,支援多級優先順序、多向中斷、巢狀向量中斷等特性。
NVIC支援多級優先順序,可以配置不同的優先順序和互斥優先順序組。中斷控制器負責中斷的掛起、解掛和優先順序管理。
透過檢測GPIO的PB14的電平變化觸發中斷的例項:
初始化:
void EXTI_NVIC_Init(void){ /* GPIO --> AFIO */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //開啟GPIOB口時鐘,因為檢測的是PB14口的電平訊號 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //開啟AFIO時鐘 GPIO_InitTypeDef GPIO_InitStructure; //初始化PB14引腳 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); /* AFIO --> EXTI */ EXTI_InitTypeDef EXTI_InitStructure; //初始化EXTI EXTI_InitStructure.EXTI_Line =EXTI_Line14; //選擇14號線 EXTI_InitStructure.EXTI_LineCmd =ENABLE; //14號線使能 EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt; //選擇模式,這裡是中斷模式觸發中斷,如果是EXTI_Mode_Event,就是觸發一個事件 EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Falling; //觸發方式:EXTI_Trigger_Falling ,EXTI_Trigger_Rising_Falling ,EXTI_Trigger_Rising,這裡選的是下降沿觸發 EXTI_Init(&EXTI_InitStructure); /* EXTI --> NVIC */ //開啟NVIC NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設定優先分組為2,這裡是隨便設定的 NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = 40; //EXTI15_10_IRQn=40, /*!< External Line[15:10] Interrupts */ 選擇配置EXTI15_10線這裡PB14在EXTI15_10中 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //線路使能 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //搶佔優先順序 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //響應優先順序 NVIC_Init(&NVIC_InitStruct); //初始化 }
中斷函式:
void EXTI15_10_IRQHandler(void){ //函式名為預留的指定名稱,可以從啟動檔案複製 //中斷標誌位判斷 if(EXTI_GetITStatus(EXTI_Line14) == SET){ //判斷是否是14號線觸發的中斷 /*可新增一些操作 *count++; */ EXTI_ClearITPendingBit(EXTI_Line14);//清除中斷標誌 } }