打印
[APM32F1]

Sxx32F105移植到APM32F103后CAN失效

[复制链接]
697|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
CCCfe|  楼主 | 2022-6-24 16:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#申请原创#
问题背景
  以前用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寄存器做预分频计算!APM32F103STM32F103的时钟资源是一致的。
       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;
}







使用特权

评论回复
沙发
Fanexs168| | 2022-6-24 16:34 | 只看该作者
顶一下

使用特权

评论回复
板凳
cooldog123pp| | 2022-6-25 16:58 | 只看该作者
感谢楼主把自己填坑的经历分享给大家,给大家做国产替代的时候又避免了一个莫名其妙的bug。

使用特权

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

本版积分规则

3

主题

3

帖子

0

粉丝