Reply by zsilinszkyz April 5, 20062006-04-05
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
>
Reply by Robert Milne April 4, 20062006-04-04
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
> >.
>
Reply by Steve Letkeman April 4, 20062006-04-04
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?
>
Reply by Ashwin April 4, 20062006-04-04
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?
Reply by Steve Letkeman April 4, 20062006-04-04
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;
> }
>
Reply by Ashwin April 4, 20062006-04-04
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;
}
Reply by Ashwin April 4, 20062006-04-04
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;
}

Yahoo! Groups Links
Reply by Rob Milne March 31, 20062006-03-31
Ashwin wrote:
> Hello Robert,
>
> Thanks for pointing that out to me. After years of MATLAB, I seem to
> have lost my touch with C. Anyway, I will incorporate your method in
> my revised code. However, I have a doubt with what you gave me...
>
> CAN0CTL0 &=~ INITRQ;
> while (CAN0CTL1 & INITAK);
>
> For one, what does &=~ signify? I assumed you would just use the > operator.
>

As John-Mark pointed out, This clears the INITRQ bit of Control 0
Register. Writing a zero will do if you don't care to keep any of the
other bits set. Once you get the hang of bit twiddling, this terse
style becomes second nature. Whitespace arrangement is always debatable
- precedence is not.

> Secondly, if I understand the initialization procedure right, after
> the first command, you poll the INITAK bit of CAN0CTL1 until it goes
> to 1, which means it is 0 till then. When you AND that with INITAK it
> will be 0 and will break the loop the very first time. Right? So,
> shouldn't it be
>
> while (!(CAN0CTL1 & INITAK)); or while (CAN0CTL1 & INITAK != 1)
>

Au contraire - The code is waiting for the CAN module to exit
initialization mode. When the INITAK bit of CAN0CTL1 becomes zero, the
CAN module can operate normally. The line states that we shall loop
here as long as CAN0CTL1 & INITAK is a true condition (logic 1) or in
other words, as long as INITAK is set.

You are confused about the difference between the & bitwise operator and
the &= assignment operator. a &= b is the same as a = a & b however
a & b by itself is simply a result in an accumulator that isn't
necessarily assigned to any memory location. In this case the
accumulator result of the a & b operation is checked to see if all 8
bits are zero or not.

The following is from my assembler listing (ICC12V6). My code is a bit
different in that I use a pointer to the register so that all 5 DP256
modules can share the 'canExitInitMode' func.

0B9D L250:
0B9D .dbline 1157
0B9D L251:
0B9D .dbline 1157
0B9D ; while (dev->module->CTL1 & INITAK);
0B9D EDE30002 ldy [2,x]
0BA1 0F410102 brclr 1,y,#1,X17
0BA5 20F6 bra L250
0BA7 X17:

As you can see, the while loop is compiled to a brclr loop. Assembler
never lies.

The MSCAN module is not as simple as SPI or SCI but it isn't rocket
science. The Freescale docs provide everything you need.

-rob

Yahoo! Groups Links
Reply by John-Mark Gurney March 31, 20062006-03-31
Ashwin wrote this message on Fri, Mar 31, 2006 at 21:15 -0000:
> Thanks for pointing that out to me. After years of MATLAB, I seem to
> have lost my touch with C. Anyway, I will incorporate your method in
> my revised code. However, I have a doubt with what you gave me...
>
> CAN0CTL0 &=~ INITRQ;
> while (CAN0CTL1 & INITAK);
>
> For one, what does &=~ signify? I assumed you would just use the > operator.

better grouped as:
CAN0CTL0 &= (~INITRQ);

~ is the not operator, changes binary 0110101 into 1001010... then:
a &= b;
is equal to:
a = a & b;

so, that above statement clears (unsets) the INITRQ bit(s) of CAN0CTL0...

--
John-Mark Gurney Voice: +1 415 225 5579

"All that I will do, has been done, All that I have, has not."

Yahoo! Groups Links
Reply by Ashwin March 31, 20062006-03-31
Hello Robert,

Thanks for pointing that out to me. After years of MATLAB, I seem to
have lost my touch with C. Anyway, I will incorporate your method in
my revised code. However, I have a doubt with what you gave me...

CAN0CTL0 &=~ INITRQ;
while (CAN0CTL1 & INITAK);

For one, what does &=~ signify? I assumed you would just use the operator.

Secondly, if I understand the initialization procedure right, after
the first command, you poll the INITAK bit of CAN0CTL1 until it goes
to 1, which means it is 0 till then. When you AND that with INITAK it
will be 0 and will break the loop the very first time. Right? So,
shouldn't it be

while (!(CAN0CTL1 & INITAK)); or while (CAN0CTL1 & INITAK != 1)

If this is taken care of, is the rest of the code regarding the
receiving aspect still good? I am not interested in the sending part
from the Motorola as of now.

Yahoo! Groups Links