一、前言 1、簡介 在上一篇UART詳解中,已經有了關於UART的詳細介紹了,也有關於如何使用STM32CubeMX來配置UART的操作了,而在該篇博客,主要會講解一下如何實現UART串口的發送功能。 2、UART簡介 嵌入式開發中,UART串口通信協議是我們常用的通信協議之一,全稱叫做通用非同步收發 ...
一、前言
1、簡介
在上一篇UART詳解中,已經有了關於UART的詳細介紹了,也有關於如何使用STM32CubeMX來配置UART的操作了,而在該篇博客,主要會講解一下如何實現UART串口的發送功能。
2、UART簡介
嵌入式開發中,UART串口通信協議是我們常用的通信協議之一,全稱叫做通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter)。
3、準備工作
在UART詳解中已經有了詳細的說明,在這裡就不說明瞭。
註:
建議每次編寫好一個相關功能且測試功能成功使用後,保存並壓縮成一份Demo常式,方便日後有需要的時候可以直接使用。
例如:
二、CubeMx配置及函數說明
說明:
這篇用到的配置跟UART詳解里的配置都相同,可以按照UART詳解來配置好時鐘、UART即可。
所以在進行下一步之前,先確保已經按照UART詳解的配置步驟配置好了,然後再進行後面的操作。
1、CubeMx配置
按照上一篇UART詳解來配置
2、函數說明
1)CubeMX生成的UART初始化(在usart.c中)
1 UART_HandleTypeDef huart1;
2
3 /* USART1 init function */
4
5 void MX_USART1_UART_Init(void)
6 {
7
8 huart1.Instance = USART1;
9 huart1.Init.BaudRate = 115200;
10 huart1.Init.WordLength = UART_WORDLENGTH_8B;
11 huart1.Init.StopBits = UART_STOPBITS_1;
12 huart1.Init.Parity = UART_PARITY_NONE;
13 huart1.Init.Mode = UART_MODE_TX_RX;
14 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
15 huart1.Init.OverSampling = UART_OVERSAMPLING_16;
16 if (HAL_UART_Init(&huart1) != HAL_OK)
17 {
18 Error_Handler();
19 }
20
21 }
22
23 void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
24 {
25
26 GPIO_InitTypeDef GPIO_InitStruct = {0};
27 if(uartHandle->Instance==USART1)
28 {
29 /* USER CODE BEGIN USART1_MspInit 0 */
30
31 /* USER CODE END USART1_MspInit 0 */
32 /* USART1 clock enable */
33 __HAL_RCC_USART1_CLK_ENABLE();
34
35 __HAL_RCC_GPIOA_CLK_ENABLE();
36 /**USART1 GPIO Configuration
37 PA9 ------> USART1_TX
38 PA10 ------> USART1_RX
39 */
40 GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
41 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
42 GPIO_InitStruct.Pull = GPIO_PULLUP;
43 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
44 GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
45 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
46
47 /* USER CODE BEGIN USART1_MspInit 1 */
48
49 /* USER CODE END USART1_MspInit 1 */
50 }
51 }
52
53 void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
54 {
55
56 if(uartHandle->Instance==USART1)
57 {
58 /* USER CODE BEGIN USART1_MspDeInit 0 */
59
60 /* USER CODE END USART1_MspDeInit 0 */
61 /* Peripheral clock disable */
62 __HAL_RCC_USART1_CLK_DISABLE();
63
64 /**USART1 GPIO Configuration
65 PA9 ------> USART1_TX
66 PA10 ------> USART1_RX
67 */
68 HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
69
70 /* USER CODE BEGIN USART1_MspDeInit 1 */
71
72 /* USER CODE END USART1_MspDeInit 1 */
73 }
74 }
USART init
2)HAL庫函數HAL_UART_Transmit(在stm32f4xx_hal_uart.c中)
說明:
該函數能夠通過huart串口發送Size位pData數據。
參數說明:
huart :選擇用來發送的UART串口
pData :指向將要發送的數據的指針
Size :發送數據的大小
Timeout:超時時間
1 /**
2 * @brief Sends an amount of data in blocking mode.
3 * @param huart Pointer to a UART_HandleTypeDef structure that contains
4 * the configuration information for the specified UART module.
5 * @param pData Pointer to data buffer
6 * @param Size Amount of data to be sent
7 * @param Timeout Timeout duration
8 * @retval HAL status
9 */
10 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
11 {
12 uint16_t *tmp;
13 uint32_t tickstart = 0U;
14
15 /* Check that a Tx process is not already ongoing */
16 if (huart->gState == HAL_UART_STATE_READY)
17 {
18 if ((pData == NULL) || (Size == 0U))
19 {
20 return HAL_ERROR;
21 }
22
23 /* Process Locked */
24 __HAL_LOCK(huart);
25
26 huart->ErrorCode = HAL_UART_ERROR_NONE;
27 huart->gState = HAL_UART_STATE_BUSY_TX;
28
29 /* Init tickstart for timeout managment */
30 tickstart = HAL_GetTick();
31
32 huart->TxXferSize = Size;
33 huart->TxXferCount = Size;
34 while (huart->TxXferCount > 0U)
35 {
36 huart->TxXferCount--;
37 if (huart->Init.WordLength == UART_WORDLENGTH_9B)
38 {
39 if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
40 {
41 return HAL_TIMEOUT;
42 }
43 tmp = (uint16_t *) pData;
44 huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
45 if (huart->Init.Parity == UART_PARITY_NONE)
46 {
47 pData += 2U;
48 }
49 else
50 {
51 pData += 1U;
52 }
53 }
54 else
55 {
56 if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
57 {
58 return HAL_TIMEOUT;
59 }
60 huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
61 }
62 }
63
64 if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
65 {
66 return HAL_TIMEOUT;
67 }
68
69 /* At end of Tx process, restore huart->gState to Ready */
70 huart->gState = HAL_UART_STATE_READY;
71
72 /* Process Unlocked */
73 __HAL_UNLOCK(huart);
74
75 return HAL_OK;
76 }
77 else
78 {
79 return HAL_BUSY;
80 }
81 }
HAL_UART_Transmit
三、代碼部分:實現UART發送
1、直接發送
1)在main主函數中定義一個數組
1 /* USER CODE BEGIN 1 */ 2 unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //數組內十六進位代表“ABCDE” 3 /* USER CODE END 1 */
2)在main主函數中的while迴圈中調用HAL庫UART發送函數
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* UART發送 */ HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff); /* 延遲1s */ HAL_Delay(1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
整個main函數如下:
1 int main(void) 2 { 3 /* USER CODE BEGIN 1 */ 4 unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //數組內十六進位代表“ABCDE” 5 /* USER CODE END 1 */ 6 7 8 /* MCU Configuration--------------------------------------------------------*/ 9 10 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 11 HAL_Init(); 12 13 /* USER CODE BEGIN Init */ 14 15 /* USER CODE END Init */ 16 17 /* Configure the system clock */ 18 SystemClock_Config(); 19 20 /* USER CODE BEGIN SysInit */ 21 22 /* USER CODE END SysInit */ 23 24 /* Initialize all configured peripherals */ 25 MX_GPIO_Init(); 26 MX_USART1_UART_Init(); 27 /* USER CODE BEGIN 2 */ 28 29 /* USER CODE END 2 */ 30 31 /* Infinite loop */ 32 /* USER CODE BEGIN WHILE */ 33 while (1) 34 { 35 /* UART發送 */ 36 HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff); 37 /* 延遲1s */ 38 HAL_Delay(1000); 39 /* USER CODE END WHILE */ 40 41 /* USER CODE BEGIN 3 */ 42 } 43 /* USER CODE END 3 */ 44 }
3)編譯、下載燒寫
4)實現效果(在PC端串口助手中顯示發送成功)
2、字元串發送
說明:
前面的發送方式,不僅要傳入句柄參數,還有數組、長度、超時時間參數。
為了簡便發送,我們可以專門寫一個字元串發送函數,可以直接傳入一個數組即可發送,可以更簡便地實現字元串發送。
優點是,發送數據更簡便,能夠一次性發送很長的數據數組。
但缺點就是不能控制發送的長度,會將整個數據數組發出。
1)在Uart.c中添加vUser_UART_SendString函數
1 /* USER CODE BEGIN 1 */ 2 void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData) 3 { 4 /* -1- 判斷數據是否發送完畢 */ 5 while(*uData) //若為空即發送完畢,若不為空則還有數據 6 { 7 /* -2- 發送1Byte */ 8 HAL_UART_Transmit(uartHandle, uData, 1, 0xffff); 9 /* -3- 移至下1Byte */ 10 uData++; 11 } 12 } 13 /* USER CODE END 1 */
2)在Uart.h中聲明一下vUser_UART_SendString函數(聲明後就可以在別的地方調用該函數)
1 /* USER CODE BEGIN Prototypes */ 2 extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData); 3 /* USER CODE END Prototypes */
3)在main主函數中定義一個數組
1 /* USER CODE BEGIN 1 */ 2 unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!"; 3 /* USER CODE END 1 */
4)在main主函數的while迴圈中調用字元串發送函數
1 /* Infinite loop */ 2 /* USER CODE BEGIN WHILE */ 3 while (1) 4 { 5 /* 字元串發送 */ 6 vUser_UART_SendString(&huart1, uTx_Data); 7 /* 延遲1s */ 8 HAL_Delay(1000); 9 /* USER CODE END WHILE */ 10 11 /* USER CODE BEGIN 3 */ 12 } 13 /* USER CODE END 3 */
整個main函數如下:
1 int main(void) 2 { 3 /* USER CODE BEGIN 1 */ 4 unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!"; 5 /* USER CODE END 1 */ 6 7 8 /* MCU Configuration--------------------------------------------------------*/ 9 10 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 11 HAL_Init(); 12 13 /* USER CODE BEGIN Init */ 14 15 /* USER CODE END Init */ 16 17 /* Configure the system clock */ 18 SystemClock_Config(); 19 20 /* USER CODE BEGIN SysInit */ 21 22 /* USER CODE END SysInit */ 23 24 /* Initialize all configured peripherals */ 25 MX_GPIO_Init(); 26 MX_USART1_UART_Init(); 27 /* USER CODE BEGIN 2 */ 28 29 /* USER CODE END 2 */ 30 31 /* Infinite loop */ 32 /* USER CODE BEGIN WHILE */ 33 while (1) 34 { 35 /* UART發送 */ 36 vUser_UART_SendString(&huart1, uTx_Data); 37 /* 延遲1s */ 38 HAL_Delay(1000); 39 /* USER CODE END WHILE */ 40 41 /* USER CODE BEGIN 3 */ 42 } 43 /* USER CODE END 3 */ 44 }
5)編譯、下載燒寫
6)實現效果(在PC端串口助手顯示發送成功)
3、printf發送
說明:
這種發送方式就是相當於編寫c語言的時候,在小黑框中列印自己想要列印的東西,我們也可以在串口助手上實現一樣的功能。
由於篇幅長度有限,可能需要後續有空再補上這一發送方式,在這裡先不講解了。
四、結尾
1、總結
這篇博客主要是以上一篇UART詳解為基礎,來實現使用UART來實現發送功能,在這裡簡單講解了兩種發送方式,而在後續如果有機會還會補上第三種printf發送方式的。
如果大家還不清楚UART串口通信協議的,可以閱讀一下上一篇UART詳解。若還有對於此篇博客不懂之處,可在下方留言評論,我會儘快回覆。
2、回顧
3、後續
- UART接收(一日內發佈)
- 待補充
~
~
~
~
感謝閱讀~
歡迎大家關註我的博客,一起分享嵌入式知識~