EmbeddedRelated.com
Forums

CAN trouble on MC9212DP256B board

Started by Ashwin March 30, 2006
Hi Ashwin, CAN is not like RS232 where you connect the RX to TX
and vice versa and it works. With CAN the transmitting pin must
be seen by the receiving pin to tell whether it is winning arbitration
or not and to also see the receiving node insert an ack bit into the
data stream. It is best to use a CAN transceiver like a 82C250 (or equil)
and have two 120 ohm resistors at each end of the bus. If you
really have to hook it up right away, then make a one wire bus by
connecting the receive pins of both nodes together and connect a
small diode from that same connection to the tx pin (one diode per
board, cathode to tx pin) Then connect that same bus to Vcc with
a pull up resistor (4.7k to 10K is fine) What happens is that both
receive pins see a high signal unless either tx pin becomes dominant (low)
and forces both receive pins low (the diode drop won't matter).
Also, with CAN it is much easier to debug when you have one known
working node, preferably one that will show you the current state
of the bus as far as errors, bus off etc.
As far as debugging your program, examine memory and see if the
CAN message was actually received. If it was, check the flag that
should be set when a message is received. If that is set than you might
have an issue with the interrupt itself, not the CAN system.
I have posted sample CAN code to this list before, do a search
on this list or I can send it to you directly if you want to compare it
to your code.

Good luck!
Steve

Steven D. Letkeman BSc.
President - Zanthic Technologies Inc.
403-526-8318
www.zanthic.com Embedded micro-controllers and CAN interfaces
www.brightan.com Automated lighting systems
----- Original Message -----
From: "Ashwin"
To: <6...>
Sent: Tuesday, April 04, 2006 2:07 PM
Subject: [68HC12] Re: CAN trouble on MC9212DP256B board
>I am still unable to receive data from the host microcontroller via
> the CAN bus. The below code resides on my mc9s12dp256b chip. The PORTB
> BIT0 glows indicating that the Initialization was done. However, the
> PORTB BIT1 does not glow indicating that the ISR is not being triggered.
>
> I am connecting the RX and TX wires from the host controller into the
> corresponding pins of the CAN controller chip on the board. Is that
> the way to go?
> #include /* common defines and macros */
> #include /* derivative information */
> #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
>
> /* Acceptance Code Definitions */
> #define ACC_CODE_ID100 0x2000
> #define ACC_CODE_ID100_HIGH ((ACC_CODE_ID100&0xFF00)>>8)
> #define ACC_CODE_ID100_LOW (ACC_CODE_ID100&0x00FF)
>
> /* Mask Code Definitions */
> #define MASK_CODE_ST_ID 0x0007
> #define MASK_CODE_ST_ID_HIGH ((MASK_CODE_ST_ID&0xFF00)>>8)
> #define MASK_CODE_ST_ID_LOW (MASK_CODE_ST_ID&0xFF)
>
> #define bit(x) (1 << (x))
>
> #define INITRQ bit(0);
> #define INITAK bit(0);
> #define CANE bit(7);
>
> void CANinit(void)
> {
> CAN0CTL0 = INITRQ;
>
> CAN0CTL1 = CANE;
> CAN0BTR0 = 0xC7;
> CAN0BTR1 = 0x3A;
>
> // Acceptance Filters
> CAN0IDAC = 0x10;
> CAN0IDAR0 = ACC_CODE_ID100_HIGH;
> CAN0IDMR0 = MASK_CODE_ST_ID_HIGH;
> CAN0IDAR1 = ACC_CODE_ID100_LOW;
> CAN0IDMR1 = MASK_CODE_ST_ID_LOW;
> CAN0IDAC = 0x10; // Set four 16-bit Filters
> CAN0IDAR2 = 0x00; // 16-bit Filter 1
> CAN0IDMR2 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR3 = 0x00; // with ID 0x100
> CAN0IDMR3 = MASK_CODE_ST_ID_LOW;
> CAN0IDAR4 = 0x00; // 16-bit Filter 2
> CAN0IDMR4 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR5 = 0x00; // with ID 0x100
> CAN0IDMR5 = MASK_CODE_ST_ID_LOW; //
> CAN0IDAR6 = 0x00; // 16-bit Filter 3
> CAN0IDMR6 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR7 = 0x00; // with ID 0x100
> CAN0IDMR7 = MASK_CODE_ST_ID_LOW;
>
> CAN0CTL0 = 0x00;
>
> while ((CAN0CTL1 & INITAK));
> DDRB_BIT0 = 1;
> PORTB_BIT0 = 0;
> }
>
> void interrupt CAN0RxISR(void)
> {
> DDRB_BIT1 = 1;
> PORTB_BIT1 = 0;
>
> unsigned char length, index;
> unsigned char rxdata[8];
>
> length = (CAN0RXDLR & 0x0F);
> for (index=0; index > rxdata[index] = *(&CAN0RXDSR0 + index); /* Get received data */
> }
>
> CAN0RFLG = 0x01; /* Clear RXF */
> }
>
> void main ( )
> {
> CANinit ( );
>
> CAN0RFLG = 0xC3;
> CAN0RIER = 0x01;
> }
>
I am sorry, I meant CAN H and CAN L not TX and RX. The motorola board
has a CAN controller (MC33388). I am connecting to pins 11 and 12. Is
there anything else that should be done on the board? Jumper settings?
ahhhh, ok, so you have a MC33388 CAN "transceiver". I was just
talking to somebody (i think from this list) and they were saying this
was a tricky device to get going. If at all possible you need to eliminate
as many unknowns as possible, starting with that transceiver. Once you
know that your code is sending and receiving, then try and figure out the
transceiver if it has various modes. The other option is to force the bus
into a dominant state and check that the micro side is seeing the correct
values. Do the same for the CAN tx pin (when it is not being driven by
your program) and check that the receive pin is reflecting that value.
You have the 120 ohm termination resistors in place, right?

Steve

Steven D. Letkeman BSc.
President - Zanthic Technologies Inc.
403-526-8318
www.zanthic.com Embedded micro-controllers and CAN interfaces
www.brightan.com Automated lighting systems

----- Original Message -----
From: "Ashwin"
To: <6...>
Sent: Tuesday, April 04, 2006 3:04 PM
Subject: [68HC12] Re: CAN trouble on MC9212DP256B board
>I am sorry, I meant CAN H and CAN L not TX and RX. The motorola board
> has a CAN controller (MC33388). I am connecting to pins 11 and 12. Is
> there anything else that should be done on the board? Jumper settings?
>
Where are you actually setting PORTB BIT1 in the code below?
Also, the rxdata array is a local var which has no scope beyond the isr
func - completely unusable. Either make rxdata[] a global or write a
CAN buffer routine.
btw, your local var declarations must be the first thing after the curly
brackets.
Is there actually another CAN node on the bus that is reliably sending
data to be received?
My advice is that you either use a debugger or your uart to debug the code.

Here are the sci routines (I'll leave the sci init to you):
void put_char (char c)
{
while ((SCI0SR1 & bit(7)) == 0);
SCI0DRL = c;
}

void put_s (char* str)
{
while (*str)
put_char (*str++);
}

Inside your isr for loop, you can check your rx data by inserting this:

put_char (rxdata[index]);

Now set up teraterm or other terminal sw to read your debug output.

-rob

Ashwin wrote:

> I am still unable to receive data from the host microcontroller via
> the CAN bus. The below code resides on my mc9s12dp256b chip. The host
> is operating at a clock freq of 40MHz. The PORTB BIT0 glows indicating
> that the Initialization was done. However, the PORTB BIT1 does not
> glow indicating that the ISR is not being triggered. I don't know what
> to do:
>
> #include /* common defines and macros */
> #include /* derivative information */
> #pragma LINK_INFO DERIVATIVE "mc9s12dp256b"
>
> /* Acceptance Code Definitions */
> #define ACC_CODE_ID100 0x2000
> #define ACC_CODE_ID100_HIGH ((ACC_CODE_ID100&0xFF00)>>8)
> #define ACC_CODE_ID100_LOW (ACC_CODE_ID100&0x00FF)
>
> /* Mask Code Definitions */
> #define MASK_CODE_ST_ID 0x0007
> #define MASK_CODE_ST_ID_HIGH ((MASK_CODE_ST_ID&0xFF00)>>8)
> #define MASK_CODE_ST_ID_LOW (MASK_CODE_ST_ID&0xFF)
>
> #define bit(x) (1 << (x))
>
> #define INITRQ bit(0);
> #define INITAK bit(0);
> #define CANE bit(7);
>
> void CANinit(void)
> {
> CAN0CTL0 = INITRQ;
>
> CAN0CTL1 = CANE;
> CAN0BTR0 = 0xC7;
> CAN0BTR1 = 0x3A;
>
> // Acceptance Filters
> CAN0IDAC = 0x10;
> CAN0IDAR0 = ACC_CODE_ID100_HIGH;
> CAN0IDMR0 = MASK_CODE_ST_ID_HIGH;
> CAN0IDAR1 = ACC_CODE_ID100_LOW;
> CAN0IDMR1 = MASK_CODE_ST_ID_LOW;
> CAN0IDAC = 0x10; // Set four 16-bit Filters
> CAN0IDAR2 = 0x00; // 16-bit Filter 1
> CAN0IDMR2 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR3 = 0x00; // with ID 0x100
> CAN0IDMR3 = MASK_CODE_ST_ID_LOW;
> CAN0IDAR4 = 0x00; // 16-bit Filter 2
> CAN0IDMR4 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR5 = 0x00; // with ID 0x100
> CAN0IDMR5 = MASK_CODE_ST_ID_LOW; //
> CAN0IDAR6 = 0x00; // 16-bit Filter 3
> CAN0IDMR6 = MASK_CODE_ST_ID_HIGH; // Accepts Standard Data
> Frame Msg
> CAN0IDAR7 = 0x00; // with ID 0x100
> CAN0IDMR7 = MASK_CODE_ST_ID_LOW;
>
> CAN0CTL0 = 0x00;
>
> while ((CAN0CTL1 & INITAK));
> DDRB_BIT0 = 1;
> PORTB_BIT0 = 0;
> }
>
> void interrupt CAN0RxISR(void)
> {
> DDRB_BIT1 = 1;
> PORTB_BIT1 = 0;
>
> unsigned char length, index;
> unsigned char rxdata[8];
>
> length = (CAN0RXDLR & 0x0F);
> for (index=0; index > rxdata[index] = *(&CAN0RXDSR0 + index); /* Get received data */
> }
>
> CAN0RFLG = 0x01; /* Clear RXF */
> }
>
> void main ( )
> {
> CANinit ( );
>
> CAN0RFLG = 0xC3;
> CAN0RIER = 0x01;
> }
>
> SPONSORED LINKS
> Fast track
>
> Microcontrollers
>
> Technical support
> Intel microprocessors
> >.
>
The PORTB BIT1 is cleared right at the beginning of the CAN receive
interrupt routine. I guess the whole code is only good for seeing if
the receive interrupt works or not.

I'd first check what signal (if any) is getting to CAN pins of the uC.
Then check if the ISR table is set up correctly.
What about the baudrate? Is it the same as on the sending side?
The acceptance and mask registers can also cause the dropping of the
message. Are the setting of these correct?

Zoltan

--- In 6..., Robert Milne wrote:
>
> Where are you actually setting PORTB BIT1 in the code below?
> Also, the rxdata array is a local var which has no scope beyond the isr
> func - completely unusable. Either make rxdata[] a global or write a
> CAN buffer routine.
> btw, your local var declarations must be the first thing after the
curly
> brackets.
> Is there actually another CAN node on the bus that is reliably sending
> data to be received?
> My advice is that you either use a debugger or your uart to debug
the code.
>
> Here are the sci routines (I'll leave the sci init to you):
> void put_char (char c)
> {
> while ((SCI0SR1 & bit(7)) == 0);
> SCI0DRL = c;
> }
>
> void put_s (char* str)
> {
> while (*str)
> put_char (*str++);
> }
>
> Inside your isr for loop, you can check your rx data by inserting this:
>
> put_char (rxdata[index]);
>
> Now set up teraterm or other terminal sw to read your debug output.
>
> -rob
>