最近手上有了块金牛的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;
其中,最关键的是在
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里修改。
阅读(2861) | 评论(0) | 转发(0) |