一, 前言
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 中)
- UART_HandleTypeDef huart1;
- /* USART1 init function */
- void MX_USART1_UART_Init(void)
- {
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- }
- void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(uartHandle->Instance==USART1)
- {
- /* USER CODE BEGIN USART1_MspInit 0 */
- /* USER CODE END USART1_MspInit 0 */
- /* USART1 clock enable */
- __HAL_RCC_USART1_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- /**USART1 GPIO Configuration
- PA9 ------> USART1_TX
- PA10 ------> USART1_RX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* USER CODE BEGIN USART1_MspInit 1 */
- /* USER CODE END USART1_MspInit 1 */
- }
- }
- void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
- {
- if(uartHandle->Instance==USART1)
- {
- /* USER CODE BEGIN USART1_MspDeInit 0 */
- /* USER CODE END USART1_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_USART1_CLK_DISABLE();
- /**USART1 GPIO Configuration
- PA9 ------> USART1_TX
- PA10 ------> USART1_RX
- */
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
- /* USER CODE BEGIN USART1_MspDeInit 1 */
- /* USER CODE END USART1_MspDeInit 1 */
- }
- }
- USART init
2)HAL 库函数 HAL_UART_Transmit(在 stm32f4xx_hal_uart.c 中)
说明:
该函数能够通过 huart 串口发送 Size 位 pData 数据.
参数说明:
huart : 选择用来发送的 UART 串口
pData : 指向将要发送的数据的指针
Size : 发送数据的大小
Timeout: 超时时间
- /**
- * @brief Sends an amount of data in blocking mode.
- * @param huart Pointer to a UART_HandleTypeDef structure that contains
- * the configuration information for the specified UART module.
- * @param pData Pointer to data buffer
- * @param Size Amount of data to be sent
- * @param Timeout Timeout duration
- * @retval HAL status
- */
- HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
- {
- uint16_t *tmp;
- uint32_t tickstart = 0U;
- /* Check that a Tx process is not already ongoing */
- if (huart->gState == HAL_UART_STATE_READY)
- {
- if ((pData == NULL) || (Size == 0U))
- {
- return HAL_ERROR;
- }
- /* Process Locked */
- __HAL_LOCK(huart);
- huart->ErrorCode = HAL_UART_ERROR_NONE;
- huart->gState = HAL_UART_STATE_BUSY_TX;
- /* Init tickstart for timeout managment */
- tickstart = HAL_GetTick();
- huart->TxXferSize = Size;
- huart->TxXferCount = Size;
- while (huart->TxXferCount> 0U)
- {
- huart->TxXferCount--;
- if (huart->Init.WordLength == UART_WORDLENGTH_9B)
- {
- if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
- {
- return HAL_TIMEOUT;
- }
- tmp = (uint16_t *) pData;
- huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
- if (huart->Init.Parity == UART_PARITY_NONE)
- {
- pData += 2U;
- }
- else
- {
- pData += 1U;
- }
- }
- else
- {
- if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
- {
- return HAL_TIMEOUT;
- }
- huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
- }
- }
- if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
- {
- return HAL_TIMEOUT;
- }
- /* At end of Tx process, restore huart->gState to Ready */
- huart->gState = HAL_UART_STATE_READY;
- /* Process Unlocked */
- __HAL_UNLOCK(huart);
- return HAL_OK;
- }
- else
- {
- return HAL_BUSY;
- }
- }
- HAL_UART_Transmit
三, 代码部分: 实现 UART 发送
1, 直接发送
1) 在 main 主函数中定义一个数组
- /* USER CODE BEGIN 1 */
- unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; // 数组内十六进制代表 "ABCDE"
- /* 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 函数如下:
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; // 数组内十六进制代表 "ABCDE"
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- /* USER CODE END 2 */
- /* 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 */
- }
3) 编译, 下载烧写
4) 实现效果 (在 PC 端串口助手中显示发送成功)
2, 字符串发送
说明:
前面的发送方式, 不仅要传入句柄参数, 还有数组, 长度, 超时时间参数.
为了简便发送, 我们可以专门写一个字符串发送函数, 可以直接传入一个数组即可发送, 可以更简便地实现字符串发送.
优点是, 发送数据更简便, 能够一次性发送很长的数据数组.
但缺点就是不能控制发送的长度, 会将整个数据数组发出.
1) 在 Uart.c 中添加 vUser_UART_SendString 函数
- /* USER CODE BEGIN 1 */
- void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData)
- {
- /* -1- 判断数据是否发送完毕 */
- while(*uData) // 若为空即发送完毕, 若不为空则还有数据
- {
- /* -2- 发送 1Byte */
- HAL_UART_Transmit(uartHandle, uData, 1, 0xffff);
- /* -3- 移至下 1Byte */
- uData++;
- }
- }
- /* USER CODE END 1 */
2) 在 Uart.h 中声明一下 vUser_UART_SendString 函数 (声明后就可以在别的地方调用该函数)
- /* USER CODE BEGIN Prototypes */
- extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData);
- /* USER CODE END Prototypes */
3) 在 main 主函数中定义一个数组
- /* USER CODE BEGIN 1 */
- unsigned char uTx_Data[] = "\r\n Hallo World! 你好, 世界!";
- /* USER CODE END 1 */
4) 在 main 主函数的 while 循环中调用字符串发送函数
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* 字符串发送 */
- vUser_UART_SendString(&huart1, uTx_Data);
- /* 延迟 1s */
- HAL_Delay(1000);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
整个 main 函数如下:
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- unsigned char uTx_Data[] = "\r\n Hallo World! 你好, 世界!";
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* UART 发送 */
- vUser_UART_SendString(&huart1, uTx_Data);
- /* 延迟 1s */
- HAL_Delay(1000);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
5) 编译, 下载烧写
6) 实现效果 (在 PC 端串口助手显示发送成功)
3,printf 发送
说明:
这种发送方式就是相当于编写 c 语言的时候, 在小黑框中打印自己想要打印的东西, 我们也可以在串口助手上实现一样的功能.
由于篇幅长度有限, 可能需要后续有空再补上这一发送方式, 在这里先不讲解了.
四, 结尾
1, 总结
这篇博客主要是以上一篇 UART 详解为基础, 来实现使用 UART 来实现发送功能, 在这里简单讲解了两种发送方式, 而在后续如果有机会还会补上第三种 printf 发送方式的.
如果大家还不清楚 UART 串口通信协议的, 可以阅读一下上一篇 UART 详解. 若还有对于此篇博客不懂之处, 可在下方留言评论, 我会尽快回复.
2, 回顾
UART 详解
3, 后续
UART 接收 (一日内发布)
待补充
~
~
~
~
来源: https://www.cnblogs.com/ChurF-Lin/p/10798193.html