基於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中)

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、回顧

1)UART詳解

3、後續

1)UART接收

2)待補充

~

~

~

~

感謝閱讀~

 歡迎大家關注我的博客(來自博客園),一起分享嵌入式知識~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章