之前在实际项目使用 MM32 MCU CAN 外设过程中会遇到一些问题,本文主要描述和记录调试过程时候的相关问题以及对应的处理意见。
1.直接使用灵动微官网例程调试(附,灵动微MM32 MCU 资料下载链接: http://www.mindmotion.com.cn/download1.aspx),can 盒子与设备不能正常通讯,且一次都不行。


  • 需要根据 DS手册中引脚功能定义确定一下实际硬件使用到的 CAN_TX / CAN_RX 脚与程序中默认配置是否一致,且 CAN_H/CAN_L 接线上没有接反 ;
  • 需要确定 mcu 与can收发器芯片的电源电压是否匹配,考虑到实际需要抗干扰性更强 ,建议统一使用 5v 供电较好 ;
  • 需要确定 mcu 的时钟源是否存在异常,这里强烈建议系统时钟使用 外部晶振,由于 can  通讯本身对于位时间的偏差容忍度极低,不像 uart 能到 3%-6% 还可以通讯上 ;
  • 需要确定 can 盒子上位机的配置中波特率选项是否与程序中配置匹配得上,或者用自动波特率识别。

以上几点检查完毕用再使用官网例程基本就可以正常通讯了。
2.在总线上的设备中,会有不固定的某几个设备出现 发送数据丢帧率较大,偶尔还会一直发送不出去必须通过复位方可恢复,但接收正常的情况。


  • 引发的原因可能是 can 总线上存在较大竞争关系,比如使用了 同一个 ID 号去发送数据,或者循环发送时间间隔太短,导致数据没有正常发出 ;
  • 可以尝试在发送前去判断一下所有与发送相关的 can 状态位 , 直到判断为没有发送任务占用总线时再去发送 ;
  • 可以尝试在发送前延时几个 ms ,增加错开数据帧碰撞的几率  ;
  • 可以在 Send_CANFrame 发送函数里面调用 CAN_Peli_TransmitRepeat 而不用 CAN_Peli_Transmit ,这样相当于增加了硬件重发机制 ,且 CAN_Peli_TransmitRepeat 的定义需要改写为如下:
  • void CAN_Peli_TransmitRepeat(CanPeliTxMsg* PeliTxMessage)
  • {
  • CAN1_PELI->FF = (PeliTxMessage->FF << 7) | (PeliTxMessage->RTR << 6) | (PeliTxMessage->DLC);
  • if (((FunctionalState)PeliTxMessage->FF) != ENABLE) {
  • CAN1_PELI->ID0 = (PeliTxMessage->IDHH);
  • CAN1_PELI->ID1 = (PeliTxMessage->IDHL & 0xE0);
  • if ((FunctionalState)(PeliTxMessage->RTR) != ENABLE) {
  • CAN1_PELI->DATA0 = PeliTxMessage->Data[0];
  • CAN1_PELI->DATA1 = PeliTxMessage->Data[1];
  • CAN1_PELI->DATA2 = PeliTxMessage->Data[2];
  • CAN1_PELI->DATA3 = PeliTxMessage->Data[3];
  • CAN1_PELI->DATA4 = PeliTxMessage->Data[4];
  • CAN1_PELI->DATA5 = PeliTxMessage->Data[5];
  • CAN1_PELI->DATA6 = PeliTxMessage->Data[6];
  • CAN1_PELI->DATA7 = PeliTxMessage->Data[7];
  • }
  • }
  • else {
  • CAN1_PELI->ID0 = PeliTxMessage->IDHH;
  • CAN1_PELI->ID1 = PeliTxMessage->IDHL;
  • CAN1_PELI->DATA0 = PeliTxMessage->IDLH;
  • CAN1_PELI->DATA1 = PeliTxMessage->IDLL;
  • if ((FunctionalState)(PeliTxMessage->RTR) != ENABLE) {
  • CAN1_PELI->DATA2 = PeliTxMessage->Data[0];
  • CAN1_PELI->DATA3 = PeliTxMessage->Data[1];
  • CAN1_PELI->DATA4 = PeliTxMessage->Data[2];
  • CAN1_PELI->DATA5 = PeliTxMessage->Data[3];
  • CAN1_PELI->DATA6 = PeliTxMessage->Data[4];
  • CAN1_PELI->DATA7 = PeliTxMessage->Data[5];
  • CAN1_PELI->DATA8 = PeliTxMessage->Data[6];
  • CAN1_PELI->DATA9 = PeliTxMessage->Data[7];
  • }
  • }
  • (CAN1_PELI->MOD & CAN_MOD_STM) ? (CAN1->CMR = CAN_CMR_GTS | CAN_CMR_AT) : (CAN1->CMR = CAN_CMR_TR);
  • }