0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

聊聊一個STM32中斷處理問題

茶話MCU ? 來源:茶話MCU ? 作者:茶話MCU ? 2023-03-22 09:06 ? 次閱讀

先看一段代碼:

while(1)

{

if(EXTI_Sign==1)

{

HAL_Delay(Period);

HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);

HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);

EXTI_Sign=0;

。。。。。。

}

}

有人使用STM32G0系列的芯片開發(fā)產(chǎn)品,有段功能測試驗(yàn)證代碼如上所示,相同的函數(shù)必須調(diào)用2次才能正常運(yùn)行,調(diào)用2次倒也罷了,關(guān)鍵是必須!頗為納悶。

這里開啟了PA3的外部中斷功能,上下沿均可觸發(fā)。PA3接收外來報警信號,類似于煙感報警器。報警信號是一串脈沖信號,報警信號過來時存在多次抖動問題??蛻粝肓藗€方法消抖,只要報警端口有電平變化就觸發(fā)中斷然后把中斷Disable,并設(shè)置報警標(biāo)志再回到主程序。

主程序里識別到報警有效標(biāo)志后延時幾分鐘再Enable剛才Disable掉的外部中斷。但是,他發(fā)現(xiàn)再次使能外部中斷時需要連續(xù)兩次調(diào)用使能中斷的代碼才可以響應(yīng)新的報警信號?!敬颂幬淖忠罁?jù)反饋者的文字描述組織而成】

下面MX_GPIO_Init(void)是經(jīng)CubeMx配置后自動生成的,里面有EXTI相關(guān)NVIC配置。相關(guān)代碼如下:

static void MX_GPIO_Init(void)


{


  GPIO_InitTypeDef GPIO_InitStruct = {0};


/* GPIO Ports Clock Enable */


  __HAL_RCC_GPIOA_CLK_ENABLE();


  __HAL_RCC_GPIOB_CLK_ENABLE();


    。。。。。。


/*Configure GPIO pin : PA3 */


  GPIO_InitStruct.Pin = GPIO_PIN_3;


  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;


  GPIO_InitStruct.Pull = GPIO_PULLUP;


  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/


  HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 0);


  HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);


}




基于上沿觸發(fā)的中斷服務(wù)程序如下[基于下沿觸發(fā)的此處省略】:
EXTI ISR():
{
__HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_PIN_3);//清中斷申請標(biāo)志;


HAL_NVIC_DisableIRQ(EXTI2_3_IRQn);//關(guān)閉中斷響應(yīng)


EXIT_Sign=1;//表示收到報警信號
}


主循環(huán)代碼像下面書寫才能讓程序正常運(yùn)行:【略去了其它代碼】


while (1)
  {
    if(EXTI_Sign ==1)
    {
    HAL_Delay(Period);


    MX_GPIO_Init();//客戶無意中發(fā)現(xiàn)加這句有用


   HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);


   EXTI_Sign =0;
    。。。。。。
    }
}



現(xiàn)在的疑問是在EXTI中斷服務(wù)程序運(yùn)行HAL_NVIC_DisableIRQ(EXTI2_3_IRQn)后,到主循環(huán)代碼里再次使能外部中斷時,為何還要額外運(yùn)行一次MX_GPIO_Init()函數(shù)才能讓程序正常運(yùn)行。最終發(fā)現(xiàn)運(yùn)行該函數(shù)的實(shí)質(zhì)就是將HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)多運(yùn)行一次。

換句話說,上面的主循環(huán)代碼要改成下面樣子才可以讓程序正常運(yùn)行:

while(1)

{

if(EXTI_Sign==1)

{//報警有效,即發(fā)生過報警時,代碼進(jìn)到這里。

HAL_Delay(Period);

HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);//1

HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);//2

EXTI_Sign=0; //清除報警標(biāo)志,準(zhǔn)備監(jiān)測新的警情

。。。。。。

}

}

說到底,問題就是主循環(huán)里為何要兩次重復(fù)運(yùn)行HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù)后才能響應(yīng)新的報警信號呢?

可以肯定,理論上講,開啟某個中斷響應(yīng)無須2次運(yùn)行相關(guān)函數(shù)。我們來一起找找原因。為了便于查看代碼,我把中斷服務(wù)程序和主程序代碼截圖放在一起。

348cf5ca-c844-11ed-bfe3-dac502259ad0.png

34a6f79a-c844-11ed-bfe3-dac502259ad0.png

在中斷服務(wù)程序里就是清除中斷請求標(biāo)志,關(guān)閉PA3的外部中斷響應(yīng),并設(shè)置警情標(biāo)志EXTI_Sign為1。

這里有沒有問題呢?

他使用的HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù),關(guān)閉的是內(nèi)核對該中斷請求的響應(yīng),盡管他剛才在進(jìn)中斷時做外部中斷請求標(biāo)志的清零,但并不能保證他這個清零操作之后不會再產(chǎn)生外部中斷請求。事實(shí)上,結(jié)合目前的使用場景,由于報警信號是一串跳變脈沖,即使一進(jìn)中斷就先做了個中斷請求標(biāo)志的清零,在中斷退出甚至還未完全退出時大概率還會產(chǎn)生新的中斷請求,但又由于他在中斷服務(wù)程序里把中斷響應(yīng)關(guān)閉了,中斷不能得到及時響應(yīng),請求只能懸著【Pending】跟隨程序來到主循環(huán)。

主循環(huán)代碼首先檢查報警標(biāo)志是否生效,生效則進(jìn)入循環(huán)體,先靜靜地歇會兒【HAL_Delay(Period)】,讓剛才的報警信號完全消停下來,然后再調(diào)用第一個HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù)打開中斷響應(yīng)。這下可好,剛才候著的中斷請求得到響應(yīng)機(jī)會了,則馬上去執(zhí)行中斷服務(wù)程序。這次在中斷服務(wù)程序里的操作跟上次完全一樣,即在中斷服務(wù)程序里,又調(diào)用中斷響應(yīng)關(guān)閉函數(shù),做了跟剛才主循環(huán)里第一個HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù)完全相反的功能。即到這個點(diǎn)的時候,中斷響應(yīng)被關(guān)閉了。

如果中斷返回后沒有使用第2句HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù)打開中斷響應(yīng),而只是執(zhí)行那句清零報警標(biāo)志然后退出循環(huán)體。由于中斷響應(yīng)已經(jīng)關(guān)閉,不管外部怎么報警都不會得到響應(yīng),報警標(biāo)志也就永遠(yuǎn)不會被置1,這樣主循環(huán)體也進(jìn)不了內(nèi)循環(huán)來開啟中斷響應(yīng)。

如果有了第2句HAL_NVIC_EnableIRQ(EXTI2_3_IRQn)函數(shù)在循環(huán)體內(nèi),它就可以扭轉(zhuǎn)剛才在中斷服務(wù)程序里關(guān)閉外部中斷響應(yīng)的局面,即把它扳回來。這樣的話功能上至少能正常運(yùn)轉(zhuǎn)了。

原因基本就大致這么回事?;诂F(xiàn)有代碼寫法,如何破除這個連寫2次的搞法呢。其實(shí),我們只需要在主循環(huán)體內(nèi)開啟外部中斷響應(yīng)的函數(shù)前,延時等待函數(shù)之后加上對相關(guān)中斷請求標(biāo)志位的清零即可解決當(dāng)前困惑。

比如像下面這樣【其中DSB是個數(shù)據(jù)同步隔離指令,保障它前面的指令執(zhí)行完畢后才執(zhí)行它后面的】,在主循環(huán)內(nèi)開啟中斷響應(yīng)前,先做中斷請求標(biāo)志的清零。

while(1)

{

if(EXTI_Sign==1)

{

HAL_Delay(Period);

__HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_PIN_3); __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_PIN_3);

__DSB();

HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);

EXTI_Sign=0;

。。。。。。

}

}

OK,本話題就聊到這里,愿君有所獲。類似問題不論STM32新手還是老手都可能不期而遇,祝君好運(yùn)!

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • STM32
    +關(guān)注

    關(guān)注

    2270

    文章

    10904

    瀏覽量

    356367
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    899

    瀏覽量

    41529
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3788

    瀏覽量

    81105
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4333

    瀏覽量

    62699
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4791

    瀏覽量

    68694

原文標(biāo)題:聊聊一個STM32中斷處理問題

文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32中斷優(yōu)先級和開關(guān)總中斷教程

    STM32中斷優(yōu)先級和開關(guān)總中斷 教程
    發(fā)表于 11-23 18:03 ?0次下載

    STM32中斷管理函數(shù)

    STM32中斷管理函數(shù),感興趣的小伙伴們可以瞧瞧。
    發(fā)表于 11-02 19:13 ?15次下載

    中斷是什么?STM32中斷系統(tǒng)介紹和中斷配置步驟資料免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是中斷是什么?STM32中斷系統(tǒng)介紹和中斷配置步驟資料免費(fèi)下載。
    發(fā)表于 10-11 08:00 ?5次下載
    <b class='flag-5'>中斷</b>是什么?<b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>系統(tǒng)介紹和<b class='flag-5'>中斷</b>配置步驟資料免費(fèi)下載

    STM32的Cortex-M3中斷異常處理

    STM32處理器中有43可屏蔽中斷通道(不包含 16 Cortex?-M3的中斷線)。共設(shè)
    發(fā)表于 11-16 15:35 ?8262次閱讀
    <b class='flag-5'>STM32</b>的Cortex-M3<b class='flag-5'>中斷</b>異常<b class='flag-5'>處理</b>

    STM32中斷及FreeRTOS中斷優(yōu)先級配置

    STM32中斷,及FreeRTOS中斷優(yōu)先級配置
    的頭像 發(fā)表于 03-04 11:45 ?8933次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>及FreeRTOS<b class='flag-5'>中斷</b>優(yōu)先級配置

    STM32關(guān)全局中斷的方法 STM32中斷類型

    。 STM32中斷類型: 系統(tǒng)異常:內(nèi)核水平 10 外部中斷:外設(shè)水平 60 STM32關(guān)全
    的頭像 發(fā)表于 07-22 10:52 ?2.8w次閱讀

    STM32中斷與DMA通信編程

    學(xué)習(xí)stm32中斷、DMA通信原理和編程方法。使用stm32tubemx和HAL庫分別完成以下編程練習(xí):(1)用stm32F103核心板的GPIOA端
    發(fā)表于 11-23 17:51 ?12次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>與DMA通信編程

    stm32f103中斷總結(jié)很詳細(xì)

    stm32f103中斷總結(jié)很詳細(xì)
    發(fā)表于 11-24 17:06 ?28次下載
    <b class='flag-5'>stm32</b>f103<b class='flag-5'>中斷</b>總結(jié)很詳細(xì)

    STM32中斷與DMA通信編程

    學(xué)習(xí)stm32中斷、DMA通信原理和編程方法。使用stm32tubemx和HAL庫分別完成以下編程練習(xí):(1)用stm32F103核心板的GPIOA端
    發(fā)表于 11-26 10:21 ?3次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>與DMA通信編程

    STM32中斷與DMA通信編程

    學(xué)習(xí)stm32中斷、DMA通信原理和編程方法。使用stm32tubemx和HAL庫分別完成以下編程練習(xí):(1)用stm32F103核心板的GPIOA端
    發(fā)表于 11-26 19:21 ?11次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>與DMA通信編程

    STM32中斷系統(tǒng)的基本概念

    STM32中斷系統(tǒng)基本概念、日常生活中斷*圖片來源網(wǎng)絡(luò)二、處理
    發(fā)表于 01-14 14:57 ?0次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>系統(tǒng)的基本概念

    stm32中斷初識與實(shí)踐(上)

    stm32中斷的講解我分為兩部分,即兩篇文章,上半部分做一個總結(jié)性的概覽,有初步認(rèn)識,下半部分會通過
    發(fā)表于 02-11 15:26 ?4次下載
    <b class='flag-5'>stm32</b><b class='flag-5'>中斷</b>初識與實(shí)踐(上)

    STM32中斷系統(tǒng)的工作流程

    管理核心的STM32中斷系統(tǒng)有初步的了解,明白中斷些基本概念以及
    的頭像 發(fā)表于 06-22 09:17 ?2635次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>系統(tǒng)的工作流程

    為什么有些STM32中斷沒有子優(yōu)先級?

    看到交流群在討論關(guān)于【關(guān)于STM32中斷優(yōu)先級的話題】,其中就有小伙伴提到:為什么有些STM32中斷
    的頭像 發(fā)表于 10-17 15:50 ?898次閱讀
    為什么有些<b class='flag-5'>STM32</b><b class='flag-5'>中斷</b>沒有子優(yōu)先級?

    stm32中斷怎么處理

    STM32款非常強(qiáng)大的微控制器系列,具有豐富的外設(shè)和功能。中斷STM32非常重要的部分,能夠幫助我們提高系統(tǒng)的響應(yīng)速度和效率。本文將
    的頭像 發(fā)表于 01-02 17:35 ?2617次閱讀