STM32學習筆記(九) 外部中斷,待機模式和事件喚醒

來源:互聯網
上載者:User

標籤:

    學會知識只需要不段的積累和提高,但是如何將知識系統的講解出來就需要深入的認知和系統的瞭解。外部中斷和事件學習難度並不高,不過涉及到STM32的電源控制部分,還是值得認真瞭解的,在本文中我將以實際代碼為例詳細講解這些內容,希望對每一個閱讀者有協助。

  1.外部中斷

     如果已經學習了SysTick系統時鐘滴答實驗,掌握了Cortex-M3中斷的相關知識,那麼外部中斷也是比較好理解的,和SysTick中斷一樣,外部中斷也是當有訊號觸發時,如果中斷屏蔽寄存器允許觸發,就會產生中斷,這時CPU尋找中斷向量表,找到入口函數,就會正確的執行相關代碼,因為外部中斷本身就是依託於普通GPIO口的上升沿或者下降沿訊號的,所以本例中以按鍵作為測試外部中斷的硬體電路。

  根據工作原理圖:KEY1 ~ PC4;  KEY2 ~ PB10;

          KEY3 ~ PC13;  KEY4 ~ PA0;

       其中KEY1,2,3作為外部中斷引腳,KEY4作為喚醒引腳,後續會講解。

      知曉了工作原理圖,下面就要確定其對應的中斷線號了,這個在參考手冊外部中斷/事件線路映像章節中有詳細的說明,這裡部分:

   

 

  從上面可以看出,不同地區的相同位置的管腳共用同一個中斷線號,依次類推,上面的四個管腳分別對應的中斷線號為EXIT4, EXIT10, EXIT13,EXIT0,在這裡還有個注意點:那就是一個中斷線號只能反過來對應一個管腳,這就需要設計外部中斷硬體電路時不要重複,如PA0和PB0不能同時設計為外部中斷。

  瞭解了這些之後,如果熟悉STM32設計流程的話,那麼就知道順序是:

      1.外部中斷管腳GPIO初始化,代碼如下:

