#申请原创# 问题背景 以前用APM32F103RCT6去替换STM32F105RCT6(为了双CAN功能),但最近有其他方案商朋友反馈,单纯只是修改了CAN2的配置(可以参考论坛里有篇相关帖子,写得挺详细https://bbs.21ic.com/icview-3206858-1-1.html),但CAN还是跑起来有问题,CAN分析仪抓包CAN的收发都异常(连CAN1都不对劲),跟我之前验证的不太一样。 最近抽空去帮他们测试分析了下,发现F103系列MCU跟F105/F107系列MCU的时钟资源有差异。
修改过程 1. 检查其软/硬件后汇总初步信息:
a. 外接16MHz HSE无源晶振
b. 原工程基于ST的Hal库做开发——确认在STM32F105平台上,各功能测试正常
c. 按照极海F103RC的双CAN要求修改后,按键等功能正常,唯独CAN1/2出问题
[size=12.0111pt]2. [size=10.5097pt]检查代码发现:
a. 系统主频确认——基于STM32F105生成的Hal库工程,期望让16M HSE经2分频,再进行PLL 9倍频
(16÷2*9=72MHz)
[size=14.0129px]
[size=12.0111pt] b. 关键来了——F103相较于F105,没有RCC_CFGR2寄存器!!但基于STM32F105自动生成的初始化代码,在配置主频时,使用了RCC_CFRG2寄存器做预分频计算!而APM32F103跟STM32F103的时钟资源是一致的。
i. 如下图STM32手册,(图2)左边是F103的时钟寄存器资源,右边是F105(严谨来说是Conectivity line devices,ST的互联型产品,即105/107这些额外支持CAN2、USB-Host、Ethernet的产品)
c. 如果要在F103上实现等效HSE预二分频,需要置位RCC->CFGR的bit17 PLLXTPRE位
[size=12.0111pt] i. 在如图所示的代码位置,插入代码 “RCC->CFGR |= 0x00020000;"
3. 修改之后,CAN1、CAN2的波特率正常、收发正常。但新问题来了——“串口通讯异常了?”
a. 对比过F103、105的系统架构,还有外设的时钟源,发现都一致——看来问题还是在软件工程上了,且推测跟上述的CFGR2差异有关联
i. 实测串口波特率有问题:软件用于计算串口波特率的SystemCoreClock全局变量有问题
1. 默认是16MHz,即系统配置的外部16MHz HSE晶振时间
2. 在运行完时钟初始化配置SystemClock_Config()后,变成了144MHz(刚好是期望72MHz MCU主频的2倍)——检查是在计算新一轮SystemCoreClock时,还是读取了"CFGR2"的对应地址数值作为计算参考。
ii. 解决方案
1. 在时钟初始化结束后,调用SystemCoreClockUpdate(),更新SystemCoreClock这个全局变量
2. SystemCoreClockUpdate()里的PLL时钟计算,有差别——需要把F105分支下涉及CFGR2的计算处理,全部屏蔽&替换成F103的系统时钟计算方式)
考虑实际生产情况
跟朋友沟通,让他们把STM32F105xC的宏,换成103的,也是一种方案——但可能不能兼容F105[size=12.0111pt]的时钟配置,即不能做到同个固件,在ST F105和APM32E103上都可以烧录生产的需求[size=12.0111pt] 解决方案——使用“JTAG_ID”的读出、校验方案(之前原厂介绍的,实测是能区分出是ST还是[size=12.0111pt]APM32)。[size=12.0111pt]读出如果是0x0477[size=12.0111pt](极海APM32的MCU读出来是这个值),才执行。
a. “RCC->CFGR |= 0x00020000;”
b. “SystemCoreClockUpdate()”
这2个操作↑
uint16_t Get_JTAG_ID(void)
{
if( *( uint8_t *)( 0xE00FFFE8 ) & 0x08 )
{
return (( *( uint8_t *)( 0xE00FFFD0 ) & 0x0F ) << 8 ) |
(( *( uint8_t *)( 0xE00FFFE4 ) & 0xFF ) >> 3 ) |
(( *( uint8_t *)( 0xE00FFFE8 ) & 0x07 ) << 5 ) + 1 ;
}
return 0;
}
|