首页 > 解决方案 > HAL_UART_Transmit 发送错误数据

问题描述

当 ch = 0x80 时,在 PC 上收到 0x00,
当 ch = 0x40 时,在 PC 上收到 0x80,
当 ch = 0x20 时,在 PC 上收到 0x60,
当 ch = 0x10 时,在 PC 上收到 0x10,
当 ch = 0x08 时,打开PC 我收到 0x08,
当 ch = 0x04,在 PC 上我收到 0x04,
当 ch = 0x02,在 PC 上我收到 0x02,
当 ch = 0x01,在 PC 我收到 0x01,

无法弄清楚这里发生了什么...我正在附加 USART 初始化、传输函数和主函数。我应该是软件问题,已经测试了硬件,没关系。单片机 = STM32L011

void InitUSART(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    USARTx_CLK_ENABLE();

    UartHandle.Instance = USARTx;
    UartHandle.Init.BaudRate = 9600;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = UART_MODE_TX_RX;
    //UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;
    HAL_UART_Init(&UartHandle);

    /* Transmit Configuration */
    USARTx_TX_GPIO_CLK_ENABLE();
    GPIO_InitStruct.Pin = USARTx_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = USARTx_TX_AF;
    HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);

    /* Receive Configuration */
    USARTx_RX_GPIO_CLK_ENABLE();
    GPIO_InitStruct.Pin = USARTx_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = USARTx_TX_AF;
    HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(USARTx_IRQn);
}

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint16_t* tmp;
  uint32_t tickstart = 0;

  /* Check that a Tx process is not already ongoing */
  if(huart->gState == HAL_UART_STATE_READY)
  {
    if((pData == NULL ) || (Size == 0U))
    {
      return  HAL_ERROR;
    }

    /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter 
       should be aligned on a u16 frontier, as data to be filled into TDR will be 
       handled through a u16 cast. */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      if((((uint32_t)pData)&1) != 0)
      {
        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(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
      {
        return HAL_TIMEOUT;
      }
      if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
      {
        tmp = (uint16_t*) pData;
        huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU);
        pData += 2U;
      }
      else
      {
        huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU);
      }
    }
    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;
  }
}

int main(void)
{
  /* STM32L0xx HAL library initialization:
       - Configure the Flash prefetch, Flash preread and Buffer caches
       - Systick timer is configured by default as source of time base, but user
             can eventually implement his proper time base source (a general purpose
             timer for example or other time source), keeping in mind that Time base
             duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
             handled in milliseconds basis.
       - Low Level Initialization
     */
    HAL_Init();

    /* Configure the system clock to 32 MHz */
    SystemClock_Config();

    InitUSART();
    //Transmit(txBuffer, 2);

    extern UART_HandleTypeDef UartHandle;
    uint16_t ch = 0x80;
    TransmitEnable();
    while(1){
        HAL_UART_Transmit(&UartHandle, &ch, 1, 0xFF);
        HAL_Delay(5);
    }
}

标签: cembeddedstm32uart

解决方案


看来这毕竟是一个时钟问题。我正在使用内部 16 MHz 振荡器 (HSI) 乘以 32 MHz 和 PLL。9600 波特率的单波特宽为 110us。现在我切换到 4 MHz(内部 MSI),每波特率为 104us。现在沟通无懈可击。

RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
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)
{
  while(1);
}

__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
__HAL_RCC_PWR_CLK_DISABLE();

推荐阅读