单片机学习小组
直播中

张静

7年用户 1434经验值
私信 关注

用CAN总线分析仪接收调试板发出的数据时接收不到怎么解决?

用CAN总线分析仪接收调试板发出的数据时接收不到怎么解决?

回帖(1)

刘文明

2022-2-7 11:38:44
在调试中遇到了这样的问题:在用CAN总线分析仪接收调试板发出的数据时,接收不到数据。但是程序拿到另外一块类似板中一切正常。
原因分析

在程序没问题的基础上,想到是硬件的问题,如是开始了以下问题检查



  • 威廉希尔官方网站 板线路是否接错,尤其是RX与TX是否接反、CANH与CANL是否接反,是否短接
  • 收发器供电是否正常

经检查后均不是上述问题,于是用示波器对总线电平进行测量





  • 发现有电平跳变说明不是硬件威廉希尔官方网站 的问题。我的波特率位125Kbps,所以位时间是8微秒,所以上面的报文结构位7个显性位,11个隐性位,应该为错误帧;但是过一段时间波形变换为如下所示:




报文变为一位显性,25位隐性电平,这个电平形式我始终不知道是什么。


软件问题
既然硬件没有问题那就从软件着手。


/*************************************************************/
/*                       CAN发送                            */
/*************************************************************/
Bool MSCANSendMsg(struct can_msg msg)
{
  unsigned char send_buf, sp;
    unsigned char num;   
   if(msg.len > 8)     // 检查数据长度
    return(FALSE);      //返回true和false所以要用bool型,在以后 if(fucn(x,y))//可以用来作if语句的判断,while(fucn(x,y))//也可以做循环条件的判断
  // 检查总线时钟是否同步
  if(CANCTL0_SYNCH==0)
    return(FALSE);
send_buf = 0;
  do
  {
    CANTBSEL=CANTFLG;      // 寻找空闲的缓冲器
    send_buf=CANTBSEL;//等待该寄存器有值,即等待相关报文缓冲器为空
    num++;
    if(num>10)
    break;
  }
  while(!send_buf);
  // 写入标识符
  CANTIDR0 = (unsigned char)(msg.id>>3);//id为8位
  CANTIDR1 = (unsigned char)(msg.id<<5);
  
   if(msg.RTR)                 //Remote Transmission Request 远程传输请求
    // RTR = 阴性
    CANTIDR1 |= 0x10;
   
  // 写入数据
  for(sp = 0; sp < msg.len; sp++)
    *((&CANTDSR0)+sp) = msg.data[sp];//数据段寄存器,包含将要发送的数据


  // 写入数据长度
  CANTDLR = msg.len;
  
  // 写入优先级
  CANTTBPR = msg.prty;         //ransmit Buffer Priority Register (TBPR)
  
  // 清 TXx 标志 (缓冲器准备发送)
  CANTFLG = send_buf;
  
  return(TRUE);
  
}


在调试时程序总是进到寻找空闲的缓冲器这个do while循环里,跳不出来,所以定义了个num变量让它自加到10跳出循环;但是还是不通,于是想从 CAN初始化程序 入手:


/*************************************************************/
/*                        初始化CAN                         */
/*************************************************************/


void INIT_CAN(void) //按照dz60寄存器改编的程序
{
  if(CANCTL0_INITRQ==0)      // 查询是否进入初始化状态   
    CANCTL0_INITRQ =1;        // 进入初始化状态


  while (CANCTL1_INITAK==0);  //等待进入初始化状态,初始化模式确认


  CANBTR0_SJW = 3;            //设置同步跳转宽度,总线计时寄存器,现在设为4
  CANBTR0_BRP = 3  ;            //设置波特率预分频器-prescaler value ,
  CANBTR1_TSEG_10 = 6;
  CANBTR1_TSEG_20 = 7;
        //设置时段1-7个和时段2-8个的Tq个数 ,总线频率为125kb/s,1/125K=bit time=(prescaler value)*(1+tseg1+tseg2)/Fcanclk=4*(7+8+1)/8M


// 关闭滤波器                                 
  CANIDMR0 = 0xFF;//不比较
  CANIDMR1 = 0xFF;
  CANIDMR2 = 0xFF;
  CANIDMR3 = 0xFF;
  CANIDMR4 = 0xFF;
  CANIDMR5 = 0xFF;
  CANIDMR6 = 0xFF;
  CANIDMR7 = 0xFF;


  CANCTL1 = CANCTL1_CLKSRC_MASK | CANCTL1_CANE_MASK;             //使能MSCAN模块,设置为一般运行模式、使用总线时钟源 环回自测禁止
  


  CANCTL0 = 0x00;             //返回一般模式运行


  while(CANCTL1_INITAK);      //等待回到一般运行模式


  while(!CANCTL0_SYNCH);    //等待总线时钟同步


  CANRIER_RXFIE = 0;          //禁止接收中断
}


改了两个位置


第一个位置改了同步跳转宽度
CANBTR0_SJW = 3;            //设置同步跳转宽度,总线计时寄存器,现在设为4


同步跳转宽度是CAN总线机制中为了寻找同步而在缓冲段增加或减少时间的上限值。总线中能通信的基础是各个节点的波特率一致,然而各个节点的波特率又不能达到百分百相同,所以CAN总线允许各节点波特率有微小偏差,而对位时间的微调就能微调波特率,使该节点与总线波特率一致,所以同步跳转宽度越大,波特率的波动范围就越大,容错率提高,也就是说这个值越大,对总线中个节点的波特率的要求就越松。


第二个位置改变了缓冲段一与缓冲段二的时长
  CANBTR1_TSEG_10 = 6;
  CANBTR1_TSEG_20 = 7;


将缓冲段一设置为7个Tq时长,将缓冲段二设置为8个Tq时长,这样采样点就在该位的中间位置,利于采样


再进行调试时能够很好地接收到数据:






  • 总结

要有一定的判断力,我在调试时已经测出总线上有电平跳变时,依然怀疑是硬件的问题而在威廉希尔官方网站 板上浪费了大量时间,没有想到要改程序。要试着从不同方向入手,不要用同样的方法去得到同样的错误结论。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分