STM32系统时钟 CAN UART

来源:互联网 发布:mac 复制文件到硬盘 编辑:程序博客网 时间:2024/05/21 09:32

在调试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设定了一个时间单位的长度12CAN_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 */