STM32
直播中

贾熹

7年用户 1627经验值
私信 关注
[问答]

如何利用CubeMx去配置并实现UART通信呢

UART通信是什么?

如何利用CubeMx去配置并实现UART通信呢?

回帖(1)

李玲

2021-12-14 15:32:12
一、前言

1、简介

  在上一篇UART详解中,已经有关于UART的介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会演示一下如何实现UART的详细介绍
2、UART发送简介

  嵌入式中开发,UART通信通信协议是我们常用的协议之一,全称通用异步收发传输器(通用异步收发器)。
3、准备工作

  在UART详解中已经有详细的说明,这里就不说明了。

  注:

    建议每次编写好一个相关功能且测试功能成功使用后,保存并压缩成一份演示例程,方便日后有需要的时候可以直接使用。
    例如:
  





二、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


  说明:

    该函数能够通过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)在主主函数中定义一个数组


/* USER CODE BEGIN 1 */
unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //数组内十六进制代表“ABCDE”
/* USER CODE END 1 */


2)在主函数中的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 */
整个主要函数如下:

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[] = "rn 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[] = "rn 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发送


  说明:

    。这种发送方式就是相当于编写Ç语言的时候,在小黑框中打印自己想要打印的东西,也。我们可以在串口助手上实现一样的功能
    由于篇幅长度有限,可能需要后续有空再补上这个发送方式,这里先不讲解了。

四、总结

1 、总结这篇

  主要博客是上一篇UART详解为基础,来实现使用UART来实现发送功能,快速讲解了两种发送方式,而在等有机会补上第三篇种
  打印f发送方式的。如果大家还通过UART 通信协议的,可以看一下上一篇UART 详解。若还有此篇博客看不懂,可在下方留言评论,我会尽快回复。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分