历史上的今天

今天是:2024年08月28日(星期三)

正在发生

2018年08月28日 | 关于STM32F107RCT6使用8M晶振串口波特率错误的问题

发布者:创意驿站 来源: eefocus关键字:STM32F107RCT6  8M晶振  串口波特率 手机看文章 扫描二维码
随时随地手机看文章

发现问题

这段时间在学习FreeRTOS,今天移植成功后,写了2个任务。一个是LED每隔1s闪烁任务,另一个是使用UART4每隔100ms发送字符串任务。下载成功后,发现LED闪烁间隔不对,串口打印间隔时间也不对。当时就很纳闷了:RCC是按标准库的例子来配置的,FreeRTOS的系统节拍也是配置正确的,不可能会出现这种问题。后来,仔细排查,用示波器测试串口的波形发现一个问题:程序代码配置的是115200波特率,但实际输出波形算出来是38400,相差3倍。到这就开始怀疑RCC配置了,这时,我把MCO引脚打开,让其出示SYSCLK时钟,示波器上面反应的是72MH。接着又让它输出APB1CLK时钟,是正常的36MHz。调试到这里就感觉莫名其妙了,后来仔细查看RCC配置代码,发现官方例子是使用的25MHz的晶振,于是我换上25Mhz,重算了下分频系数等。烧写后,就变正常了。这里说下官网的例子模板

问题解决

STM32F107的时钟树

这里写图片描述
从图中可以看出,STM32F107的SYSCLK时钟有2条配置路线。第一条可以使用8M外部晶振来配置系统72MHz。第二条可以使用25M外部晶振来配置系统72MHz时钟。起出使用的是第一条路线,系统时钟也是正确配置成72MHz了,但是串口时钟是不正确的(其实是HSE_VALUE值没修改)。换成25MHz晶振,按第二条线路配置后,串口就正常了

官方RCC配置例子代码


void RCC_Configuration(void)

{

 RCC_ClocksTypeDef RCC_ClockFreq;


   /* RCC system reset(for debug purpose) */

  RCC_DeInit();


  /* Enable HSE */

  RCC_HSEConfig(RCC_HSE_ON);


  /* Wait till HSE is ready */

  HSEStartUpStatus = RCC_WaitForHSEStartUp();


  if(HSEStartUpStatus != ERROR)

  {

    /* Enable Prefetch Buffer */

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


 /****************************************************************/

 /*      HSE=25MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz         */

 /****************************************************************/

    /* Flash 2 wait state */

    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */

    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */

    RCC_PCLK1Config(RCC_HCLK_Div2);

    /*  ADCCLK = PCLK2/4 */

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);


    /* Configure PLLs *********************************************************/

    /* PPL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

    RCC_PREDIV2Config(RCC_PREDIV2_Div5);

    RCC_PLL2Config(RCC_PLL2Mul_8);


    /* Enable PLL2 */

    RCC_PLL2Cmd(ENABLE);


    /* Wait till PLL2 is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)

    {}


    /* PPL1 configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */

    RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);


    /* Enable PLL */

    RCC_PLLCmd(ENABLE);


    /* Wait till PLL is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {}


    /* Select PLL as system clock source */

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


    /* Wait till PLL is used as system clock source */

    while (RCC_GetSYSCLKSource() != 0x08)

    {}

  }


  RCC_GetClocksFreq(&RCC_ClockFreq);


  /* Enable USART2 clock */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);    



  /* Enable ETHERNET clock  */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx |

                        RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);


  /* Enable GPIOs clocks */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |

                         RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO, ENABLE);

  /* Enable ADC1 clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

}


可以发现官方的例子代码是使用25MHz外部晶振来配置的系统时钟,我在官方的代码基础上修改我的8M晶振配置就不能正常运行


我修改的代码


void bsp_RCC_Init(void)

{

 RCC_ClocksTypeDef RCC_ClockFreq;


   /* RCC system reset(for debug purpose) */

  RCC_DeInit();



  /* Enable HSE */

  RCC_HSEConfig(RCC_HSE_ON);


  /* Wait till HSE is ready */

  if(RCC_WaitForHSEStartUp() != ERROR)

  {

    /* Enable Prefetch Buffer */

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


 /****************************************************************/

 /*      HSE=8MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz         */

 /****************************************************************/

    /* Flash 2 wait state */

    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */

    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */

    RCC_PCLK1Config(RCC_HCLK_Div2);

    /*  ADCCLK = PCLK2/4 */

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);


    /* Configure PLLs *********************************************************/

    /* PPL2 configuration: PLL2CLK = (HSE / 2) * 10 = 40 MHz */

    RCC_PREDIV2Config(RCC_PREDIV2_Div2);

    RCC_PLL2Config(RCC_PLL2Mul_10);


    /* Enable PLL2 */

    RCC_PLL2Cmd(ENABLE);


    /* Wait till PLL2 is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)

    {}


    /* PPL1 configuration: PLLCLK = (HSE / 1) * 9 = 72 MHz */

    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);


    /* Enable PLL */

    RCC_PLLCmd(ENABLE);


    /* Wait till PLL is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {}


    /* Select PLL as system clock source */

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


    /* Wait till PLL is used as system clock source */

    while (RCC_GetSYSCLKSource() != 0x08)

    {}

  }

 }

上面我修改的代码使用后就出现了串口波特率错误的问题。在keil调试查看寄存器发现UART->BRR的数值与理论计算的不一样。追溯USART_Init()函数配置过程,发现获取的PCLK1时钟频率不是36MHz。这里写图片描述
仔细查询源头代码,发现HSE_VALUE定义的是25000000,这就导致图中RCC_GetClockFreq()函数获取的PCLK1_Frequency的值计算出错。所以需将HSE_VALUE改成8000000。 
这里写图片描述
另一种办法,更换外部8M晶振为25M,修改RCC配置为官方代码,就可以正常运行

