在调试USB-CAN的适配器的过程中,采用库函数开发,在调试串口的过程中串口数据始终乱码。
思考一番,发现由于外部晶振的原因,在 Keil 中Ctrl + Shift + F 查找 HSE_VALUE:
#if !defined HSE_VALUE
#ifdef STM32F10X_CL
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#else
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* STM32F10X_CL */
#endif /* HSE_VALUE */
由于我采用的是12M的晶振,所以将 8000000 改为 12000000,程序测试通过;
接下来调试CAN总线,程序在自己做的 两个 USB-CAN适配器间 CAN通信测试通过,
但是接上公司买来的 USB-CAN适配器 ,数据始终不成功,双方收发一点反应都没有。
这是为什么,买来的 USB-CAN适配器 是没问题的,我自己做的 USB-CAN适配器 在两个CAN网络间也可以通信,
说明我的 USB-CAN适配器 大体是没什么问题的,由于初次调试 CAN 总线,问题出在哪里, 也没什么思路。
最后把情况反馈给 公司所买 USB-CAN适配器 的卖家,卖家人很好,他推测是CAN总线间波特率的问题。
是这个原因吗? STM32的CAN时钟。在SystemInit()函数中的SetSysClock()
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
SetSysClockTo72() 将系统倍频到 72M ,
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK / 2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
CAN时钟选采用的是PCLK1时钟,为SYSCLK的一半,即是36M,
但是CAN波特率配置是按照 36M的时钟来配置的,为什么还会不成功呢。
void CAN_StructInit_Init(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE;//DISABLE;//软件对CAN_MCR寄存器的INRQ位进行置1随后清0后,一旦硬件检测到128次11 位连续的隐性位,就退出离线状态。
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过清除CAN_MCR寄存器的SLEEP位,由软件唤醒
CAN_InitStructure.CAN_NART=ENABLE;//////DISABLE;CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)
CAN_InitStructure.CAN_RFLM=DISABLE;//在接收溢出时FIFO未被锁定,当接收FIFO的报文未被读出,下一个收到的报文会 覆盖原有的报文
CAN_InitStructure.CAN_TXFP=DISABLE;//发送FIFO优先级由报文的标识符来决定
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN硬件工作在正常模式
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳跃宽度1个时间单位
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;//时间段1为8个时间单位
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//时间段2为3个时间单位
CAN_InitStructure.CAN_Prescaler=12;//(pclk1/((1+3+2)*12)) = 36Mhz/6/12 = 0.5Mbits设定了一个时间单位的长度12
CAN_Init(CAN1, &CAN_InitStructure);
}
反复思考,各种怀疑,最后发现是系统倍频至 72M的时候出了问题,
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); ////////////////////////////////
#endif /* STM32F10X_CL */
SetSysClockTo72() 里面的赫然是RCC_CFGR_PLLMULL9,我晕。
果断改为RCC_CFGR_PLLMULL6。
为什么库函数 SetSysClockTo72() 这么不不完善,就不能根据外部晶振参数 HSE_VALUE 来倍频吗?
这样局限只能是8M的晶振,在采用8M以外的晶振的时候,一定要注意这个问题。
也怪自己太过于相信库函数了。
一直没怀疑系统倍频 72M的原因也是因为我的串口采用的STM32的串口2,
为什么同是APB1时钟PCLK1,串口能正常工作,而CAN不可以呢...
(PCLK1用于串口2,3,4,5;PCLK2用于串口1)
uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate.
The baud rate is computed using the following formula:
- IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』