你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于STM32L476时钟设置使得串口波特率加倍问题

[复制链接]
天堂隔壁 提问时间:2017-9-9 14:49 /
悬赏10ST金币未解决
如题,第一次玩STM32L476,从网上下载了1个串口例程,波特率设置9600后,没问题,然后自己配置时钟(使用外部有源晶振),输出时钟都一样,比特率设置9600后,实际波特率竟然是19200.。。 实在找不到问题了,下面是代码。屏蔽的部分是9600波特率正常,没屏蔽的是实际是19200.
  1. void SystemClock_Config12(void)
  2. {
  3.         RCC_OscInitTypeDef RCC_OscInitStruct;
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  5.   RCC_PeriphCLKInitTypeDef PeriphClkInit;

  6.     /**Initializes the CPU, AHB and APB busses clocks
  7.     */
  8.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  9.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  10.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  11.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  12.   RCC_OscInitStruct.PLL.PLLM = 1;
  13.   RCC_OscInitStruct.PLL.PLLN = 10;
  14.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  15.   RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  16.   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  17.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  18.   {
  19.     _Error_Handler(__FILE__, __LINE__);
  20.   }

  21.     /**Initializes the CPU, AHB and APB busses clocks
  22.     */

  23.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  24.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  25.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  26.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  27.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  28.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  29.   {
  30.     _Error_Handler(__FILE__, __LINE__);
  31.   }

  32.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  33.   PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  34.   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  35.   {
  36.     _Error_Handler(__FILE__, __LINE__);
  37.   }


  38. //        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  39. //  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  40. //  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  41. //        RCC_OscInitStruct.MSICalibrationValue = 0;
  42. //  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  43. //  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  44. //  RCC_OscInitStruct.PLL.PLLM = 1;
  45. //  RCC_OscInitStruct.PLL.PLLN = 40;
  46. //  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  47. //  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  48. //  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  49. //  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  50. //  {
  51. //    _Error_Handler(__FILE__, __LINE__);
  52. //  }
  53. //       
  54. //        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  55. //  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  56. //  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  57. //  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  58. //  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  59. //  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  60. //  {
  61. //    _Error_Handler(__FILE__, __LINE__);
  62. //  }

  63. //  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  64. //  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  65. //  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  66. //  {
  67. //    _Error_Handler(__FILE__, __LINE__);
  68. //  }
  69. }
复制代码


收藏 2 评论10 发布时间:2017-9-9 14:49

举报

10个回答
疯de_恒 回答时间:2018-1-19 09:08:30
不应该是先配置好时钟再去配置串口的么?我记得串口配置波特率里有用到当前的系统时钟,如果你配置串口时系统时钟的值时旧的,肯定是按旧的时钟达到9600,但是你后面又改了时间,串口又不知道,天知道波特率会变成怎么样。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

chrome777 回答时间:2018-1-19 09:50:14
我在使用的时候好像没这个问题。
你波特率不对。应该是时钟频率不对,原来配置的PCLK2是80M的,你先把时钟频率改成80M试试,
(HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);可以在PA8脚输出系统时钟波形,你可以看下是否是80M。)

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

大碗刚 回答时间:2018-1-19 09:51:38
下图是STM32L476的时钟树,我觉得你需要先确定外部晶振的频率是多少MHz,之后分别配置系统时钟和AHB、APB时钟。注释的代码里有使用MSI时钟为系统时钟,也有选择HSE时钟为系统时钟,可能是这个产生的原因,可以修改试一试。
1.png

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

wenyangzeng 回答时间:2018-1-19 09:52:15
无标题.png

如果外部晶振频率为8MHZ时,系统时钟的配置如下:

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;


红色部分与楼主的配置有所不同

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

随风飘扬 回答时间:2018-1-19 09:52:17
我建议在确认一遍时钟的计算是否正确,同时确认一下 oversampling的设置是16还是8,最好写进程序之后读寄存器,看寄存器的配置

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

队长shiwo 回答时间:2018-1-19 10:02:33
时钟没设置对,可以使用CUBEMX来配置系统时钟和串口的时钟源,我都没遇到过波特率倍增的

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

Inc_brza 回答时间:2018-1-19 10:06:56
百分百代码问题,楼主可以首先通过HAL的GetSystemClock获取当前的各个总线时钟,检查是否正确,
然后再配置一下你的串口模块即可!

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

无薪税绵 回答时间:2018-1-19 14:13:03
屏蔽部分时钟使用的是MSI,
你的代码时钟使用的是HSE,
肯定是系统时钟 、或者时钟分频系数没有设置正确。
请仔细检查对应头文件中的定义。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wolfgang 回答时间:2018-1-19 14:23:22
按顺时钟初始化顺序来,先初始化PPL及系统时钟,然后再使能AHBx的RCC,
注意看RCC_OSCILLATORTYPE_MSI 还是 RCC_OSCILLATORTYPE_HSE 一定要选择好基础震荡频率

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

