STM32 HAL庫學習(二) 串口收發數據

   上一篇實現了LED的點亮和串口輪詢發送數據,這章想着實現串口接收數據,不得不說,在開始使用STM32的外設纔對HAL庫的框架有更準確的理解。之前一直不懂HAL庫的優越性在哪,這次對它的msp層有了一定認識。

   簡單來說,HAL庫有一個特點就是對於許多外設的初始化以及功能操作,都提供有一個weak版本的函數,例如串口的HAL_UART_MspInit()函數和HAL_UART_MspDeInit()函數等,這些都可以供用戶在需要時在stm32f0xx_hal_msp.c中進行重寫實現功能。

   用串口初始化來舉例子,用Cube配置UART1使能並生成代碼後可以看到有三個關鍵函數:

1、void MX_USART1_UART_Init(void)

      這個函數是Cube配置完成後自動幫我們生成的,存在於用戶文件usart.c中(如果Cube中有配置選項生成用戶.c文件,否則在main函數中)。裏面主要是將USART的結構體初始化成USART1以及我們設置好的參數),並且在最後有一個語句:if (HAL_UART_Init(&huart1) != HAL_OK)通過這個來調用HAL_UART_Init函數。

2、HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)

     這個函數在HAL庫文件stm32f0xx_hal_uart.c中,在上一個函數 MX_USART1_UART_Init(void)中有被調用,這個函數將初始化UART1,使能UART1,而重點是裏面有調用一個函數HAL_UART_MspInit(huart)

3、__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)

     這個函數也在HAL庫文件stm32f0xx_hal_uart.c中,它是weak修飾的,也就是可以重寫。我們發現在Cube生成的用戶文件usart.c文件中有對這個函數進行重寫,主要實現對UART1的TX、RX引腳的IO口配置,以及開啓串口中斷等設置。

由此,HAL庫的串口外設初始化操作就清晰了,也就是說如果我們使用Cube生成代碼,要完成對串口的初始化,就要自行對串口的結構體參數進行配置,並對HAL_UART_MspInit函數進行重寫。到這裏,也能看書HAL庫的優越性,用戶只需在msp.c中對要實現的函數進行重寫,調用相關函數既可實現。

 

串口初始化完成後,下一步就是實現串口的收發數據,輪詢發送很簡單,上一篇就實現了。這裏主要研究下串口的中斷接收,和中斷接收有關的函數有下面幾個:

1、HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

     函數有是三個參數,分別是串口結構體,要傳輸的數據指針以及待傳輸數據的大小,這其實是對中斷接收的一個配置函數,指定當接收到Size大小的字節後就產生一次中斷進入中斷處理。對比以前的庫函數的串口接收協議,可以將這裏的Size設置爲1,也就是每次接收一個字節就產生一次中斷,並將數據存儲到pData指向的地址中。這就類似於庫函數中的每次中斷將數據賦值給臨時變量res。需要注意的是,這個函數調用一次只適用於一次中斷,如果要連續接收數據的話應該在重寫函數中調用它。

2、USART1_IRQHandler(void)、HAL_UART_IRQHandler(&huart1)

     第一個是在it.c中的通用的硬件中斷入口函數,其中在裏面調用了HAL_UART_IRQHandler(&huart1),也就進入了UART1的中斷處理,HAL_UART_IRQHandler函數在stm32f0xx_hal_uart.c文件中,主要進行中斷標誌的判定,當判定接收到數據時,調用UART_Receive_IT(huart)函數。

3、HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)

     這個函數也在stm32f0xx_hal_uart.c中,這纔是真正的處理數據的函數,讀取接收寄存器,將數據賦值給結構體huart的pRxBuffer並清除中斷標誌,而在裏面還調用了一個函數HAL_UART_RxCpltCallback(huart);

4、__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

    這個是用戶真正可以進行重寫實現自己所需功能的函數,在msp.c中將其重寫。前面我們設置了參數使得每接收一個字節就產生中斷,於是可以重寫這個函數,在裏面將每次接收到的數據存放在自己定義的UART1RXBuffer中。另外,上面有提到配置中斷參數的函數 HAL_UART_Receive_IT()每次調用僅適用於一次中斷,如果要實現連續採用中斷接收數據,也要這個函數中調用HAL_UART_Receive_IT()。因爲這個回調函數是每次中斷髮生都會調用,也就相當於每次發生中斷處理完數據後又將中斷打開,從而實現連續中斷接收數據。

 

總結下整個邏輯就是:

1、初始化UART1

2、調用HAL_UART_Receive_IT(&huart1,&RxData,1)

3、在msp.c中重寫HAL_UART_RxCpltCallback

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	UART1RxBuffer[receive_count++] = RxData;
	HAL_UART_Transmit(huart,&RxData,1,10);
	HAL_UART_Receive_IT(huart,&RxData,1);
}

 

實驗時如何保證HAL庫的完整性是一個值得重視的問題。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章