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

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

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

HAL庫中斷處理以及相關(guān)的回調(diào)函數(shù)

strongerHuang ? 來源:strongerHuang ? 作者:strongerHuang ? 2021-01-07 11:46 ? 次閱讀

STM32Cube HAL出來六七年了,還是有很多初學(xué)者沒有適應(yīng),今天就分享一個讀者問到的關(guān)于中斷處理的問題。 很多人都知道STM32CubeMX這套工具的一個目的:減少開發(fā)者對STM32底層驅(qū)動的開發(fā)時間,把重心放在應(yīng)用代碼上。 但是,STM32CubeMX只是生成了底層驅(qū)動的初始化代碼。所以,我們還需要掌握:應(yīng)用層代碼如何調(diào)用HAL庫函數(shù)(API接口),以及HAL庫中斷處理機(jī)制等相關(guān)知識。 HAL庫牽涉的內(nèi)容較多,下面簡單描述一下HAL庫中斷處理,以及相關(guān)的回調(diào)函數(shù)。

1HAL庫中斷處理機(jī)制

之前使用標(biāo)準(zhǔn)外設(shè)庫開發(fā)時,中斷程序(函數(shù))由我們自己實(shí)現(xiàn)。

而HAL庫的中斷處理函數(shù)是按照HAL處理機(jī)制來實(shí)現(xiàn),如USART1,統(tǒng)一由HAL_UART_IRQHandler來進(jìn)行處理,如下圖:

00f04488-4ad8-11eb-8b86-12bb97331649.jpg

其它大部分外設(shè)(TIM、SPI、CAN...)中斷都類似,HAL進(jìn)行統(tǒng)一處理。
也就是說,HAL已經(jīng)幫我們把中斷處理函數(shù)寫好了,我們只需要調(diào)用相應(yīng)函數(shù)來編寫應(yīng)用程序就行了。 HAL_xxx_IRQHandler里面做了哪些處理?我們以STM32F1的HAL_UART_IRQHandler為例:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart){ uint32_t isrflags = READ_REG(huart->Instance->SR); uint32_t cr1its = READ_REG(huart->Instance->CR1); uint32_t cr3its = READ_REG(huart->Instance->CR3); uint32_t errorflags = 0x00U; uint32_t dmarequest = 0x00U; /* If no error occurs */ errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); if(errorflags == RESET) { /* UART in mode Receiver -------------------------------------------------*/ if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) { UART_Receive_IT(huart); return; } } /* If some errors occur */ if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) {/*··刪減了部分代碼·*/ } /* End if some error occurs */ /* UART in mode Transmitter ------------------------------------------------*/ if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) { UART_Transmit_IT(huart); return;} /* UART in mode Transmitter end --------------------------------------------*/ if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) { UART_EndTransmit_IT(huart); return; }}

