Christopher Sagedy

Trouble Configuring MSCAN on MCF51JM128

Discussion created by Christopher Sagedy on Mar 3, 2009
Latest reply on Sep 29, 2013 by TomE
Hello everyone,

I'm attempting to set up CAN to pass data between two DEMOJM boards, and suffice to say, it's not working. I have CAN configured in loopback mode, and it appears that my messages are being transmitted, but I never seem to receive them. The receive ISR is never called. Can someone spot what I'm doing wrong?

Thanks in advance!

Chris


/* This function initializes the CAN module. */
void can_init()
{
  // Ask CAN to enter initialization mode.
  CANCTL0_INITRQ = 1;

  // Wait until CAN has entered initialization  mode.
  while(CANCTL1_INITAK == 0)
    __RESET_WATCHDOG();

  // Enable MSCAN by asserting CANE.
  CANCTL1_CANE = 1;

  // Use the oscillator clock instead of the bus clock. The bus
  // clock is generated by a PLL, which may create too much
  // jitter to fall within the CAN requirements.
  CANCTL1_CLKsrc=0;

  // Set the synchronization jump width to 2 Tq clock cycles.
  CANBTR0_SJW = 0b01;

  // Sample each bit one time.
  CANBTR1_SAMP = 0;

  // Set time segment 2 to 2 Tq clock cycles.
  CANBTR1_TSEG_20 = 0b001;

  // Set time segment 1 to 4 Tq clock cycles.
  CANBTR1_TSEG_10 = 0b0011;
 
  // Enable loopback self test mode.
  CANCTL1_LOOPB = 1;

  // Select eight 8-bit acceptance filters.                
  CANIDAC_IDAM = 0b10;

  // Accept all messages by programming the mask
  // registers to be all ones.
  CANIDMR0 = 0xff;
  CANIDMR1 = 0xff;
  CANIDMR2 = 0xff;
  CANIDMR3 = 0xff;
  CANIDMR4 = 0xff;
  CANIDMR5 = 0xff;
  CANIDMR6 = 0xff;
  CANIDMR7 = 0xff;
 
  // Clear INITRQ to leave initialization mode and
  // enter normal mode.
  CANCTL0_INITRQ = 0;

  // Wait until CAN is in normal mode.
  while(CANCTL1_INITAK == 1)
    __RESET_WATCHDOG();

  // Enable the receiver full/message received interrupt.
  CANRIER_RXFIE = 1;

  LED = 0;
}

/* This is the ISR for the CAN receiver full interrupt. */
__interrupt VectorNumber_Vcanrx void canrx_isr()
{
  unsigned int identifier;
  unsigned char data_length;
  unsigned char data_buffer[8];

  LED ^= 1;

  // Read the received message from RxFG.
  identifier = (CANRIDR0  3) | (CANRIDR1 & 0xe0);

  data_length = (CANRDLR & 0x0f);

  data_buffer[0] = CANRDSR0;
  data_buffer[1] = CANRDSR1;
  data_buffer[2] = CANRDSR2;
  data_buffer[3] = CANRDSR3;
  data_buffer[4] = CANRDSR4;
  data_buffer[5] = CANRDSR5;
  data_buffer[6] = CANRDSR6;
  data_buffer[7] = CANRDSR7;

  // Clear the RXF flag to acknowledge the interrupt and to release
  // the foreground buffer.
  CANRFLG_RXF = 1;
}

/* This function sends a message over CAN. */
int can_send(unsigned int identifier, byte data[8], byte length, byte priority)
{
  // To get the next available transmit buffer, we must
  // read the CANTFLG register and write this value back
  // to the CANTBSEL register.
  CANTBSEL = CANTFLG;

  // If there is not an available transmit buffer, it is
  // not possible to proceed.
  if(CANTBSEL == 0x00)
    return -1;

  // Write the identifier into the IDR registers.
  CANTIDR0    = (identifier >> 3) & 0xff;
  CANTIDR1_ID = identifier & 0b111;

  // Write the data into the data segment registers.
  CANTDSR0 = data[0];
  CANTDSR1 = data[1];
  CANTDSR2 = data[2];
  CANTDSR3 = data[3];
  CANTDSR4 = data[4];
  CANTDSR5 = data[5];
  CANTDSR6 = data[6];
  CANTDSR7 = data[7];

  // Write the length into the data length register.
  CANTDLR_DLC = length;

  // Set the priority for this data.
  CANTTBPR = priority;

  // Clear the transmit buffer empty flag to indicate that the
  // message is ready to be sent. (Write of 1 clears the flag.)
  CANTFLG = CANTBSEL;

  return 0;
}


/* Main entry point of the program. */
void main(void) {

  char data[8];
  int i;

  EnableInterrupts;

  // MCU/Board Specific configuration
  SOPT1 = 0;             
                              
  //Multi-purpose Clock Generator config register2
  //set HGO (high gain operation),EREFS (oscillator),
  //ERCLKEN (ext clk reference enable)      
  MCGC2 |= 0x26;
  
  //wait for oscillator to initialize
  while(!MCGSC_OSCINIT);
  
  //Multi-purpose Clock Generator config register1
  MCGC1 = 0x00;
  
  //wait until output of PLL is selected as clock mode
  if(MCGSC & 0x0C)
  {
    for(;;)
      ;
  }

  // Make the LED an output, initially off.
  PTEDD_PTEDD2 = 1;
  LED = 1;

  // Make push button 0 an input.
  PTGDD_PTGDD0 = 0;
  PTGPE_PTGPE0 = 1;

  // Initialize the CAN module.
  can_init(); 

  // Clear out the data buffer.
  for(i = 0; i  8; i++)
  {
    data[i] = 0x00;
  }

  for(;;) {

    // Wait for a button press and debounce.
    while(BUTTON == 1) 
      __RESET_WATCHDOG();

    while(BUTTON == 0)
      __RESET_WATCHDOG();
  
    // Toggle the data.
    data[0] ^= 0x01;
   
    // Send the data.
    can_send(0x12, data, 8, 0);

  }
}

Outcomes