STM32 HAL库串口发送函数HAL_UART_Transmit()分析

STM32 HAL库串口发送函数HAL_UART_Transmit()分析

硬件平台:STM32F103VET6

软件平台:STM32CubeMX 4.22

MDK 5.23

HAL库版本:FW_F1 V1.6.0

以下是分析过程:

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 */
  /*检查有没有一个发送的处理正在运行*/
  /*如果是准备好的状态就判断指针是否为空或者接收到数据的大小是否为0,上述条件满足
   *任意一个就返回错误标志。
   */
  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;
    /*判断数值是否大于0*/
    while(huart->TxXferCount > 0U)
    {
      huart->TxXferCount--;
      /*判断是不是9个字节的长度*/应该是字长是9位数据格式2022.7.20
      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;
        }
      }
      /*不是9个字节长度*/应该是字长是9位数据格式2022.7.20
      else
      {
        /*等待超时标志,如果发送寄存器为空(详见STM32中文参考手册V10),则执行此if函数
         *并返回HAL_TIMEOUT
         */
        if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
        {
          return HAL_TIMEOUT;
        }
       /*将数据送给发送数据移位寄存器*/
        huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
      }
    }
    /*等待超时标志,如果发送还未完成(详见STM32中文参考手册V10),则执行此if函数,并
     *返回HAL_TIMEOUT
     */
    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);
    /*返回HAL_OK成功标志*/
    return HAL_OK;
  }
 /*如果状态不是准备好的状态则返回忙标志*/
  else
  {
    return HAL_BUSY;
  }
}

ST官方手册Description of STM32F1 HAL and Low - layer drivers对于此函数的介绍

这是在写STM32F103VET6基于HAL库(非标准库)关于串口发送时的时候出现了一些问题,将分析函数的过程记录在这里,还会继续更新相关内容。

使用STM32 HAL发送数据非常简单,以下是一个示例代码: ```c #include "stm32f4xx_hal.h" #include <string.h> UART_HandleTypeDef huart2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); char message[] = "Hello World!\r\n"; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); while (1) { HAL_UART_Transmit(&huart2, (uint8_t*)message, strlen(message), HAL_MAX_DELAY); HAL_Delay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 上述代码使用了USART2串口发送数据,并且每隔一秒发送一次“Hello World!”。使用 `HAL_UART_Transmit` 函数将数据发送串口缓冲区。其中,第一个参数是串口句柄,第二个参数是发送的数据,第三个参数是数据长度,第四个参数是发送超时时间。 需要注意的是,在使用串口发送数据前,需要先初始化串口,这里使用了 `MX_USART2_UART_Init` 函数对USART2进行了初始化。 另外,还需要注意的是,使用串口发送数据时,需要等待数据发送完毕后再进行下一次发送,否则可能会发生数据丢失的情况。可以使用 `HAL_UART_Transmit` 函数的返回值来判断数据是否发送完毕。此外,还可以使用中断方式发送数据,这里不再赘述。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值