3
\$\begingroup\$

I'm using a PIC32MX534F064L, and I just started working with the CAN module. The first thing I tried was using the examples from Microchip. None of them worked. The basic problem is these lines:

CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION);
while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION);

The while on the second line never completes.

I'll explain. The PIC32's CAN module has to be configured in the following order:

  1. Enable the CAN module.
  2. Switch the CAN module to "configuration" operation mode.
  3. Configure the CAN module.
  4. Switch CAN module to "normal" operation mode.

Step 2 and 4 are a little more complicated. Instead of just setting a register which would change the mode, there's a two-step process. You set a register (C1CON.REQOP) to request that the operation mode (C1CON.OPMOD) will change, and when the CAN module is ready to change, it does.

Anyway, here is the code. I'm sure I just forgot something, but scouring the Internet and trying various examples has been without result.

#include <plib.h>

#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1

#define SYS_FREQ (80000000L)
#define CAN_BUS_SPEED 250000

BYTE CAN1MessageFifoArea[2 * 8 * 16];

int main(void)
{
    CAN_BIT_CONFIG canBitConfig;
    CAN_OP_MODE mode;
    int i;

    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    CANEnableModule(CAN1,TRUE);
    while(C1CONbits.ON == 0);
    CANSetOperatingMode(CAN1, CAN_CONFIGURATION);
    while(CANGetOperatingMode(CAN1) != CAN_CONFIGURATION);

    canBitConfig.phaseSeg2Tq            = CAN_BIT_3TQ;
    canBitConfig.phaseSeg1Tq            = CAN_BIT_3TQ;
    canBitConfig.propagationSegTq       = CAN_BIT_3TQ;
    canBitConfig.phaseSeg2TimeSelect    = TRUE;
    canBitConfig.sample3Time            = TRUE;
    canBitConfig.syncJumpWidth          = CAN_BIT_2TQ;
    CANSetSpeed(CAN1,&canBitConfig,SYS_FREQ,CAN_BUS_SPEED);

    CANAssignMemoryBuffer(CAN1,CAN1MessageFifoArea,(2 * 8 * 16));

    CANConfigureChannelForTx(CAN1, CAN_CHANNEL0, 8,
                             CAN_TX_RTR_DISABLED, CAN_LOW_MEDIUM_PRIORITY);
    CANConfigureChannelForRx(CAN1, CAN_CHANNEL1, 8,
                             CAN_RX_FULL_RECEIVE);

    CANConfigureFilter      (CAN1, CAN_FILTER0, 0x8004001, CAN_EID);
    CANConfigureFilterMask  (CAN1, CAN_FILTER_MASK0, 0x3FFFFFFF,
                             CAN_EID, CAN_FILTER_MASK_IDE_TYPE);
    CANLinkFilterToChannel  (CAN1, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1);
    CANEnableFilter         (CAN1, CAN_FILTER0, TRUE);

    CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
    CANEnableModuleEvent(CAN1, CAN_RX_EVENT, TRUE);

    // The code gets stuck in the while and never finishes.
    C1CONbits.CANBUSY = 1;
    CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION);
    while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION);

    // This code is never reached
    i=0;
    while(1)
        ++i;
}
\$\endgroup\$
5
  • \$\begingroup\$ Are you working in the simulator, or with real hardware in emulation mode? Are you using an ICD or a PicKit? Do you have a CAN transciever on your target board and is it connected to a CAN bus with another device and two terminators? \$\endgroup\$
    – Martin
    Commented Nov 7, 2011 at 8:42
  • \$\begingroup\$ I'm working with a real PIC32 connected to MPLAB using an ICD3. I've got an MCP2551 connected to the C1TX and C1RX of my PIC. The MCP2551 is connected to a terminated CAN bus on which there is an FSM simulator. Do you think the PIC is refusing to complete the configuration of its CAN module because of external hardware? \$\endgroup\$ Commented Nov 7, 2011 at 8:58
  • 1
    \$\begingroup\$ It's possible, I've seen a PIC18's CAN module refuse to change mode because of a line condition. \$\endgroup\$
    – Martin
    Commented Nov 7, 2011 at 10:32
  • \$\begingroup\$ The new PICs have so much configuration of pins and what function on which pin, are you sure that you have that all correct? \$\endgroup\$
    – kenny
    Commented Nov 7, 2011 at 11:48
  • \$\begingroup\$ Just for fun I decided to try the same code on a different PIC, and it worked. I guess I managed to screw up the PIC somehow. Thanks for all the help! \$\endgroup\$ Commented Nov 7, 2011 at 12:16

2 Answers 2

7
\$\begingroup\$

Well, it turned out that if you connect a CAN transceiver to the CAN pins on the PIC, but fail to supply it with power, then the PIC never leaves configuration mode. Connecting the transceiver to a reliable power source solved the problem.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I have clearly not worked with a CAN project in a long time, this used to be part of my training to students, "If it sticks in the configuration right here then you have an issue with your communication." Sorry I was out of touch and did not help sooner. Glad you figured it out! \$\endgroup\$
    – Kortuk
    Commented Jun 20, 2012 at 23:25
  • \$\begingroup\$ @Kortuk: Well, better late than never. And honestly, your confirmation is encouraging. Thanks! \$\endgroup\$ Commented Jun 21, 2012 at 7:56
0
\$\begingroup\$

Here's an interesting one on a PIC18F-Q chip (PIC18F26Q84 to be exact). Code kept hanging when trying to exit CAN BUS Configuration with CANTX on RB2, CANRX on RB3. Code would NOT hang when changing the CAN Bus RX input from RB3 to some other input pin. Just trying to read RB3 as a digital input always came back as 0 even when set as a regular digital input pin and feeding 3.3V into it. The solution? TURN OFF JTAG Boundary Scan in CONFIG2. Update: At this point in time, the documentation and MCC for the PIC18F26Q84 incorrectly configures C1FIFOBA = 0x3800. That's great for the PIC18F27Q84 but the PIC18F26Q84 works a lot better with C1FIFOBA = 0x2600;

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.