STM32F407与STM32F105 CAN通讯失败的定位解决

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/hwytree/article/details/102647112

问题的发现

在STM32 CAN总线的应用过程,遇到STM32F407与STM32F105的CAN通讯失败问题,经过一系列的测试分析,发现并解决问题,实现正常的CAN通讯。

问题的现象

  1. STM32F407 板上安装25MHz晶体,作为HSE时钟,内部配置到168MHz,配置CAN速率为250Kbps,实现CAN LOOP测试正常,两块同样的STM32F407板子,实现CAN NORMAL通信测试正常;
  2. STM32F105板上安装8MHz晶体,作为HSE时钟,内部配置到72MHz,配置CAN速率为250Kbps,实现CAN LOOP测试正常,两块同样的STM32F105板子,实现CAN NORMAL通信测试正常;
  3. STM32F407板子向STM32F105板子CAN发送,无法接收成功;
  4. STM32F105向STM32F407板子CAN发送, 无法接收成功;
  5. 将一块STM32F105板子重焊为25MHz晶体,调整系统时钟配置后,CAN部分配置不变,与8MHz晶体的STM32F105板子CAN通讯失败;
  6. 将一块STM32F407板子重焊为8MHz晶体,调整系统时钟配置后,CAN部分配置不变,与25MHz晶体的STM32F407板子CAN通讯失败;
  7. STM32F407和STM32F105 CAN部分的SJW, BS1和BS2相同;
  8. 最终体现为采用8MHz晶体的STM32与采用25MHz晶体的STM32 CAN通讯不成功;
  9. 串口配置为115200bps和PC通讯正常。

测试过程

硬件调整测试

  1. 用万用表检查测试过程中的连接,无问题;
  2. 通过示波器简单查看CAN发送信号波特率,似乎也很接近250Kbps;

软件调整测试

  1. 波特率调整测试,重新配置CAN的波特率为更高500Kbps,更低50Kbps,25M晶体的板子和8M晶体的板子,双板CAN测试依旧不通;
  2. CAN的速率配置需要较严格的一致,因为采用不同晶体的板子,CAN配置部分相同,继续上升到系统时钟SYSCLK和CAN时钟PCLK1层面进行调查。
  3. 在8MHz晶体的STM32F105板子的主文件main()函数里增加时钟频率测试部分代码:

RCC_ClocksTypeDef get_rcc_clock;
RCC_GetClocksFreq(&get_rcc_clock);

此方式为STM32库函数支持, RCC_ClocksTypeDef的定义如下:
typedef struct
{
uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz /
uint32_t HCLK_Frequency; /
!< returns HCLK clock frequency expressed in Hz /
uint32_t PCLK1_Frequency; /
!< returns PCLK1 clock frequency expressed in Hz /
uint32_t PCLK2_Frequency; /
!< returns PCLK2 clock frequency expressed in Hz /
uint32_t ADCCLK_Frequency; /
!< returns ADCCLK clock frequency expressed in Hz */
}RCC_ClocksTypeDef;

下载程序后,通过调试看get_rcc_clock结构体变量内的SYSCLK_Frequency(72MHz)和PCLK1_Frequency(36MHz)频率情况。或者通过串口将频率数据输出进行查看。

发现时钟异常,SYSCLK不是72000000Hz,而是82285713Hz,而PCK1不是36000000Hz,而是41142785Hz,所以可能是时钟部分锁相配置异常所致,此时对应的系统时钟配置部分是:

/* PLL2 configuration: PLL2CLK = (HSE / 1) * 8 = 64 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 8 = 8 MHz */
    
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                          RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV1 | RCC_CFGR2_PLL2MUL8 |
                         RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV8);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                        RCC_CFGR_PLLMULL9); 
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;    

貌似时钟分频倍频配置计算没有问题。仍然进行调整,将原有的配置的分频和倍频部分进行调整,如下:

/* PLL2 configuration: PLL2CLK = (HSE / 2) * 10 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
    
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                          RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV2 | RCC_CFGR2_PLL2MUL10 |
                         RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);  
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                        RCC_CFGR_PLLMULL9); 
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;        

测试后发现,8MHz晶体的STM32板子和25MHz晶体的STM32板子CAN通讯正常,问题解决。

结论

基本结论

STM32系统时钟配置部分的锁相环分频和倍频,并非所有计算正确的配置都是运行正确,具有一定的有效选择性,所以对锁相环部分做了配置或更新后,需要用 RCC_ClocksTypeDef结构体实现验证时钟配置有效性。

结论扩展验证

采用STM32CUBE工具,也能更直观的看到ST对时钟配置有效性的提醒:

  1. STM32F105的时钟配置,针对本问题对应的时钟配置,ST在软件工具里,显示出了异常;

STM32F105系统时钟配置(异常)

  1. STM32F105的时钟配置,针对本问题对应的时钟配置,做了修改调整后,ST在软件工具里,未显示出异常。

STM32F105系统时钟配置(正常)

–End–

猜你喜欢

转载自blog.csdn.net/hwytree/article/details/102647112