总结

STM32F107具有以太网、USB OTG 等网络设备,以太网使用MII接口时需要提供25MHz时钟,STM32F107使用外部25MHz晶振来作为时钟源是最好不过了,官方也推荐使用25MHz。使用8M晶振需要修改HSE_VALUE值为8000000,然后配置相应的PLL时钟了。


关键字:STM32F107RCT6  8M晶振  串口波特率 引用地址:关于STM32F107RCT6使用8M晶振串口波特率错误的问题

上一篇:关于STM32中PA15引脚作为普通io的使用
下一篇:STM32 USART出现乱码

推荐阅读

    子弹短信自8月20日推出之后迅速走红,短短几天时间冲到了苹果App Store下载量第一名。  8月25日晚,锤子科技CEO罗永浩发微博求助:子弹短信在苹果软件商店的下载量太大,被误会有刷榜行为,触发了苹果软件商店的自动验证机制,这导致安装和下载变得非常复杂,给用户造成了不必要的麻烦。快如科技急需跟苹果中国建立顺畅的沟通渠道,请大家帮忙...
摘要:测量对地存在共模电压的信号波形,若测量仪器或测量方法不正确,轻则影响测量结果,重则危害生命财产安全。本文通过典型的两个实例,说明不当的测量方法对结果的影响和可能引起的安全问题,并提出正确的测量方法。 一、实例1 客户的产品是一个压电陶瓷及其驱动电路,图1是产品原理和测试连接图,开关管以约100kHz的频率通断,带抽头的电感实现升压功...
一、实验目的1、学习步进电机驱动原理;2、掌握通过CPU控制步进电机的方法。二、实验内容1、了解步进电机的运行控制;2、了解步进电机运行速度的控制方法;3、了解步进电机运行方向的控制方法。三、实验设备DM2410B十实验系统;PC机;JTTAG仿真器;串口线。2、软件:PC机操作系统(WINDOWS 2000);ARM Developer Suite v1.2;MulTI-ICE V2.2.5;DNW 2410(或...
导读:欧洲电池制造商InoBat公司宣布与美国电池材料供应商Group14 Technologies公司进行合作,将使用Group14的专利硅基负极材料为汽车生产高能量密度的电池。InoBat公司表示,高能量密度电池市场需求飙升,相比传统锂离子电池,硅基负极材料的单位体积能量密度更高。Group14表示,能源部已经认可其“新颖的、可投入使用的纳米材料和可靠的工业规模工艺”...

史海拾趣

问答坊 | AI 解惑

开关死区对SPWM逆变器输出电压波形的影响

开关死区对SPWM逆变器输出电压波形的影响 摘要:分析开关死区对SPWM逆变器输出电压波形的影响,讨论考虑开关死区时的谐波分析方法,并导出谐波计算公式。用计算机辅助分析和实验方法对理想的和实际的SPWM逆变器进行对比研究,得出一些不同于现有理 ...…

查看全部问答∨

ADC0809A/D转换器基本应用技术

基本知识   ADC0809是带有8位A/D转换器、8路多路开关以及微处理机兼容的控制逻辑的CMOS组件。它是逐次逼近式A/D转换器,可以和单片机直接接口。 (1).ADC0809的内部逻辑结构   由上图可知,ADC0809由一个8路模拟开关、一个地址锁存与译 ...…

查看全部问答∨

一个双绞线共电传输的例子

刚好手上有30米的双绞线 没事做了个试验  双绞线和 电源一起使用双绞线传输 可能使用的双绞线质量差了点 传输出来的图像没 同轴电缆 75-3 效果好 要差点 由于采集卡效果差 不要见怪 …

查看全部问答∨

有没有4路16位A/D转换芯片

有没有4路16位A/D转换芯片?请问哪款性价比好点?…

查看全部问答∨

哪位用过TSC2006的内部温度传感器?

TSC2006,内部有一个温度传感器,可以测量温度。 哪位大侠用过,能否告知一下如何使用,或者附上代码,谢谢了。…

查看全部问答∨

ARM7的动态分配内存问题

我用的LPC2138芯片,开发软件是ADS 程序如下: int main(void) {         uint8 flag = 0;             sys = (SYS_TYPE *) malloc(sizeof(SYS_TYPE));      &nb ...…

查看全部问答∨

platformbuilder编译错误,请高手指点,谢谢啦!

这是build.err的内容 D:\\WINCE500\\build.log(1) : error SYSGEN0000: error(s) in sysgen phase 这是build.log的内容 Starting sysgen phase for project ( common ) Found localized resources for Languages ( 0404 0407 040C 0410 0411 ...…

查看全部问答∨

在win32的工程中如何弹出一个提示框?

RT,就是点击一个按钮后弹出的只有OK键的那种对话框, 小弟对win32不熟悉,望各位详细讲解,谢谢, 另外,想问一下,因为是做手机应用软件的开发, 看一些教程都是用MFC的一个工程去做,为什么我们这用win32呢, 这两个开发手机应用软件有什么 ...…

查看全部问答∨

STM32学习

我们学校哪位老师嵌入式牛啊?带带我呢?简单入门就OK! 我现在在学习基于Cortex-m3 的STM32单片机!选择这个如何啊?…

查看全部问答∨

大容量发电机应采用负序反时限过流保护

负荷或系统的不对称,引起负序电流流过发电机定子绕组,并在发电机空气隙中建立负序旋转磁场,使转子感应出两倍频率的电流,引起转子发热。大型发电机由于采用了直接冷却式(水内冷和氢内冷),使其体积增大比容量增大要小,同时,基于经济和技术上的 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved