ST意法半导体
直播中

梁宏满

8年用户 1057经验值
私信 关注
[问答]

请问STM32H750怎么才能把串口频率设置到2M以上?

经过多次测试,发现用STM32CubeMX生成的串口通信程序,串口波特率设置不能超过2M,如果大于2M在 HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) 这个函数会报错!!

我的波特率设置是这样的
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 2500000;//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_8;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;//UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;


这个是在波特率配置后  usartdiv 不满足条件进入  ret = HAL_ERROR;

    /* USARTDIV must be greater than or equal to 0d16 */
    if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX))
    {
      brrtemp = (uint16_t)(usartdiv & 0xFFF0U);
      brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U);
      huart->Instance->BRR = brrtemp;
    }
    else
    {
      ret = HAL_ERROR;
    }



下面是我的时钟配置

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 2;
  RCC_OscInitStruct.PLL.PLLN = 240;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_USART2
                              |RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_UART7
                              |RCC_PERIPHCLK_FDCAN|RCC_PERIPHCLK_USART1
                              |RCC_PERIPHCLK_UART8|RCC_PERIPHCLK_UART5
                              |RCC_PERIPHCLK_SPI4|RCC_PERIPHCLK_ADC
                              |RCC_PERIPHCLK_I2C4|RCC_PERIPHCLK_LPTIM1
                              |RCC_PERIPHCLK_CKPER;
  PeriphClkInitStruct.CkperClockSelection = RCC_CLKPSOURCE_HSI;
  PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_HSE;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
  PeriphClkInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_D3PCLK1;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}


串口的时钟 有120M ,理论上配置大于2M波特率应该没有问题,为什么实际上我配置后,在HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) 这个函数会报错,?有没有高手解释一下!!

回帖(3)

贾大林

2025-3-3 11:55:54

在STM32H750上实现超过2M波特率的串口通信需注意以下几点:




1. 时钟源与分频计算



  • APB时钟频率:确保USART的时钟源(APB1/APB2)足够高。例如,若目标波特率为2.5Mbps:

    • 若使用过采样8模式USARTDIV = APB_CLK / (8 * BaudRate)

    • 若使用过采样16模式USARTDIV = APB_CLK / (16 * BaudRate)

    • 假设APB2时钟为240MHz,过采样8模式下需USARTDIV = 240e6 / (8*2.5e6) = 12,需满足分频系数≥16(HAL库限制),此时需改用过采样16模式。





2. 修改过采样模式


CubeMX默认可能使用过采样16模式,需手动改为过采样8以支持更高波特率:


   huart1.Init.OverSampling = UART_OVERSAMPLING_8;  // 修改为过采样8


  • 代码中直接配置:在MX_USART1_UART_Init()函数中添加此配置。




3. 调整HAL库的波特率容错检查


若因分频系数过小报错,可修改HAL库的容错阈值(需谨慎):


   // 在stm32h7xx_hal_uart.c中找到以下代码,调整`UART_DIV_SAMPLING8`的容错值
   #define UART_DIV_SAMPLING8(_PCLK_, _BAUD_)
     (((_PCLK_)*2)/((_BAUD_)))  // 修改分频计算容差



4. 直接操作寄存器(绕过HAL限制)


若HAL库限制过严,可直接配置USART寄存器:


   huart1.Instance->BRR = 12;  // 示例:APB=240MHz, 过采样8, 波特率=240e6/(8*12)=2.5Mbps



5. CubeMX配置步骤



  1. 设置APB时钟:在Clock Configuration中确保APB2时钟足够高(如240MHz)。

  2. 选择过采样模式:在USART配置中将Over Sampling设为“8”。

  3. 输入波特率:直接输入2500000,若CubeMX报错则手动修改代码。




6. 验证硬件兼容性



  • 确保物理线路和收发器(如RS485芯片)支持2.5Mbps速率。

  • 检查信号完整性,使用示波器确认波形质量。




示例代码修改


huart1.Instance = USART1;
huart1.Init.BaudRate = 2500000;
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.OverSampling = UART_OVERSAMPLING_8;  // 关键:过采样8
huart1.Init.FIFOMode = UART_FIFOMODE_DISABLE;    // 关闭FIFO以提高速度

通过以上步骤,应能突破2M波特率限制。若仍有问题,建议检查时钟配置或使用示波器验证实际输出波形。

举报

卢鉴冰

2025-3-13 16:21:38
串口通讯牵涉到误码率的问题,波特率越高,误码率越大。如果设置到256000的6位数已经很高了,楼主设置到7位数的2500000有点过头了,STM32CubeMX知道已经超限了。
举报

陈政竹

2025-3-13 16:21:42
检查一下主频设置  是不是主频太低了  2M以上的波特率主频都要求比较高
举报

更多回帖

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