PIC24 CAN, but won't

| No Comments | No TrackBacks

PIC24HJGP504 CAN Example Code (not working)

Trying to get basic CAN Transmission working on a PIC24HJ64GP504. There are a couple of app note examples, but all of them are complex and none seem to cover using CAN with PPS. I tried them anyway, and no success. In an attempt to make the simplest example possible I cut and pasted the code examples from the Family Guide into this application.

Speed is 500kbit with a 16mhz crystal and no PLL. I have a CANUSB adapter and an older 18F2580 based product on the bus. I can see frames from the 18F, but frames from the 24HJ just retransmit over and over until the EC reaches 128 and cause bus errors on the CANUSB. I don't have a bus analyzer, but on the scope the good frames look similar to the bad ones, so I think the timing is in the ballpark. Is there a way to tell which of the five CAN errors it is experiencing? Did I do my speed calculations correct?



#include <p24hxxxx.h>

_FBS( RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF );
_FSS( RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF );
_FGS( GSS_OFF & GCP_OFF & GWRP_OFF );
_FOSCSEL( FNOSC_PRI & IESO_OFF );
_FOSC( FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_HS );
_FWDT( FWDTEN_OFF );

unsigned int ecan1MsgBuf[32][8] __attribute__(( space(dma)) );

int main(void) {

  AD1PCFGL = 0xFFFF;
  __builtin_write_OSCCONL(OSCCON & 0xbf);
  _C1RXR = 9; // RX = RP9
  _RP22R = 0b10000; // TX = RP22
  __builtin_write_OSCCONL(OSCCON | 0x40);

  /* Assign 32x8word Message Buffers for ECAN1 in DMA RAM */
  DMA0STA = __builtin_dmaoffset(ecan1MsgBuf);
  /* Data Transfer Size: Word Transfer Mode */
  DMA0CONbits.SIZE = 0x0;
  /* Data Transfer Direction: DMA RAM to Peripheral */
  DMA0CONbits.DIR = 0x1;
  /* DMA Addressing Mode: Peripheral Indirect Addressing mode */
  DMA0CONbits.AMODE = 0x2;
  /* Operating Mode: Continuous, Ping-Pong modes disabled */
  DMA0CONbits.MODE = 0x0;
  /* Assign ECAN1 Transmit event for DMA Channel 0 */
  DMA0REQ = 70;
  /* Set Number of DMA Transfer per ECAN message to 8 words */
  DMA0CNT = 7;
  /* Peripheral Address: ECAN1dmaxcnt Transmit Register */
  DMA0PAD = (volatile unsigned int)&C1TXD;
  /* Start Address Offset for ECAN1 Message Buffer 0x0000 */
  DMA0STA = 0x0000;
  /* Channel Enable: Enable DMA Channel 0 */
  DMA0CONbits.CHEN = 0x1;
  /* Channel Interrupt Enable: Enable DMA Channel 0 Interrupt */
  IEC0bits.DMA0IE = 1;

  /* Set the ECAN module for Configuration Mode before writing into the Baud
    Rate Control Registers*/
  C1CTRL1bits.REQOP = 4;
  /* Wait for the ECAN module to enter into Configuration Mode */
  while(C1CTRL1bits.OPMODE != 4);
  /* Phase Segment 1 time is 8 TQ */
  C1CFG2bits.SEG1PH = 0x8; 
  /* Phase Segment 2 time is set to be programmable */
  C1CFG2bits.SEG2PHTS = 0x1;
  /* Phase Segment 2 time is 6 TQ */
  C1CFG2bits.SEG2PH = 0x6; 
  /* Propagation Segment time is 1 TQ */
  C1CFG2bits.PRSEG = 1; 
  /* Bus line is sampled three times at the sample point */
  C1CFG2bits.SAM = 0x1;
  /* Synchronization Jump Width set to 1 TQ */
  C1CFG1bits.SJW = 1; 
  /* Baud Rate Prescaler bits set to 1:1 */
  C1CFG1bits.BRP = 0x0 ;
  /* Put the ECAN Module into Normal Mode Operating Mode*/
  C1CTRL1bits.REQOP = 0;
  /* Wait for the ECAN module to enter into Normal Operating Mode */
  while(C1CTRL1bits.OPMODE != 0);
  /* Configure Message Buffer 0 for Transmission and assign priority*/
  C1TR01CONbits.TXEN0 = 0x1;
  C1TR01CONbits.TX0PRI = 0x3;
  /* WRITE TO MESSAGE BUFFER 0 */
  /* CiTRBnSID = 0bxxx1 0010 0011 1100
  	IDE = 0b0
  	SRR = 0b0
  	SID<10:0>= 0b100 1000 1111 */
  ecan1MsgBuf[0][0] = 0x123C;
  /* CiTRBnEID = 0bxxxx 0000 0000 0000
    EID<17:6> = 0b0000 0000 0000 */
  ecan1MsgBuf[0][1] = 0x0000;
  /* CiTRBnDLC = 0b0000 0000 xxx0 1111
    EID<17:6> = 0b000000
    RTR = 0b0
    RB1 = 0b0
    RB0 = 0b0
    DLC = 0b1000 */
  ecan1MsgBuf[0][2] = 0x8;
  /* WRITE MESSAGE DATA BYTES */
  ecan1MsgBuf[0][3] = 0xabcd;
  ecan1MsgBuf[0][4] = 0xabcd;
  ecan1MsgBuf[0][5] = 0xabcd;
  ecan1MsgBuf[0][6] = 0xabcd;
  /* REQUEST MESSAGE BUFFER 0 TRANSMISSION */
  C1TR01CONbits.TXREQ0 = 0x1;
  while (C1TR01CONbits.TXREQ0);
  while(1);
  return 0;
}

void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
{
   IFS0bits.DMA0IF = 0;          // Clear the DMA0 Interrupt Flag;
}

No TrackBacks

TrackBack URL: http://mindbent.org/cgi-bin/mt/mt-tb.cgi/23

Leave a comment

About this Entry

This page contains a single entry by Mark Farver published on March 8, 2010 3:49 AM.

Secret SQuirreL was the previous entry in this blog.

Bigger Pipes for a Better Austin is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by Movable Type 4.24-en