# How do I set up both CAN modules on the PIC DSPIC33EP128GM604?

So I am in the midst of my first proper PIC project, and it has been interesting to say the least. The problem I'm having is setting up the CAN modules. The PIC I'm using has two ECAN modules. Using the code examples provided, I set up CAN1 (module 1) to transmit a message, and it works absolutely fine. I can see the signal on the designated I/O pin.

The problem is when I try to use the same code with CAN2 (the second module on the PIC). It transmits some data, but not the one I set up in the buffer; all I see is 0x0000 throughout the package.

My code is mostly from the the ECAN application notes, with my few configuration tweeks. CAN1 works just fine, but CAN2 does not. When I ask both modules to transmit (CAN1 first then CAN2), only CAN1 works, but CAN2 doesn't budge at all (I have no idea why). When I turn off CAN1 and only ask CAN2 to transmit, as mentioned above, it works, but only transmits 0's (it seems like it's not talking to the DMA properly, even though I'm using the same tried-and-tested code that I used for CAN1).

Set up DMA1 for CAN transmit:

DMA1CONbits.SIZE = 0x0;
DMA1CONbits.DIR = 0x1; //From peripheral to DMA
DMA1CONbits.AMODE = 0x2;
DMA1CONbits.MODE = 0x0;
DMA1REQ = 70;
DMA1CNT = 7; //Data length
DMA1PAD = (volatile unsigned int) &C1TXD; //Point to peripheral register
DMA1STAL = (unsigned int) &CAN1MsgBuf; //Point to buffer
DMA1STAH = (unsigned int) &CAN1MsgBuf; //Point to buffer
DMA1CONbits.CHEN = 0x1; //Enable


Set CAN bus speed (This is a peripheral Library function):

CAN1Initialize(CAN_SYNC_JUMP_WIDTH2 &
CAN_BAUD_PRE_SCALE(4),
CAN_WAKEUP_BY_FILTER_DIS &
CAN_PHASE_SEG2_TQ(3) &
CAN_PHASE_SEG1_TQ(3) &
CAN_PROPAGATIONTIME_SEG_TQ(3) &
CAN_SEG2_FREE_PROG &
CAN_SAMPLE1TIME); //CAN-IN


Send the Data:

    C1TR01CONbits.TXEN0 = 0x1;
C1TR01CONbits.TX0PRI = 0x3;

/* At this point the ECAN1 module is ready to transmit a message. Place the ECAN module in
Normal mode. */
C1CTRL1bits.REQOP = 0;
while (C1CTRL1bits.OPMODE != 0)
;

/* Write to message buffer 0. */
/* CiTRBnSID = 0bxxx1 0010 0011 1100
IDE = 0b0
SRR = 0b0
SID<10:0>= 0b100 1000 1111 */

unsigned int ID = 0xB1;
CAN1MsgBuf[0][0] = ID<<2;
/* CiTRBnEID = 0bxxxx 0000 0000 0000
EID<17:6> = 0b0000 0000 0000 */

CAN1MsgBuf[0][1] = 0x0000;
/* CiTRBnDLC = 0b0000 0000 xxx0 1111
EID<17:6> = 0b000000
RTR = 0b0
RB1 = 0b0
RB0 = 0b0
DLC = 0b1111 */
CAN1MsgBuf[0][2] = 0x0008;

/* Write message data bytes */
CAN1MsgBuf[0][3] = 0xabcd;
CAN1MsgBuf[0][4] = 0xabcd;
CAN1MsgBuf[0][5] = 0xabcd;
CAN1MsgBuf[0][6] = 0xabcd;

/* Request message buffer 0 transmission */
C1TR01CONbits.TXREQ0 = 0x1;

/* The following shows an example of how the TXREQ bit
can be polled to check if transmission is complete. */
while (C1TR01CONbits.TXREQ0 == 1)
;

/* Message was placed successfully on the bus. */


I am using the same code for both modules. I only switch the 1's to the 2's for the address names. For example, C1TR01CON for CAN1 becomes C2TR01CON for CAN2, etc.

• You are using two separate DMA engines for the two CAN modules, right? Jan 7, 2016 at 12:31
• Yup, a different DMA for each module.
– MAM
Jan 7, 2016 at 12:34
• After hours and hours of trial and error i seemed to have narrowed it down to a DMA address glitch (?). Any DMA,when configured for CAN2 seems to generate a lot of garbage by reading off the specified buffer from a weird offseted location. I have no idea what is going on: For example if i change the bytes in the buffer related to the data packets, instead the CAN ID part of the message is effected. Completely lost.
– MAM
Jan 7, 2016 at 16:44
• Make sure that the buffers are in DMA memory. On some parts, the DMA engine can only access a limited part of RAM. Jan 7, 2016 at 18:07
• How do i ensure that? Well i have religiously followed the datasheet and im going insane. CAN2 is behaving so oddly, im completely lost.
– MAM
Jan 7, 2016 at 18:09

3. Selecting the required peripheral as the interrupt source for the DMA --> I had done this correctly for CAN1 (DMA1REQ = 70;), but I did not change this when I copied the code to set up the DMA for CAN2 which was IRQ 71 and not 70! Changing this to DMA1REQ = 71 for CAN2 fixed everything!