Hello Freescale Forum,
I'm trying to set up CAN communication between a PC and a MCF51AC256 via the the following polling scheme the MCU side.
void main(void) { int msgs; setup_clocks(); init_can(); msgs = 0; for(;;){ /* Is Receiver FIFO not empty? */ if(CANRFLG & 0x1) { msgs++; /* clear CANRFLG_RXF */ CANRFLG = 0x1; } __RESET_WATCHDOG(); }}If I send a message from the PC it is received on the MCU end correctly(!), but CANRFLG_RXF is never cleared and there are overruns. So it looks as if the message is sent all the time (msgs grows). However the message is sent only once from the PC end! Debugging shows CANRXERR == 0x0 all the time, and the Receiver Flag Register CANRFLG always looks like this
CANRLGBit Field Values: WUPIF bits[ 7:7 ] = 0 No wake-up activity CSCIF bits[ 6:6 ] = 0 No change RSTAT bits[ 5:4 ] = 0 RXOK:0less than or equal to RX error CNTless than =96 TSTAT bits[ 3:2 ] = 0 TXOK:0less than or equal to TX error CNTless than =96 OVRIF bits[ 1:1 ] = 1 A data overrun detected RXF bits[ 0:0 ] = 1 Receiver FIFO not empty
The configuration of clocks and bit rates _looks_ okay: When I debug the control registers always look like this:
CANCTL0Bit Field Values: RXFRM bits[ 7:7 ] = 1 Valid message received RXACT bits[ 6:6 ] = 1 Receiving a message CSWAI bits[ 5:5 ] = 0 Module not affected by wait SYNCH bits[ 4:4 ] = 1 MSCAN synch to CAN bus TIME bits[ 3:3 ] = 0 Disable int MSCAN timer WUPE bits[ 2:2 ] = 0 Disabled SLPRQ bits[ 1:1 ] = 0 Running INITRQ bits[ 0:0 ] = 0 Normal operationCANCTL1Bit Field Values: CANE bits[ 7:7 ] = 1 Enabled CLKSRC bits[ 6:6 ] = 0 Oscillator clock LOOPB bits[ 5:5 ] = 0 Disabled LISTEN bits[ 4:4 ] = 1 Activated BORM bits[ 3:3 ] = 0 Automatic WUPM bits[ 2:2 ] = 0 On any dominant level SLPAK bits[ 1:1 ] = 0 Running INITAK bits[ 0:0 ] = 0 Running
I guess that if PC and MCU hat different bit rate settings CANCTL0_SYNCH wouldn't be set.
On the PC end I'm using a PEAK usb interface and the bundled PCAN-View program to transmit. That's why I don't think the problem comes from this end either. In PCAN-View the status of the bus switches to "BUSHEAVY" immediately after the message is sent.
I can also exclude hardware problems - I sucessfully could get a CAN connection with the same CAN-USB interface on the same board with another program which was created with Processor Expert and using interrupts.
I carefully read the reference manual of the MCF51AC256 and I tried multiple variations/configurations - I always end up with the same problem. I guess I'm missing something very important that's why i would be happy for any kind of hints or suggestions!
Switching to interrupts is unfortunately not an option to me. It has to be a polling scheme. I also must not use the Processor Expert.
Thanks in advance!
Stefan
For completness here are the remaining functions:
/* Sorry no comments - I copied the configuration from code which was generated by Processor Expert however */void setup_clocks(void) { SOPT2 = 0x28; MCGC4 = 0x0; MCGC2 = 0x26; MCGC1 = 0x0A; MCGC3 = 0x46; while(!MCGSC_LOCK) { __RESET_WATCHDOG(); } FCDIV=0x4E;}
void init_can(void){ int id; /* enable can */ CANCTL1_CANE = 1; /* enter config mode */ CANCTL0_INITRQ = 1; while(!CANCTL1_INITAK) { __RESET_WATCHDOG(); } /* config bit rate 500 kbit/s */ /* select external crystal (4 Mhz) as reference*/ CANCTL1_CLKsrc=0; /* synchronization jump Width = 2 Tq, Baudrate Prescaler = 1 */ CANBTR0 = 0x40; /* SAMP=1, Time Segment 2 = 4 Tq, Time Segment 1 = 3 Tq */ CANBTR1 = 0xB2; /* => Bit Time : 1 / 4e6 * (1 + 3 + 4) = 2e-6 */ /* => Bit Rate : 1 / 2e-6 = 0.5*e6 = 500k */ /* config two 32-bit filters */ CANIDAC = 0x00; /* 1. filter: accept only extended id (bits 28-0) */ id = 0x0DEADBEE; CANIDMR0 = 0x00; CANIDMR1 = 0x00; CANIDMR2 = 0x00; CANIDMR3 = 0x00; CANIDAR0 = (unsigned char) (id >> (28-7)) & 0xFF; CANIDAR1 = (unsigned char) (((id >> (20-7)) & 0xE0) | 0x18 | ((id >> (17-2)) & 0x07)); CANIDAR2 = (unsigned char) (id >> (14-7)) & 0xFF; CANIDAR3 = (unsigned char) (id << (7-6)) & 0xFE; /* 2. filter */ /* ignored for now */ /* enter normal mode */ CANCTL0_INITRQ = 0; while(!CANCTL1_INITAK) { __RESET_WATCHDOG(); } /* reset error flags */ CANRFLG |= 0xFE; /* disable interrupts */ CANTIER = 0x00; CANRIER = 0x00;}