一、前言
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、后续
待补充……
~
~
~
~
感谢阅读~
欢迎大家关注我的博客,一起分享嵌入式知识~
原文地址:https://www.cnblogs.com/ChurF-Lin/p/10798193.html