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

[复制链接]
1542|5
 楼主| 奥德赛 发表于 2015-9-29 11:22 | 显示全部楼层 |阅读模式
最近手上有了块金牛的stm32实验板,兴致勃勃的测试各种功能,但是碰到一个问题,用stm32的外设库写串口程序,发现串口速度与实际不一样。一度怀疑是外设库的问题,但是用mdk的外设监控查看后,发现实际的串口速度为自定义的3倍,如图
很疑惑,本人有一种钻牛角尖的精神,因此一度debug下去,发现这个设置是在如下关键语句(位于 外设库中的 USART_Init定义语句,在stm32f10x_usart.c中)
USART_Init初始化函数
  1. RCC_GetClocksFreq(&RCC_ClocksStatus);
  2.   if (usartxbase == USART1_BASE)
  3.   {
  4.     apbclock = RCC_ClocksStatus.PCLK2_Frequency;
  5.   }
  6.   else
  7.   {
  8.     apbclock = RCC_ClocksStatus.PCLK1_Frequency;
  9.   }
  10.   
  11.   integerdivider = ((0x19 * apbclock) / (0x04 * (USART_InitStruct->USART_BaudRate)));
  12.   tmpreg = (integerdivider / 0x64) << 0x04;
  13.   
  14.   fractionaldivider = integerdivider - (0x64 * (tmpreg >> 0x04));
  15.   tmpreg |= ((((fractionaldivider * 0x10) + 0x32) / 0x64)) & ((uint8_t)0x0F);
  16.   
  17.   USARTx->BRR = (uint16_t)tmpreg;



boy1990 发表于 2015-9-29 11:26 | 显示全部楼层
实际的串口速度为自定义的3倍??这也太奇怪了吧...
 楼主| 奥德赛 发表于 2015-9-29 11:27 | 显示全部楼层
其中,最关键的是在
  1. apbclock = RCC_ClocksStatus.PCLK2_Frequency;

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

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

  10.       
  11.       pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
  12.       pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
我是采用外部晶振作为系统时钟的,也就是这里的case 0x04,
  1. 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 来自手机 | 显示全部楼层
不一样是不是哪儿没有修改到位,看看楼主怎么说
55854234 发表于 2015-9-29 13:28 | 显示全部楼层
楼主说的很对 ,就是HSE_Value的值要跟实际的外部晶振的值一样,要不然 系统算出来是错误的
lefeng 发表于 2015-9-30 10:15 | 显示全部楼层
#define HSE_Value    ((u32)12000000)
这个就是用来定义时钟 的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

397

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部