打印
[应用相关]

一例使用STM32外设库设置串口速度与实际不一样的解决

[复制链接]
1327|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
奥德赛|  楼主 | 2015-9-29 11:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近手上有了块金牛的stm32实验板,兴致勃勃的测试各种功能,但是碰到一个问题,用stm32的外设库写串口程序,发现串口速度与实际不一样。一度怀疑是外设库的问题,但是用mdk的外设监控查看后,发现实际的串口速度为自定义的3倍,如图
很疑惑,本人有一种钻牛角尖的精神,因此一度debug下去,发现这个设置是在如下关键语句(位于 外设库中的 USART_Init定义语句,在stm32f10x_usart.c中)
USART_Init初始化函数
RCC_GetClocksFreq(&RCC_ClocksStatus);
  if (usartxbase == USART1_BASE)
  {
    apbclock = RCC_ClocksStatus.PCLK2_Frequency;
  }
  else
  {
    apbclock = RCC_ClocksStatus.PCLK1_Frequency;
  }
  
  integerdivider = ((0x19 * apbclock) / (0x04 * (USART_InitStruct->USART_BaudRate)));
  tmpreg = (integerdivider / 0x64) << 0x04;
  
  fractionaldivider = integerdivider - (0x64 * (tmpreg >> 0x04));
  tmpreg |= ((((fractionaldivider * 0x10) + 0x32) / 0x64)) & ((uint8_t)0x0F);
  
  USARTx->BRR = (uint16_t)tmpreg;



沙发
boy1990| | 2015-9-29 11:26 | 只看该作者
实际的串口速度为自定义的3倍??这也太奇怪了吧...

使用特权

评论回复
板凳
奥德赛|  楼主 | 2015-9-29 11:27 | 只看该作者
其中,最关键的是在
apbclock = RCC_ClocksStatus.PCLK2_Frequency;

这一句,其他都以此来进行加减乘除得到相应的寄存器数值,debug的时候发现这个值为16M,但是,我本人的外部晶振是25M,经过pll倍频后市50M,和这个不一样。怀疑自己是不是记错了apb时钟的来源,拿出官方pdf,如图

是没错的,但是,这个apbclock是怎么得出的16兆的,继续深入stm32f10x_rcc.c里面RCC_GetClocksFreq定义查看,查看到如下结果
switch (tmp)
  {
    case 0x00:  
      RCC_Clocks->SYSCLK_Frequency = HSI_Value;
      break;
    case 0x04:  
      RCC_Clocks->SYSCLK_Frequency = HSE_Value;
      break;
    case 0x08:  

      
      pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
      pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
我是采用外部晶振作为系统时钟的,也就是这里的case 0x04,
RCC_Clocks->SYSCLK_Frequency = HSE_Value;

来源于此HSE_Value;查看默认的采用外部晶振的定义是8000000,也就是说,如果你的系统的外部晶振不是8M,这个速度计算就会错,我的系统是25兆,差了接近三倍,与检测到的错误速度一致,用查找搜索HSE_Value的定义,改成25000000就好了。系统完美运行,这算是这几天一直迷惑有了一个完美的答案吧
我图方便是把整个项目的HSI_Value都改成了2500000,大家可以去stm32f10x.h里修改。





使用特权

评论回复
地板
gejigeji521| | 2015-9-29 13:13 | 只看该作者
不一样是不是哪儿没有修改到位,看看楼主怎么说

使用特权

评论回复
5
55854234| | 2015-9-29 13:28 | 只看该作者
楼主说的很对 ,就是HSE_Value的值要跟实际的外部晶振的值一样,要不然 系统算出来是错误的

使用特权

评论回复
6
lefeng| | 2015-9-30 10:15 | 只看该作者
#define HSE_Value    ((u32)12000000)
这个就是用来定义时钟 的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

397

帖子

3

粉丝