其實(shí),大家認(rèn)真看一下代碼應(yīng)該能明白,這些和我們編寫的中斷處理函數(shù)是不是有類似之處? 這是無非就是接收中斷、發(fā)送中斷、錯誤中斷等一系列處理。只是這里又進(jìn)行了再次封裝,比如接收中斷UART_Receive_IT。 當(dāng)然,這個UART_Receive_IT接收中斷實(shí)現(xiàn)方式又可能存在不同。像F0、F1...就是直接調(diào)用這個接收中斷函數(shù)來進(jìn)一步處理。 像L0、G0...是通過執(zhí)行指針函數(shù)RxISR來進(jìn)一步處理。G0的接收中斷處理為:huart->RxISR(huart);

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart){//刪除了前面代碼 /* If no error occurs */ errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); if (errorflags == 0U) { /* UART in mode Receiver ---------------------------------------------------*/ if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) || ((cr3its & USART_CR3_RXFTIE) != 0U))) { if (huart->RxISR != NULL) { huart->RxISR(huart); } return; } }//刪除了后面代碼}

看了上面USART中斷處理的函數(shù),大家有沒有得到什么啟發(fā)?

其實(shí),HAL庫里面處理機(jī)制基本一致,只是實(shí)現(xiàn)方式上有所不同。

如果你摸清楚了HAL庫基本原理,相信閱讀HAL庫源碼,或者使用HAL庫編寫應(yīng)用代碼不是問題。

2回調(diào)函數(shù)實(shí)現(xiàn)原理

在HAL庫中存在大量類似HAL_XXX_XXXCallback這樣的函數(shù),這些都是回調(diào)函數(shù)。

回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當(dāng)這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。 回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進(jìn)行響應(yīng)。

---來自百度百科

HAL庫中斷處理使用了較多的回調(diào)函數(shù),還是拿UART接收中斷來舉例說明。

初始化配置好UART中斷接收,如果有中斷請求,就會執(zhí)行回調(diào)函數(shù)HAL_UART_RxCpltCallback。

看上面回調(diào)函數(shù)的定義,通過特定條件調(diào)用『回調(diào)函數(shù)』,這里觸發(fā)的條件就是中斷。

3

擴(kuò)展說明

這里也簡單說幾點(diǎn):

1.初學(xué)者想直接使用HAL不是不行,需要有一定C語言功底

針對大部分初學(xué)者來說,是不建議直接上手HAL。但是,有部分C功底較好的,還是建議直接上手。

2.學(xué)HAL,建議參看官網(wǎng)例程

很多人不知道如何找資源,我不止一次強(qiáng)調(diào),官方的才是最好。在HAL庫中Projects目錄下就有很多例程Examples。

3.我們追求效率,可以HAL庫源碼

如果你想修改HAL庫源碼,允許修改少部分。如果要大量修改,還是別折騰了。

4.實(shí)際項(xiàng)目需做一定修改

STM32CubeMX僅僅是生成初始化代碼和工程,你實(shí)際項(xiàng)目中一般都有自己的軟件架構(gòu)。

特別是項(xiàng)目越大,軟件架構(gòu)就需要更加規(guī)范。

比如:生成的gpio.c文件名,你需要修改成bsp_gpio.c.

再比如:函數(shù)MX_USART2_UART_Init改成MX_DEBUG_UART_Init.

原文標(biāo)題:STM32Cube HAL庫中斷處理機(jī)制,回調(diào)函數(shù)實(shí)現(xiàn)原理

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

責(zé)任編輯:haq

聲明:本文內(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)注

    2263

    文章

    10847

    瀏覽量

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

    關(guān)注

    3

    文章

    4260

    瀏覽量

    62233

原文標(biāo)題:STM32Cube HAL庫中斷處理機(jī)制,回調(diào)函數(shù)實(shí)現(xiàn)原理

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

收藏 人收藏

    評論

    相關(guān)推薦

    定時器調(diào)函數(shù)能不能用ICACHE_FLASH_ATTR定義?

    非 OS SDK 在中斷處理函數(shù)中,請勿使用任何 ICACHE_FLASH_ATTR 定義的函數(shù)。 請問: 1、定時器和hw定時器的
    發(fā)表于 07-22 06:33

    對于中斷,先執(zhí)行中斷服務(wù)函數(shù)還是先清理中斷標(biāo)志?

    對于中斷,先執(zhí)行中斷服務(wù)函數(shù)還是先清理中斷標(biāo)志?開始學(xué)習(xí)固件的時候,差不多是先進(jìn)入服務(wù)函數(shù)在清
    發(fā)表于 05-22 07:20

    請問hal的串口接收完成調(diào)函數(shù)中如何區(qū)分是不是DMA接收完成?

    HAL_UART_RxCpltCallback 這個調(diào)函數(shù)在串口中斷接收完成后會被調(diào)用,在DMA接收完成后也會被調(diào)用 那么能否在這個
    發(fā)表于 05-07 07:39

    STM32 hal無法接收串口數(shù)據(jù)是怎么回事?

    一個字節(jié)產(chǎn)生中斷。在接收中斷調(diào)函數(shù)處理保存數(shù)據(jù)并重新開啟接收一個字節(jié)的
    發(fā)表于 04-29 06:11

    請問ucos-III中斷保護(hù)放在中斷調(diào)函數(shù)還是中斷里面?

    請教下ucos-III 中斷保護(hù)放在中斷調(diào)函數(shù)還是中斷里面? 1.
    發(fā)表于 04-23 07:44

    使用HAL的USB模塊時,當(dāng)設(shè)置要接收的數(shù)據(jù)長度為大于64字節(jié)時,無法從接收結(jié)束調(diào)函數(shù)的原因?

    兩個方面:1、HAL包調(diào)用接收結(jié)束的調(diào)函數(shù)的條件為:接收完預(yù)設(shè)的數(shù)據(jù)長度 或者 接收到小于max_packet長度的包。 當(dāng)接收到第一個64字節(jié)后,因?yàn)檫€不滿要求接收的長度,因此
    發(fā)表于 04-12 06:07

    請問Hall多串口接收時串口中斷調(diào)函數(shù)重入導(dǎo)致HardFault 0xFFFFFFF1怎么解決?

    _BUSY){ UART3_RestartRecIT=1; } } } 按照正常集成的設(shè)計,各串口都有獨(dú)立的串口中斷響應(yīng)函數(shù),所以不會存在該問題。但是HAL
    發(fā)表于 04-03 06:44

    STM32CUBUMX定時器1中斷調(diào)函數(shù)就是進(jìn)不去怎么解決?

    );HAL_TIM_PWM_Start( htim1, TIM_CHANNEL_3); HAL_TIM_PWM_Start_IT( htim1, TIM_CHANNEL_3); 就死活進(jìn)不去,
    發(fā)表于 03-28 07:58

    HAL_UART_RxCpltCallback HAL調(diào)函數(shù),通過485發(fā)送命令與串口三通信后,整個調(diào)函數(shù)就不執(zhí)行了的原因?

    HAL_UART_RxCpltCallbackHAL調(diào)函數(shù)兩個串口同時進(jìn)行中斷接受數(shù)據(jù),一
    發(fā)表于 03-22 06:53

    Stm32G474 DMA傳輸全部完畢后,需要產(chǎn)生中斷并調(diào)運(yùn)回調(diào)函數(shù)完成相關(guān)操作,如何處理

    Stm32G474,DMA傳輸全部完畢后,需要產(chǎn)生中斷并調(diào)運(yùn)回調(diào)函數(shù)完成相關(guān)操作。請問我如何處理?沒有看到常規(guī)的
    發(fā)表于 03-15 08:26

    調(diào)函數(shù)(callback)是什么?調(diào)函數(shù)的實(shí)現(xiàn)方法

    調(diào)函數(shù)是一種特殊的函數(shù),它作為參數(shù)傳遞給另一個函數(shù),并在被調(diào)用函數(shù)執(zhí)行完畢后被調(diào)用。
    發(fā)表于 03-12 11:46 ?2479次閱讀

    ??嵌入式中調(diào)函數(shù)的實(shí)現(xiàn)方法

    調(diào)函數(shù)的命名規(guī)范沒有固定的標(biāo)準(zhǔn),但是根據(jù)通用慣例和編碼規(guī)范,調(diào)函數(shù)的命名應(yīng)該能夠反映
    發(fā)表于 03-04 14:49 ?592次閱讀

    stm32f1如何將外部中斷關(guān)掉hal

    Layer)來簡化芯片和外設(shè)的驅(qū)動開發(fā)。在STM32F1中,外部中斷的關(guān)閉是通過HAL中的相應(yīng)函數(shù)來實(shí)現(xiàn)的。下面我將詳細(xì)介紹如何使用HAL
    的頭像 發(fā)表于 12-22 13:52 ?2932次閱讀

    函數(shù)指針的五大作用

    1,調(diào)函數(shù)機(jī)制函數(shù)指針常用于實(shí)現(xiàn)調(diào)函數(shù)。通過將
    的頭像 發(fā)表于 12-06 08:00 ?1681次閱讀
    <b class='flag-5'>函數(shù)</b>指針的五大作用

    HAL常用函數(shù)匯總

    1,系統(tǒng)函數(shù)HAL_Delay原型:voidHAL_Delay(uint32_tDelay);作用:利用滴答定時器生成的系統(tǒng)延遲函數(shù)參數(shù):Delay:延遲時間,單位是ms返回值:無示例代碼
    的頭像 發(fā)表于 11-29 08:00 ?2776次閱讀
    <b class='flag-5'>HAL</b><b class='flag-5'>庫</b>常用<b class='flag-5'>函數(shù)</b>匯總