CAN bus send or receive failure problem

CAN bus send or receive failure problem

Encountered such a problem in debugging: when using the CAN bus analyzer to receive the data sent by the debugging board, the data cannot be received. But the program got another similar board and everything was normal.

Cause Analysis

On the basis that the program is no problem, I thought it was a hardware problem, so the following problem check was started

  • Whether the circuit board circuit is connected wrongly, especially whether RX and TX are connected reversely, whether CANH and CANL are connected reversely, and whether they are short-circuited
  • Is the power supply of the transceiver normal?

After inspection, none of the above problems are found, so use an oscilloscope to measure the bus level

Insert picture description here
Insert picture description here

  • It is found that there is a level jump indicating that it is not a problem with the hardware circuit. My baud rate is 125Kbps, so the bit time is 8 microseconds, so the message structure above has 7 dominant bits and 11 recessive bits, which should be an error frame; but after a while, the waveform changes as shown below :

Insert picture description here
Insert picture description here
The message becomes a dominant and 25 recessive level. I still don't know what this level format is.

Software problem

Since there is no problem with the hardware, start with the software.

/*************************************************************/
/*                       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);
  
}

When debugging, the program always enters into the do while loop of looking for free buffers and cannot jump out, so a num variable is defined to make it increase to 10 and jump out of the loop; but it still doesn't work , so I want to start with the CAN initialization program :

/*************************************************************/
/*                        初始化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;          //禁止接收中断
}

Changed two positions

  • Changed the sync jump width in the first position
 CANBTR0_SJW = 3;            //设置同步跳转宽度,总线计时寄存器,现在设为4

The synchronization jump width is the upper limit of the increase or decrease of time in the buffer segment in order to find synchronization in the CAN bus mechanism. The basis for communication in the bus is that the baud rate of each node is the same, but the baud rate of each node cannot be 100% the same, so the CAN bus allows a slight deviation of the baud rate of each node, and the fine-tuning of the bit time The baud rate can be fine-tuned to make the node consistent with the bus baud rate. Therefore, the larger the synchronization jump width, the greater the fluctuation range of the baud rate and the higher the fault tolerance rate. The baud rate requirement of the node is looser.

  • The second position changes the duration of buffer segment one and buffer segment two
  CANBTR1_TSEG_10 = 6;
  CANBTR1_TSEG_20 = 7;

Set buffer segment 1 to 7 Tq duration, and buffer segment 2 to 8 Tq duration, so that the sampling point is in the middle of the bit, which is good for sampling

  • The data can be received well when debugging again:

Insert picture description here

  • Summary :

I must have a certain degree of judgment. When I have detected a level transition on the bus during debugging, I still suspected that it was a hardware problem and wasted a lot of time on the circuit board. I did not expect to change the program. Try to start from different directions, don't use the same method to get the same wrong conclusion.

Guess you like

Origin blog.csdn.net/xiaobaoAlex/article/details/103675003