STM32Cube HAL出來六七年了,還是有很多初學者沒有適應,今天就分享一個讀者問到的關于中斷處理的問題。 很多人都知道STM32CubeMX這套工具的一個目的:減少開發者對STM32底層驅動的開發時間,把重心放在應用代碼上。 但是,STM32CubeMX只是生成了底層驅動的初始化代碼。所以,我們還需要掌握:應用層代碼如何調用HAL庫函數(API接口),以及HAL庫中斷處理機制等相關知識。 HAL庫牽涉的內容較多,下面簡單描述一下HAL庫中斷處理,以及相關的回調函數。
1HAL庫中斷處理機制
之前使用標準外設庫開發時,中斷程序(函數)由我們自己實現。
而HAL庫的中斷處理函數是按照HAL處理機制來實現,如USART1,統一由HAL_UART_IRQHandler來進行處理,如下圖:
其它大部分外設(TIM、SPI、CAN...)中斷都類似,HAL進行統一處理。
也就是說,HAL已經幫我們把中斷處理函數寫好了,我們只需要調用相應函數來編寫應用程序就行了。 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; }}
其實,大家認真看一下代碼應該能明白,這些和我們編寫的中斷處理函數是不是有類似之處? 這是無非就是接收中斷、發送中斷、錯誤中斷等一系列處理。只是這里又進行了再次封裝,比如接收中斷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庫編寫應用代碼不是問題。
2回調函數實現原理
在HAL庫中存在大量類似HAL_XXX_XXXCallback這樣的函數,這些都是回調函數。
回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。 回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。
---來自百度百科
HAL庫中斷處理使用了較多的回調函數,還是拿UART接收中斷來舉例說明。
初始化配置好UART中斷接收,如果有中斷請求,就會執行回調函數HAL_UART_RxCpltCallback。
看上面回調函數的定義,通過特定條件調用『回調函數』,這里觸發的條件就是中斷。
3
擴展說明
這里也簡單說幾點:
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.
原文標題:STM32Cube HAL庫中斷處理機制,回調函數實現原理
文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
責任編輯:haq
-
STM32
+關注
關注
2272文章
10923瀏覽量
357550 -
函數
+關注
關注
3文章
4346瀏覽量
62968
原文標題:STM32Cube HAL庫中斷處理機制,回調函數實現原理
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論