STM32Cube HAL庫中斷處理機制,以及回調函數實現原理


————————————————
版權聲明:本文為CSDN博主「ybhuangfugui」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ybhuangfugui/article/details/88704013

1寫在前面

很多人都知道STM32CubeMX這套工具的一個目的:減少開發者對STM32底層驅動的開發時間,把重心放在應用代碼上。

 

但是,STM32CubeMX只是生成了底層驅動的初始化代碼。所以,我們還需要掌握:應用層代碼如何調用HAL庫函數接口,以及HAL庫中斷處理機制等相關知識。

 

HAL庫牽涉的內容較多,本文拿HAL庫中斷處理來講解,以及相關的回調函數。

 

2

HAL庫中斷處理機制
之前使用標准外設庫開發時,中斷程序(函數)由我們自己實現。

 

而HAL庫的中斷處理函數是按照HAL處理機制來實現,如USART1,統一由HAL_UART_IRQHandler來進行處理,如下圖:

 

其它大部分外設(TIM、SPI、CAN...)中斷都類似,HAL進行統一處理。


也就是說,HAL已經幫我們把中斷處理函數寫好了,我們只需要調用相應函數來編寫應用程序就行了。

 

HAL_xxx_IRQHandler里面做了哪些處理? 我們以STM32F1的HAL_UART_IRQHandler為例:

 1 void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)    
 2 {    
 3    uint32_t isrflags   = READ_REG(huart->Instance->SR);    
 4    uint32_t cr1its     = READ_REG(huart->Instance->CR1);    
 5    uint32_t cr3its     = READ_REG(huart->Instance->CR3);    
 6    uint32_t errorflags = 0x00U;    
 7    uint32_t dmarequest = 0x00U;    
 8  
 9     
10   /* If no error occurs */    
11   errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));    
12   if(errorflags == RESET)    
13   {    
14     /* UART in mode Receiver -------------------------------------------------*/    
15     if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))    
16     {    
17       UART_Receive_IT(huart);    
18       return;    
19     }    
20   }    
21  
22     
23   /* If some errors occur */    
24   if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))    
25   {    
26   /*    
27   ·    
28   ·刪減了部分代碼    
29   ·    
30   */    
31   } /* End if some error occurs */    
32  
33     
34   /* UART in mode Transmitter ------------------------------------------------*/    
35   if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))    
36   {    
37     UART_Transmit_IT(huart);    
38     return;    
39   }    
40   /* UART in mode Transmitter end --------------------------------------------*/    
41   if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))    
42   {    
43     UART_EndTransmit_IT(huart);    
44     return;    
45   }    
46 }

其實,大家認真看一下代碼應該能明白,這些和我們編寫的中斷處理函數是不是有類似之處?

 

這是無非就是接收中斷、發送中斷、錯誤中斷等一系列處理。只是這里又進行了再次封裝,比如接收中斷UART_Receive_IT。

 

當然,這個UART_Receive_IT接收中斷實現方式又可能存在不同。像F0、F1...就是直接調用這個接收中斷函數來進一步處理。

 

像L0、G0...是通過執行指針函數RxISR來進一步處理。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中斷處理的函數,大家有沒有得到什么啟發?

 

其實,HAL庫里面處理機制基本一致,只是實現方式上有所不同。

 

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

3

回調函數實現原理
在HAL庫中存在大量類似HAL_XXX_XXXCallback這樣的函數,這些都是回調函數。

 

回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。

回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。

---來自百度百科

 

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

 

初始化配置好UART中斷接收,如果有中斷請求,就會執行回調函數HAL_UART_RxCpltCallback。

 

看上面回調函數的定義,通過特定條件調用『回調函數』,這里觸發的條件就是中斷。

4

擴展說明
這里也簡單說幾點:

 

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

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

 

2.學HAL,建議參看官網例程

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

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

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

 

4.實際項目需做一定修改

STM32CubeMX僅僅是生成初始化代碼和工程,你實際項目中一般都有自己的軟件架構。

特別是項目越大,軟件架構就需要更加規范。

 

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

 

再比如:函數MX_USART2_UART_Init改成MX_DEBUG_UART_Init.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM