• 基于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[] = "
     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[] = "
     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、回顾

    1)UART详解

    3、后续

    1)UART接收

    2)待补充

    ~

    ~

    ~

    ~

    感谢阅读~

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

  • 相关阅读:
    windows服务创建与管理
    html前端技术:??
    C#整数三种强制类型转换int、Convert.ToInt32()、int.Parse()的区别
    convert转化成特定日期格式
    关于android性能,内存优化(转载)
    不错的Android博客
    十步优化SQL Server中的数据访问(转载)
    数据库SQL优化大总结之 百万级数据库优化方案(转载)
    SQL Server数据库性能优化之SQL语句篇(转载)
    50种方法优化SQL Server数据库查询(转载)
  • 原文地址:https://www.cnblogs.com/ChurF-Lin/p/10798193.html
Copyright © 2020-2023  润新知