nyszx 回答时间:2018-1-19 16:40:33
1、首先对楼主的一些建议:想要外设测试样例,不要去网上找,网上的根本没保证,就简单最可靠的就是去STM32CubeMX库里面找每个系列都对应的官方开发板,都有外设的驱动样例。以STM32L476RG-Nucleo为例,打开里面有很多代码可以学习参考:
QQ截图20180119161723.jpg
各种外设驱动样例:
QQ截图20180119161713.jpg
2、其次,楼主只贴了RCC代码,无法明确问题原因,只能帮楼主分析下,如果使用完整的HAL驱动的话,串口初始化,会执行底层的HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart)函数,里面会获取UART时钟源,并根据时钟源去查找系统当前时钟,进而进行波特率等更时钟相关的寄存器设置,而程序是如何知道系统当前时钟的呢?答案是stm32l4xx_hal_conf.h中定义的,并不是神奇的软件能够自动识别硬件得到的,只是根据RCC寄存器值获取分频、倍频等参数状态+基础时钟(HSE\HSI\LSE\LSI等)计算出来的,关键的就在这些定义上,如:
  1. /* ########################## Oscillator Values adaptation ####################*/
  2. /**
  3.   * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
  4.   *        This value is used by the RCC HAL module to compute the system frequency
  5.   *        (when HSE is used as system clock source, directly or through the PLL).
  6.   */
  7. #if !defined  (HSE_VALUE)
  8.   #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
  9. #endif /* HSE_VALUE */

  10. #if !defined  (HSE_STARTUP_TIMEOUT)
  11.   #define HSE_STARTUP_TIMEOUT    ((uint32_t)100)   /*!< Time out for HSE start up, in ms */
  12. #endif /* HSE_STARTUP_TIMEOUT */

  13. /**
  14.   * @brief Internal Multiple Speed oscillator (MSI) default value.
  15.   *        This value is the default MSI range value after Reset.
  16.   */
  17. #if !defined  (MSI_VALUE)
  18.   #define MSI_VALUE    ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
  19. #endif /* MSI_VALUE */

  20. /**
  21.   * @brief Internal High Speed oscillator (HSI) value.
  22.   *        This value is used by the RCC HAL module to compute the system frequency
  23.   *        (when HSI is used as system clock source, directly or through the PLL).
  24.   */
  25. #if !defined  (HSI_VALUE)
  26.   #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
  27. #endif /* HSI_VALUE */

  28. /**
  29.   * @brief Internal Low Speed oscillator (LSI) value.
  30.   */
  31. #if !defined  (LSI_VALUE)
  32. #define LSI_VALUE  ((uint32_t)32000)       /*!< LSI Typical Value in Hz*/
  33. #endif /* LSI_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
  34.                                              The real value may vary depending on the variations
  35.                                              in voltage and temperature.*/
  36. /**
  37.   * @brief External Low Speed oscillator (LSE) value.
  38.   *        This value is used by the UART, RTC HAL module to compute the system frequency
  39.   */
  40. #if !defined  (LSE_VALUE)
  41.   #define LSE_VALUE    ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
  42. #endif /* LSE_VALUE */

  43. #if !defined  (LSE_STARTUP_TIMEOUT)
  44.   #define LSE_STARTUP_TIMEOUT    ((uint32_t)5000)   /*!< Time out for LSE start up, in ms */
  45. #endif /* HSE_STARTUP_TIMEOUT */

  46. /**
  47.   * @brief External clock source for SAI1 peripheral
  48.   *        This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
  49.   *        frequency.
  50.   */
  51. #if !defined  (EXTERNAL_SAI1_CLOCK_VALUE)
  52.   #define EXTERNAL_SAI1_CLOCK_VALUE    ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/
  53. #endif /* EXTERNAL_SAI1_CLOCK_VALUE */

  54. /**
  55.   * @brief External clock source for SAI2 peripheral
  56.   *        This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
  57.   *        frequency.
  58.   */
  59. #if !defined  (EXTERNAL_SAI2_CLOCK_VALUE)
  60.   #define EXTERNAL_SAI2_CLOCK_VALUE    ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/
  61. #endif /* EXTERNAL_SAI2_CLOCK_VALUE */
复制代码
比如如果你使用外部8M高速晶振,你需要修改HSE_VALUE为8000000,假设你实际使用的外部晶振为12M,而你的HSE_VALUE仍为8000000,系统也会跑起来,但是通过HAL_RCC_GetSysClockFreq()等获取时钟的函数得到的值就不对了。也许这就是问题原因的所在,希望楼主能解决此问题。

评分

参与人数 1蝴蝶豆 +5 收起 理由
zero99 + 5

查看全部评分

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版