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:
- Enable the CAN module.
- Switch the CAN module to "configuration" operation mode.
- Configure the CAN module.
- 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;
}