/***************************************************************** function    : EXTI_GPIO_Config* Description : 外部中斷觸發對應GPIO口配置                KEY1 PC4  外部中斷4                KEY2 PB10 外部中斷10                KEY3 PC13 外部中斷13                KEY4 PA0  WAKEUP喚醒事件* input       : 無* output      : 無*****************************************************************/void EXTI_GPIO_Config(void){    GPIO_InitTypeDef GPIO_InitStructure;          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB                            | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        GPIO_InitStructure.GPIO_Pin = EXTI_KEY1_Pin;    GPIO_Init(EXTI_KEY1_Port, &GPIO_InitStructure);    GPIO_EXTILineConfig(EXTI_KEY1_PortSource, EXTI_KEY1_PinSource);        //將GPIO複用為外部中洞觸發連接埠        GPIO_InitStructure.GPIO_Pin = EXTI_KEY1_Pin;    GPIO_Init(EXTI_KEY2_Port, &GPIO_InitStructure);     GPIO_EXTILineConfig(EXTI_KEY2_PortSource, EXTI_KEY2_PinSource);        GPIO_InitStructure.GPIO_Pin = EXTI_KEY3_Pin;    GPIO_Init(EXTI_KEY3_Port, &GPIO_InitStructure);    GPIO_EXTILineConfig(EXTI_KEY3_PortSource, EXTI_KEY3_PinSource);        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;    GPIO_InitStructure.GPIO_Pin = EXTI_KEY4_Pin;    GPIO_Init(EXTI_KEY4_Port, &GPIO_InitStructure);    GPIO_EXTILineConfig(EXTI_KEY4_PortSource, EXTI_KEY4_PinSource);}

      2.外設EXTI初始化

      3.在中斷屏蔽寄存器中允許對應中斷觸發

/***************************************************************** function    : EXTI_MODE_Config* Description : 外部中斷觸發配置及向量表開啟對應中斷                其中KEY1作為中斷進入_WFE模式                KEY2和KEY3作為普通中斷點亮對應LED燈                KEY4作為事件用來喚醒CPU* input       : 無* output      : 無*****************************************************************/void EXTI_MODE_Config(void){    EXTI_InitTypeDef EXTI_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;        EXTI_DeInit();        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        //外部按鍵觸發中斷   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    //下降沿觸發    EXTI_InitStructure.EXTI_LineCmd = ENABLE;                  //外部中斷使能    EXTI_InitStructure.EXTI_Line = EXTI_KEY1_Line;             //外部中斷線號4    EXTI_Init(&EXTI_InitStructure);        EXTI_InitStructure.EXTI_Line = EXTI_KEY2_Line;             //外部中斷線號10    EXTI_Init(&EXTI_InitStructure);        EXTI_InitStructure.EXTI_Line = EXTI_KEY3_Line;             //外部中斷線號13    EXTI_Init(&EXTI_InitStructure);        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;            //外部按鍵觸發事件    EXTI_InitStructure.EXTI_Line = EXTI_KEY4_Line;             //外部中斷線號0    EXTI_Init(&EXTI_InitStructure);    //PWR_WakeUpPinCmd(ENABLE);                                //PA0作為喚醒引腳使能        NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);               //向量表位於FLASH中,位移0    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        /*在向量表中啟用對應的中斷線號*/    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    NVIC_InitStructure.NVIC_IRQChannel = EXTI_KEY1_IRQn;                      NVIC_Init(&NVIC_InitStructure);    //    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                  //    NVIC_Init(&NVIC_InitStructure);        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    NVIC_InitStructure.NVIC_IRQChannel = EXTI_KEY2_3_IRQn;              NVIC_Init(&NVIC_InitStructure);}

      4.中斷函數處理

     按鍵PC4對應外部中斷入口,因為按鍵預設高電平,當有按鍵按下時,就會產生下降沿訊號,觸發中斷,此時CPU就在中斷向量表裡查詢外部中斷的入口地址,如PC4對應的入口地址就是void EXTI4_IRQHandler(void) ,開始執行中斷中內容,具體實現流程可參考SysTick章節。

/***************************************************************** function       : EXTI4_IRQHandler* Description    : 外部中斷4入口函數,實現LED點亮以及系統進入_WFE模式* input          : 無* output         : 無*****************************************************************/void EXTI4_IRQHandler(void)        {    led_light_up(0);    EXTI_ClearFlag(EXTI_Line4);                                      //清除中斷線號4    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);    //進入WFE停止低功耗模式 僅事件能喚醒    SystemInit();                                                    //退出STOP模式要初始化時鐘,因為睡眠時切換到內部時鐘    LED1_OFF();}

   在stm32的標頭檔和開機檔案設計中,中斷線號10~15共用相同的入口函數,因此需要在中斷中進行判斷,來確定是那個訊號觸發了中斷。

/***************************************************************** function       : EXTI15_10_IRQHandler* Description    : 外部中斷10和13共用中斷入口,通過觸發後狀態檢查確定                   觸發中斷的管腳並執行相應代碼。* input          : 無* output         : 無*****************************************************************/void EXTI15_10_IRQHandler(void)   {    ITStatus EXTI10_Status;    ITStatus EXTI13_Status;    EXTI10_Status = EXTI_GetITStatus(EXTI_Line10);    //獲得外部中斷10的狀態    EXTI13_Status = EXTI_GetITStatus(EXTI_Line13);     //獲得外部中斷13的狀態
  if(EXTI10_Status == SET) 
  {
    led_light_up(1);
  }
  if(EXTI13_Status == SET)
  {
    led_light_up(2);
  }
  EXTI_ClearFlag(EXTI_Line10 | EXTI_Line13); /*清除外部中斷10或者13的掛起位 */
}

    外部中斷涉及到的知識並並不多,不過仔細觀察上面的代碼,就會發現KEY4(PA0)並沒有配置為中斷,而配置為了事件,且被設定為喚醒引腳,KEY1(PC4)在中斷裡不只點亮了LED,還調用了PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE); 這種功能其實很有用,涉及到低功耗和外來事件喚醒,下面我來詳細說明。

    2.外來事件和中斷的區別和聯絡

     外來事件和中斷都是由管腳訊號觸發的,參考:

     

  這張圖可以很直觀的看出中斷和事件的區別,當外部有訊號輸入時,如果通過了了事件屏蔽寄存器,那麼事件訊號就進入脈衝觸發器,引發一個脈衝訊號,直接傳遞給相應的外設,用於觸發,這就是一個純硬體的過程,理解DMA的應該知道,這個方式不需要CPU參與,但是這也有它的缺點,如功能比較單一,僅能提供訊號,不能提供資訊,也就是只能產生指定功能的事件。如果通過中斷屏蔽寄存器,就被直接送到CPU中,產生中斷,如進入上面的入口函數開始處理。從這就可看出,事件是單純硬體觸發執行的過程,與CPU本身設計支援有關,而中斷中則可以軟體實現各種功能,而低功耗模式和事件喚醒就是stm32支援的事件之一。

   3.低功耗模式和事件喚醒

   低功耗模式是嵌入式設計用於可行動裝置的重要功能,在這種狀態下,CPU會關閉時鐘,從而降低耗電,延長單次使用時間。

   

    上面進入的就是停機-低功耗-WFE模式,因此只能由按鍵4事件喚醒。其實低功耗模式還有待機模式以及睡眠模式,這裡並沒有使用到,以後如果用到會穿插講解。中斷無法喚醒,另外,當CPU退出停止模式時,會強制切換到內部時鐘,因此在進入停止模式後一句要加上SystemInit()重新設定系統時鐘,避免時鐘改變。具體代碼參考:http://files.cnblogs.com/files/zc110747/7.EXTI_LED.7z

STM32學習筆記(九) 外部中斷,待機模式和事件喚醒

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.