Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CAN communication between LPC 2292 and LPC1758 boards "Start of Frame " error

I am trying to setup CAN communication between a couple of LPC device nodes. My setup includes a couple of CAN nodes writing on to the CAN bus. For example LPC 2292 CAN controller can write on to the CAN bus and the LPC1758 can receive the data. This works perfectly fine. Now LPC1758 has 2 CAN controllers and I have setup one for receiving data and the other for transmitting data on the bus as a response. I also setup interrupt handlers for LPC 1758 CAN 1 transmit & receive and CAN 2 transmit & receive. ( I dont have code for LPC 2292. its not under my control)

My problem is at the LPC1758 side. Here the CAN 1 receiver is able to get the data from the other CAN nodes as I can see the interrupt vector handler being called. The problem is when the the LPC 1758 CAN 2 tranmistter writes to the bus . It gets a bus error . More specificially "Start of Frame " error . ( I use a Ulink2 debugger). Now reading the CAN specs I know the start frame of the CAN message should start with a low ( dominant) bit CAN specs ; See page 3

How do I go about fixing this error ? Its not a configurable register that I can set the first bit to 0 or 1. I run the default LPC 1758 CAN code that comes with KEIL C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN I think the code is fine because when I run the code in simulation mode of KEIL I can see the CAN commnication work well.

Is this "Start of Frame" a by product of some other configurations that I am missing ?

Update Code : 

I run the default LPC 1758 CAN code that comes with KEIL C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN I think the code is fine because when I run the code in simulation mode of KEIL I can see the CAN communication work well. Also I did not make any changes to the code except the baudrate. CAN setup :

/*----------------------------------------------------------------------------
  setup CAN interface.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_setup (uint32_t ctrl)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;

  if (ctrl == 1) {
    LPC_SC->PCONP       |=  (1 << 13);           /* Enable power to CAN1 block */
    LPC_PINCON->PINSEL0 |=  (1 <<  0);           /* Pin P0.0 used as RD1 (CAN1) */
    LPC_PINCON->PINSEL0 |=  (1 <<  2);           /* Pin P0.1 used as TD1 (CAN1) */

    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  } else {
    LPC_SC->PCONP       |=  (1 << 14);           /* Enable power to CAN2 block */
    LPC_PINCON->PINSEL4 |=  (1 << 14);           /* Pin P2.7 used as RD2 (CAN2) */
    LPC_PINCON->PINSEL4 |=  (1 << 16);           /* Pin P2.8 used as TD2 (CAN2) */

    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  }

  LPC_CANAF->AFMR = 2;                           /* By default filter is not used */
  pCAN->MOD   = 1;                               /* Enter reset mode */
  pCAN->IER   = 0;                               /* Disable all interrupts */
  pCAN->GSR   = 0;                               /* Clear status register */
  CAN_cfgBaudrate(ctrl, /*250000*/ 100000);                 /* Set bit timing */
  pCAN->IER   = 0x0003;                          /* Enable Tx and Rx interrupt */
    //pCAN->IER   = 0x7FF;

}

Here is my code to transmit and receive:

/*----------------------------------------------------------------------------
  wite a message to CAN peripheral and transmit it.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_wrMsg (uint32_t ctrl, CAN_msg *msg)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t CANData;

  CANData = (((uint32_t) msg->len) << 16)     & 0x000F0000 | 
            (msg->format == EXTENDED_FORMAT ) * 0x80000000 |
            (msg->type   == REMOTE_FRAME)     * 0x40000000;

  if (pCAN->SR & (1<<2))  {                      /* Transmit buffer 1 free */
    pCAN->TFI1  = CANData;                       /* Write frame informations */
    pCAN->TID1 = msg->id;                        /* Write CAN message identifier */
    pCAN->TDA1 = *(uint32_t *) &msg->data[0];    /* Write first 4 data bytes */
    pCAN->TDB1 = *(uint32_t *) &msg->data[4];    /* Write second 4 data bytes */
    //pCAN->CMR  = 0x31;                           /* Select Tx1 for Self Tx/Rx */
    pCAN->CMR  = 0x21;                           /* Start transmission without loop-back */ -- Here is when "Start of Frame " error happens

  }
}

Receive code is fine but still posting

/*----------------------------------------------------------------------------
  read a message from CAN peripheral and release it.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_rdMsg (uint32_t ctrl, CAN_msg *msg)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t CANData;

                                                 /* Read frame informations */
  CANData = pCAN->RFS;
  msg->format   = (CANData & 0x80000000) == 0x80000000;
  msg->type     = (CANData & 0x40000000) == 0x40000000;
  msg->len      = ((uint8_t)(CANData >> 16)) & 0x0F;

  msg->id = pCAN->RID;                           /* Read CAN message identifier */

  if (msg->type == DATA_FRAME)  {                /* Read the data if received message was DATA FRAME  */ 
    *(uint32_t *) &msg->data[0] = pCAN->RDA;
    *(uint32_t *) &msg->data[4] = pCAN->RDB;
  }
}

Baudrate Calculation:

/*----------------------------------------------------------------------------
  configure the requested baudrate.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
static void CAN_cfgBaudrate (uint32_t ctrl, uint32_t baudrate)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t result = 0;
  uint32_t nominal_time;

  /* Determine which nominal time to use for PCLK */
  if (((PCLK / 1000000) % 6) == 0) {
    nominal_time = 12;                   /* PCLK based on  72MHz CCLK */
  } else {
    nominal_time = 10;                   /* PCLK based on 100MHz CCLK */
  }

  /* Prepare value appropriate for bit time register */
  result  = (PCLK / nominal_time) / baudrate - 1;
  result &= 0x000003FF;
  result |= CAN_BIT_TIME[nominal_time];

  pCAN->BTR  = result;                           /* Set bit timing */
}
like image 411
rockstar Avatar asked Jan 26 '16 03:01

rockstar


People also ask

What is error frame in CAN protocol?

The Error Frame. The error frame is a special message that violates the formatting rules of a CAN message. It is transmitted when a node detects an error in a message, and causes all other nodes in the network to send an error frame as well. The original transmitter then automatically retransmits the message.

CAN bus overload error?

If a CAN node receives messages faster than it can process them, an overload frame is used to inject an additional delay between data or remote frames. An Overload Frame has two fields, including an overload flag consisting of six dominant bits and an overload delimiter consisting of eight recessive bits.

What happens when CAN bus is overloaded?

The overload frame contains the two bit fields Overload Flag and Overload Delimiter. There are two kinds of overload conditions that can lead to the transmission of an overload flag: The internal conditions of a receiver, which requires a delay of the next data frame or remote frame.

CAN bus initialization?

Enable can initialization Control Register 0. wait until can bus is in initialization mode by checking control register 1 bit. Enables can bus by setting bit on CAN Control Register 1 again and set clock source - Ethier bus clock or eclock. set prescaler baudrate and Tq with Bus timing register.


1 Answers

I am finally able to get rid of the "Start of Frame " error that had being bogging me down. I had a discussion with some of our other CAN bus code authors and he suggested i use the same CAN controller for sending and receiving. In short this:

** Does not work** : 
LPC 2292 : CAN 1 Rx & CAN 2 Tx
LPC 1750 : CAN 1 Rx & CAN 2 TX 

** WORKS** :
LPC 2292 : CAN 1 Rx & CAN 1 Tx
LPC 1750 : CAN 1 Rx & CAN 1 TX 

Being a newbie i may have made this mistake. But the default code provided by KEIL shows using alternate CAN controllers for sending and transmitting. I hope this helps someone .

like image 166
rockstar Avatar answered Oct 01 '22 21:10

rockstar