基于STM32之UART串口通信协议发送

Posted churf-lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于STM32之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、后续

  待补充……

~

~

~

~

感谢阅读~

 欢迎大家关注我的博客,一起分享嵌入式知识~

以上是关于基于STM32之UART串口通信协议发送的主要内容,如果未能解决你的问题,请参考以下文章

STM32怎么编写一个串口通信协议

STM32F407-串口学习1(UART协议简介)

基于STM32模拟uart串口通信

STM32串口发送接收数据

STM32学习笔记 二基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发

STM32学习笔记 二基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发