单片机 > 单片机程序设计 > 详情

STM32系统时钟 CAN UART

发布时间:2024-07-26 发布时间:
|

在调试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 */





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STC89C52RC单片机的NRF24L01无线通信程序.收发一体