EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

MSCAN problem

Started by Johannes Schmid May 6, 2009
Hi everybody!

I have a problem using the CAN-Bus interface of the HCS12 used in the
MicroSquirt(tm) ECU we use on our Formula race car.

Following the various data sheets I came up with the following code:

void CanInit(void)
{
/* Set up CAN communications */
/* Enable CAN, set Init mode so can change registers */
CANCTL1 |= 0x80;
CANCTL0 |= 0x01;

while(!(CANCTL1 & 0x01))
; // make sure in init mode

/* Set Can enable, use IPBusclk (24 MHz),clear rest */
CANCTL1 = 0xC0;
/* Set timing for .5Mbits/ sec */
CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
(16 Tq total including sync seg (=1)) */

CANIDAC &= ~0x30; /* no filters */

/* clear init mode */
CANCTL0 &= 0xFE;
/* wait for synch to bus */
while(!(CANCTL0 & 0x10));

/* no xmit yet */
CANTIER = 0x00;
/* clear RX flag to ready for CAN recv interrupt */
CANRFLG = 0xC3;
/* set CAN rcv full interrupt bit */
CANRIER = 0x01;
return;
}

void CanSend(CAN_message* msg)
{
unsigned char txbuffer, i;
static unsigned char flag = 1;

if (!flag)
return;
flag = 0;

if (!CANTFLG)
return; // everything is more important than messages from the
ECU, so just drop out if we cannot send

CANTBSEL = CANTFLG; // Select free buffer to use
txbuffer = CANTBSEL; // backup buffer

CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
CAN_TB0_IDR2 = 0;
CAN_TB0_IDR3 = 0;

for (i = 0; i < msg->length; i++) {
*(&CAN_TB0_DSR0 + i) = msg->data[i];
}

CAN_TB0_DLR = msg->length; // Set length
CAN_TB0_TBPR = 0; // priority

// Send message
CANTFLG = txbuffer;
}

However, when I send a single CAN message, MSCAN floods the CAN-Bus with
messages (sending probably any us) and never stops. I checked on the
osci and there is an ACK on the bus so I guess everything should be
fine. Do I need to clear some buffer to make it stop sending messages?

Thanks a lot for your help

Johannes
--
Johannes Schmid
High-Octane-Motorsports
Teamleiter Elektronik
j...@octanes.de
0179 / 1674917

I didn't look over your code but your comments about the message
continuing to
send caught my attention. This might be an obvious question, but do you
have
at least two CAN nodes on the network? CAN is not like RS232 where you
can just send a message to nobody, you must have another node with the
correct
settings for the message to be ACK'd. It also requires a properly
terminated
network, two 120 ohm resistors on each end and a common ground. Maybe
these have been covered but they are worth mentioning just in case...
Steve
--
Steven D. Letkeman BSc.
Zanthic Technologies Inc.
www.zanthic.com Embedded micro-controllers and CAN interfaces
Johannes Schmid wrote:
> Hi everybody!
>
> I have a problem using the CAN-Bus interface of the HCS12 used in the
> MicroSquirt(tm) ECU we use on our Formula race car.
>
> Following the various data sheets I came up with the following code:
>
> void CanInit(void)
> {
> /* Set up CAN communications */
> /* Enable CAN, set Init mode so can change registers */
> CANCTL1 |= 0x80;
> CANCTL0 |= 0x01;
>
> while(!(CANCTL1 & 0x01))
> ; // make sure in init mode
>
> /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> CANCTL1 = 0xC0;
> /* Set timing for .5Mbits/ sec */
> CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> (16 Tq total including sync seg (=1)) */
>
> CANIDAC &= ~0x30; /* no filters */
>
> /* clear init mode */
> CANCTL0 &= 0xFE;
> /* wait for synch to bus */
> while(!(CANCTL0 & 0x10));
>
> /* no xmit yet */
> CANTIER = 0x00;
> /* clear RX flag to ready for CAN recv interrupt */
> CANRFLG = 0xC3;
> /* set CAN rcv full interrupt bit */
> CANRIER = 0x01;
> return;
> }
>
> void CanSend(CAN_message* msg)
> {
> unsigned char txbuffer, i;
> static unsigned char flag = 1;
>
> if (!flag)
> return;
> flag = 0;
>
> if (!CANTFLG)
> return; // everything is more important than messages from the
> ECU, so just drop out if we cannot send
>
> CANTBSEL = CANTFLG; // Select free buffer to use
> txbuffer = CANTBSEL; // backup buffer
>
> CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
> CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
> CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> CAN_TB0_IDR2 = 0;
> CAN_TB0_IDR3 = 0;
>
> for (i = 0; i < msg->length; i++) {
> *(&CAN_TB0_DSR0 + i) = msg->data[i];
> }
>
> CAN_TB0_DLR = msg->length; // Set length
> CAN_TB0_TBPR = 0; // priority
>
> // Send message
> CANTFLG = txbuffer;
> }
>
> However, when I send a single CAN message, MSCAN floods the CAN-Bus with
> messages (sending probably any us) and never stops. I checked on the
> osci and there is an ACK on the bus so I guess everything should be
> fine. Do I need to clear some buffer to make it stop sending messages?
>
> Thanks a lot for your help
>
> Johannes
>
> --
> Johannes Schmid
> High-Octane-Motorsports
> Teamleiter Elektronik
> j...@octanes.de
> 0179 / 1674917

Hi!
> I didn't look over your code but your comments about the message
> continuing to
> send caught my attention. This might be an obvious question, but do
> you
> have
> at least two CAN nodes on the network? CAN is not like RS232 where you
> can just send a message to nobody, you must have another node with
> the
> correct
> settings for the message to be ACK'd. It also requires a properly
> terminated
> network, two 120 ohm resistors on each end and a common ground. Maybe
> these have been covered but they are worth mentioning just in case...

Yes, we have two terminations and tried with various nodes. As already
said, we also checked the ACK on the Bus using a scope. The other nodes
are known to work flawlessly as well as the Peak PCAN usb Dongle we use.

I was also suspected the ACK first but seems that this isn't the problem
(or the MSCAN does not recognize the ACK for some reason).

Regards,
Johannes
> --
> Steven D. Letkeman BSc.
> Zanthic Technologies Inc.
> www.zanthic.com Embedded micro-controllers and CAN interfaces
>
> Johannes Schmid wrote:
> >
> >
> > Hi everybody!
> >
> > I have a problem using the CAN-Bus interface of the HCS12 used in
> the
> > MicroSquirt(tm) ECU we use on our Formula race car.
> >
> > Following the various data sheets I came up with the following code:
> >
> > void CanInit(void)
> > {
> > /* Set up CAN communications */
> > /* Enable CAN, set Init mode so can change registers */
> > CANCTL1 |= 0x80;
> > CANCTL0 |= 0x01;
> >
> > while(!(CANCTL1 & 0x01))
> > ; // make sure in init mode
> >
> > /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> > CANCTL1 = 0xC0;
> > /* Set timing for .5Mbits/ sec */
> > CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> > CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> > (16 Tq total including sync seg (=1)) */
> >
> > CANIDAC &= ~0x30; /* no filters */
> >
> > /* clear init mode */
> > CANCTL0 &= 0xFE;
> > /* wait for synch to bus */
> > while(!(CANCTL0 & 0x10));
> >
> > /* no xmit yet */
> > CANTIER = 0x00;
> > /* clear RX flag to ready for CAN recv interrupt */
> > CANRFLG = 0xC3;
> > /* set CAN rcv full interrupt bit */
> > CANRIER = 0x01;
> > return;
> > }
> >
> > void CanSend(CAN_message* msg)
> > {
> > unsigned char txbuffer, i;
> > static unsigned char flag = 1;
> >
> > if (!flag)
> > return;
> > flag = 0;
> >
> > if (!CANTFLG)
> > return; // everything is more important than messages from the
> > ECU, so just drop out if we cannot send
> >
> > CANTBSEL = CANTFLG; // Select free buffer to use
> > txbuffer = CANTBSEL; // backup buffer
> >
> > CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
> > CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
> > CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> > CAN_TB0_IDR2 = 0;
> > CAN_TB0_IDR3 = 0;
> >
> > for (i = 0; i < msg->length; i++) {
> > *(&CAN_TB0_DSR0 + i) = msg->data[i];
> > }
> >
> > CAN_TB0_DLR = msg->length; // Set length
> > CAN_TB0_TBPR = 0; // priority
> >
> > // Send message
> > CANTFLG = txbuffer;
> > }
> >
> > However, when I send a single CAN message, MSCAN floods the CAN-Bus
> with
> > messages (sending probably any us) and never stops. I checked on the
> > osci and there is an ACK on the bus so I guess everything should be
> > fine. Do I need to clear some buffer to make it stop sending
> messages?
> >
> > Thanks a lot for your help
> >
> > Johannes
> >
> > --
> > Johannes Schmid
> > High-Octane-Motorsports
> > Teamleiter Elektronik
> > j...@octanes.de
> > 0179 / 1674917
> >
> --
Johannes Schmid
High-Octane-Motorsports
Teamleiter Elektronik
j...@octanes.de
0179 / 1674917

ok, I thought it was important to cover the basics first as you just
never know
where a person is starting from. Here is some very old and outdated code
but it may point you in the right direction...
Steve

// This file may be freely distributed as long as this header remains
// intact in order to encourage you to visit our web site
// at www.zanthic.com home of the CAN-4-USB interface
// This simple program was written as a quick and easy

// example of initializing and testing the msCAN port (V2.14)
// on an MC9S12 processor. No warranty implied or given.
// This program was written as a single file for
// simplicity and only some of the registers are included.
// Written by Steve Letkeman Feb 2004

// compiled using the ICC12 compiler from imagecraft (www.imagecraft.com)
// Vector file not included but only contains two entries, start at 0xFFFE
// and the CAN0 receive interrupt vector pointing to CAN_Receive()

// sends CAN ID 1 (29 bit) at power up and receives ID 2 (29 bit) and
// echos back to ID 1 when received

#define CAN0CTL0 *(unsigned char volatile *)(0x0140)
#define CAN0CTL1 *(unsigned char volatile *)(0x0141)
#define CAN0BTR0 *(unsigned char volatile *)(0x0142)
#define CAN0BTR1 *(unsigned char volatile *)(0x0143)
#define CAN0RFLG *(unsigned char volatile *)(0x0144)
#define CAN0RIER *(unsigned char volatile *)(0x0145)
#define CAN0TFLG *(unsigned char volatile *)(0x0146)
//#define CAN0TIER *(unsigned char volatile *)(0x0147)
//#define CAN0TARQ *(unsigned char volatile *)(0x0148)
//#define CAN0TAAK *(unsigned char volatile *)(0x0149)
#define CAN0TBSEL *(unsigned char volatile *)(0x014A)
#define CAN0IDAC *(unsigned char volatile *)(0x014B)
//#define CAN0RXERR *(unsigned char volatile *)(0x014E)
//#define CAN0TXERR *(unsigned char volatile *)(0x014F)
#define CAN0IDAR0 *(unsigned char volatile *)(0x0150)
#define CAN0IDAR1 *(unsigned char volatile *)(0x0151)
#define CAN0IDAR2 *(unsigned char volatile *)(0x0152)
#define CAN0IDAR3 *(unsigned char volatile *)(0x0153)
#define CAN0IDMR0 *(unsigned char volatile *)(0x0154)
#define CAN0IDMR1 *(unsigned char volatile *)(0x0155)
#define CAN0IDMR2 *(unsigned char volatile *)(0x0156)
#define CAN0IDMR3 *(unsigned char volatile *)(0x0157)
#define CAN0IDAR4 *(unsigned char volatile *)(0x0158)
#define CAN0IDAR5 *(unsigned char volatile *)(0x0159)
#define CAN0IDAR6 *(unsigned char volatile *)(0x015A)
#define CAN0IDAR7 *(unsigned char volatile *)(0x015B)
#define CAN0IDMR4 *(unsigned char volatile *)(0x015C)
#define CAN0IDMR5 *(unsigned char volatile *)(0x015D)
#define CAN0IDMR6 *(unsigned char volatile *)(0x015E)
#define CAN0IDMR7 *(unsigned char volatile *)(0x015F)
#define CAN0RXFG (unsigned char volatile *)(0x0160)
#define CAN0TXFG (unsigned char volatile *)(0x0170)

#define CANE 0x80
#define INITAK 1
#define INITRQ 1
#define SLPRQ 2
#define SLPAK 2

void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr);
void CANInit(void);

void main(void)
{
unsigned char BufPntr[8];

CANInit();

asm("cli");

BufPntr[0]=0x11;
BufPntr[1]=0x22;
BufPntr[2]=0x33;
BufPntr[3]=0x44;
BufPntr[4]=0x55;
BufPntr[5]=0x66;
BufPntr[6]=0x77;
BufPntr[7]=0x88;

SendCANMessage(8, BufPntr); // send a CAN packet
with 8 bytes of data

while(1); // wait here for
receive interupt

}

//
#############################################################################

// Incoming CAN messages will be caught here
#pragma interrupt_handler CAN_Receive
void CAN_Receive(void)
{
unsigned char Temp[8];

Temp[0]=*(CAN0RXFG+4); // Grab the first data byte
// currently no checking for
number of bytes etc
SendCANMessage(1, Temp); // send it back

CAN0RFLG |=1; // clear rec flag
}

//
#############################################################################

void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr)
{
unsigned char NACAN,C;

while(!CAN0TFLG); // wait for
available buffer
NACAN0TFLG; // get the
next available CAN buffer
CAN0TBSEL=NACAN;

*(CAN0TXFG+0)=0x00; // set the
transmit ID
*(CAN0TXFG+1)=0x08; // extended ID
(29 bit)
*(CAN0TXFG+2)=0x00;
*(CAN0TXFG+3)=0x02; //
ID-00-00-01

if (NumBytes>8) NumBytes=8;
for (C=0;C *(CAN0TXFG+4+C)=*BufPntr++; // store the data

*(CAN0TXFG+0x0C)=NumBytes; // set number of
bytes to send

NACAN0TBSEL;
CAN0TFLG =NACAN; // transmit
}

//
#############################################################################

void CANInit(void)
{
CAN0CTL0 |= INITRQ; // set
INITRQ, this will also set INITAK
while (!(CAN0CTL1 & INITAK)); // wait for init
mode to occur

CAN0CTL1 = CANE; // Set CANE just
in case this is the first time after reset

CAN0BTR0=0x03;
CAN0BTR1=0x32; // for a CAN
Baud of 500kbps at 16Mhz crystal

CAN0IDMR0=0x00;
CAN0IDMR1=0x08; //IDE=1
CAN0IDMR2=0x00;
CAN0IDMR3=0x00;

CAN0IDAR0=0x00;
CAN0IDAR1=0x18; // SRR&IDE=1
CAN0IDAR2=0x00;
CAN0IDAR3=0x04; // ID=2, remote
frame (bit 0)=0

// set the second filter to must match 0xFFFFFFFF
CAN0IDMR4=0;
CAN0IDMR5=8; //IDE=1
CAN0IDMR6=0;
CAN0IDMR7=0;
CAN0IDAR4=0xFF;
CAN0IDAR5=0xFF;
CAN0IDAR6=0xFF;
CAN0IDAR7=0xFF;

CAN0IDAC=0; // set filters to
2 32 bit acceptance filters

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

CAN0CTL1 |= CANE; // Set CANE
just in case this is the first time after reset
CAN0RIER |= 1; // enable
receive interrupt

}
Johannes Schmid wrote:
> Hi!
>
> > I didn't look over your code but your comments about the message
> > continuing to
> > send caught my attention. This might be an obvious question, but do
> > you
> > have
> > at least two CAN nodes on the network? CAN is not like RS232 where you
> > can just send a message to nobody, you must have another node with
> > the
> > correct
> > settings for the message to be ACK'd. It also requires a properly
> > terminated
> > network, two 120 ohm resistors on each end and a common ground. Maybe
> > these have been covered but they are worth mentioning just in case...
>
> Yes, we have two terminations and tried with various nodes. As already
> said, we also checked the ACK on the Bus using a scope. The other nodes
> are known to work flawlessly as well as the Peak PCAN usb Dongle we use.
>
> I was also suspected the ACK first but seems that this isn't the problem
> (or the MSCAN does not recognize the ACK for some reason).
>
> Regards,
> Johannes
>
> > --
> > Steven D. Letkeman BSc.
> > Zanthic Technologies Inc.
> > www.zanthic.com Embedded micro-controllers and CAN interfaces
> >
> > Johannes Schmid wrote:
> > >
> > >
> > > Hi everybody!
> > >
> > > I have a problem using the CAN-Bus interface of the HCS12 used in
> > the
> > > MicroSquirt(tm) ECU we use on our Formula race car.
> > >
> > > Following the various data sheets I came up with the following code:
> > >
> > > void CanInit(void)
> > > {
> > > /* Set up CAN communications */
> > > /* Enable CAN, set Init mode so can change registers */
> > > CANCTL1 |= 0x80;
> > > CANCTL0 |= 0x01;
> > >
> > > while(!(CANCTL1 & 0x01))
> > > ; // make sure in init mode
> > >
> > > /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> > > CANCTL1 = 0xC0;
> > > /* Set timing for .5Mbits/ sec */
> > > CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> > > CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> > > (16 Tq total including sync seg (=1)) */
> > >
> > > CANIDAC &= ~0x30; /* no filters */
> > >
> > > /* clear init mode */
> > > CANCTL0 &= 0xFE;
> > > /* wait for synch to bus */
> > > while(!(CANCTL0 & 0x10));
> > >
> > > /* no xmit yet */
> > > CANTIER = 0x00;
> > > /* clear RX flag to ready for CAN recv interrupt */
> > > CANRFLG = 0xC3;
> > > /* set CAN rcv full interrupt bit */
> > > CANRIER = 0x01;
> > > return;
> > > }
> > >
> > > void CanSend(CAN_message* msg)
> > > {
> > > unsigned char txbuffer, i;
> > > static unsigned char flag = 1;
> > >
> > > if (!flag)
> > > return;
> > > flag = 0;
> > >
> > > if (!CANTFLG)
> > > return; // everything is more important than messages from the
> > > ECU, so just drop out if we cannot send
> > >
> > > CANTBSEL = CANTFLG; // Select free buffer to use
> > > txbuffer = CANTBSEL; // backup buffer
> > >
> > > CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
> > > CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
> > > CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> > > CAN_TB0_IDR2 = 0;
> > > CAN_TB0_IDR3 = 0;
> > >
> > > for (i = 0; i < msg->length; i++) {
> > > *(&CAN_TB0_DSR0 + i) = msg->data[i];
> > > }
> > >
> > > CAN_TB0_DLR = msg->length; // Set length
> > > CAN_TB0_TBPR = 0; // priority
> > >
> > > // Send message
> > > CANTFLG = txbuffer;
> > > }
> > >
> > > However, when I send a single CAN message, MSCAN floods the CAN-Bus
> > with
> > > messages (sending probably any us) and never stops. I checked on the
> > > osci and there is an ACK on the bus so I guess everything should be
> > > fine. Do I need to clear some buffer to make it stop sending
> > messages?
> > >
> > > Thanks a lot for your help
> > >
> > > Johannes
> > >
> > > --
> > > Johannes Schmid
> > > High-Octane-Motorsports
> > > Teamleiter Elektronik
> > > j...@octanes.de
>
> > > 0179 / 1674917
> > >
> > >
> >
> >
> >
> >
> >
> --
> Johannes Schmid
> High-Octane-Motorsports
> Teamleiter Elektronik
> j...@octanes.de
> 0179 / 1674917

Hi!

Thanks, I think I found this in the mailing list archive before because
this was the code I started from. I had to change some names because
register definition were a bit different (only one MSCAN, so CAN0CTL
becomes CANCTL, etc.) and we use short identifiers (11 bit) but in the
end I implemented exactly this.

Did this work correctly for you on real hardware?

Thanks,
Johannes

Am Mittwoch, den 06.05.2009, 15:23 -0600 schrieb Steve Letkeman:
> ok, I thought it was important to cover the basics first as you just
> never know
> where a person is starting from. Here is some very old and outdated
> code
> but it may point you in the right direction...
> Steve
>
> // This file may be freely distributed as long as this header remains
> // intact in order to encourage you to visit our web site
> // at www.zanthic.com home of the CAN-4-USB interface
> // This simple program was written as a quick and easy
>
> // example of initializing and testing the msCAN port (V2.14)
> // on an MC9S12 processor. No warranty implied or given.
> // This program was written as a single file for
> // simplicity and only some of the registers are included.
> // Written by Steve Letkeman Feb 2004
>
> // compiled using the ICC12 compiler from imagecraft
> (www.imagecraft.com)
> // Vector file not included but only contains two entries, start at
> 0xFFFE
> // and the CAN0 receive interrupt vector pointing to CAN_Receive()
>
> // sends CAN ID 1 (29 bit) at power up and receives ID 2 (29 bit) and
> // echos back to ID 1 when received
>
> #define CAN0CTL0 *(unsigned char volatile *)(0x0140)
> #define CAN0CTL1 *(unsigned char volatile *)(0x0141)
> #define CAN0BTR0 *(unsigned char volatile *)(0x0142)
> #define CAN0BTR1 *(unsigned char volatile *)(0x0143)
> #define CAN0RFLG *(unsigned char volatile *)(0x0144)
> #define CAN0RIER *(unsigned char volatile *)(0x0145)
> #define CAN0TFLG *(unsigned char volatile *)(0x0146)
> //#define CAN0TIER *(unsigned char volatile *)(0x0147)
> //#define CAN0TARQ *(unsigned char volatile *)(0x0148)
> //#define CAN0TAAK *(unsigned char volatile *)(0x0149)
> #define CAN0TBSEL *(unsigned char volatile *)(0x014A)
> #define CAN0IDAC *(unsigned char volatile *)(0x014B)
> //#define CAN0RXERR *(unsigned char volatile *)(0x014E)
> //#define CAN0TXERR *(unsigned char volatile *)(0x014F)
> #define CAN0IDAR0 *(unsigned char volatile *)(0x0150)
> #define CAN0IDAR1 *(unsigned char volatile *)(0x0151)
> #define CAN0IDAR2 *(unsigned char volatile *)(0x0152)
> #define CAN0IDAR3 *(unsigned char volatile *)(0x0153)
> #define CAN0IDMR0 *(unsigned char volatile *)(0x0154)
> #define CAN0IDMR1 *(unsigned char volatile *)(0x0155)
> #define CAN0IDMR2 *(unsigned char volatile *)(0x0156)
> #define CAN0IDMR3 *(unsigned char volatile *)(0x0157)
> #define CAN0IDAR4 *(unsigned char volatile *)(0x0158)
> #define CAN0IDAR5 *(unsigned char volatile *)(0x0159)
> #define CAN0IDAR6 *(unsigned char volatile *)(0x015A)
> #define CAN0IDAR7 *(unsigned char volatile *)(0x015B)
> #define CAN0IDMR4 *(unsigned char volatile *)(0x015C)
> #define CAN0IDMR5 *(unsigned char volatile *)(0x015D)
> #define CAN0IDMR6 *(unsigned char volatile *)(0x015E)
> #define CAN0IDMR7 *(unsigned char volatile *)(0x015F)
> #define CAN0RXFG (unsigned char volatile *)(0x0160)
> #define CAN0TXFG (unsigned char volatile *)(0x0170)
>
> #define CANE 0x80
> #define INITAK 1
> #define INITRQ 1
> #define SLPRQ 2
> #define SLPAK 2
>
> void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr);
> void CANInit(void);
>
> void main(void)
> {
> unsigned char BufPntr[8];
>
> CANInit();
>
> asm("cli");
>
> BufPntr[0]=0x11;
> BufPntr[1]=0x22;
> BufPntr[2]=0x33;
> BufPntr[3]=0x44;
> BufPntr[4]=0x55;
> BufPntr[5]=0x66;
> BufPntr[6]=0x77;
> BufPntr[7]=0x88;
>
> SendCANMessage(8, BufPntr); // send a CAN packet
> with 8 bytes of data
>
> while(1); // wait here for
> receive interupt
>
> }
>
> //
> #############################################################################
>
> // Incoming CAN messages will be caught here
> #pragma interrupt_handler CAN_Receive
> void CAN_Receive(void)
> {
> unsigned char Temp[8];
>
> Temp[0]=*(CAN0RXFG+4); // Grab the first data byte
> // currently no checking for
> number of bytes etc
> SendCANMessage(1, Temp); // send it back
>
> CAN0RFLG |=1; // clear rec flag
> }
>
> //
> #############################################################################
>
> void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr)
> {
> unsigned char NACAN,C;
>
> while(!CAN0TFLG); // wait for
> available buffer
> NACAN0TFLG; // get the
> next available CAN buffer
> CAN0TBSEL=NACAN;
>
> *(CAN0TXFG+0)=0x00; // set the
> transmit ID
> *(CAN0TXFG+1)=0x08; // extended ID
> (29 bit)
> *(CAN0TXFG+2)=0x00;
> *(CAN0TXFG+3)=0x02; //
> ID-00-00-01
>
> if (NumBytes>8) NumBytes=8;
> for (C=0;C > *(CAN0TXFG+4+C)=*BufPntr++; // store the data
>
> *(CAN0TXFG+0x0C)=NumBytes; // set number of
> bytes to send
>
> NACAN0TBSEL;
> CAN0TFLG =NACAN; // transmit
> }
>
> //
> #############################################################################
>
> void CANInit(void)
> {
> CAN0CTL0 |= INITRQ; // set
> INITRQ, this will also set INITAK
> while (!(CAN0CTL1 & INITAK)); // wait for init
> mode to occur
>
> CAN0CTL1 = CANE; // Set CANE just
> in case this is the first time after reset
>
> CAN0BTR0=0x03;
> CAN0BTR1=0x32; // for a CAN
> Baud of 500kbps at 16Mhz crystal
>
> CAN0IDMR0=0x00;
> CAN0IDMR1=0x08; //IDE=1
> CAN0IDMR2=0x00;
> CAN0IDMR3=0x00;
>
> CAN0IDAR0=0x00;
> CAN0IDAR1=0x18; // SRR&IDE=1
> CAN0IDAR2=0x00;
> CAN0IDAR3=0x04; // ID=2, remote
> frame (bit 0)=0
>
> // set the second filter to must match 0xFFFFFFFF
> CAN0IDMR4=0;
> CAN0IDMR5=8; //IDE=1
> CAN0IDMR6=0;
> CAN0IDMR7=0;
> CAN0IDAR4=0xFF;
> CAN0IDAR5=0xFF;
> CAN0IDAR6=0xFF;
> CAN0IDAR7=0xFF;
>
> CAN0IDAC=0; // set filters to
> 2 32 bit acceptance filters
>
> CAN0CTL0 &= ~INITRQ; // clear
> INITRQ
> while (CAN0CTL1 & INITAK);
>
> CAN0CTL1 |= CANE; // Set CANE
> just in case this is the first time after reset
> CAN0RIER |= 1; // enable
> receive interrupt
>
> }
>
> Johannes Schmid wrote:
> >
> >
> > Hi!
> >
> > > I didn't look over your code but your comments about the message
> > > continuing to
> > > send caught my attention. This might be an obvious question, but
> do
> > > you
> > > have
> > > at least two CAN nodes on the network? CAN is not like RS232 where
> you
> > > can just send a message to nobody, you must have another node with
> > > the
> > > correct
> > > settings for the message to be ACK'd. It also requires a properly
> > > terminated
> > > network, two 120 ohm resistors on each end and a common ground.
> Maybe
> > > these have been covered but they are worth mentioning just in
> case...
> >
> > Yes, we have two terminations and tried with various nodes. As
> already
> > said, we also checked the ACK on the Bus using a scope. The other
> nodes
> > are known to work flawlessly as well as the Peak PCAN usb Dongle we
> use.
> >
> > I was also suspected the ACK first but seems that this isn't the
> problem
> > (or the MSCAN does not recognize the ACK for some reason).
> >
> > Regards,
> > Johannes
> >
> > > --
> > > Steven D. Letkeman BSc.
> > > Zanthic Technologies Inc.
> > > www.zanthic.com Embedded micro-controllers and CAN interfaces
> > >
> > > Johannes Schmid wrote:
> > > >
> > > >
> > > > Hi everybody!
> > > >
> > > > I have a problem using the CAN-Bus interface of the HCS12 used
> in
> > > the
> > > > MicroSquirt(tm) ECU we use on our Formula race car.
> > > >
> > > > Following the various data sheets I came up with the following
> code:
> > > >
> > > > void CanInit(void)
> > > > {
> > > > /* Set up CAN communications */
> > > > /* Enable CAN, set Init mode so can change registers */
> > > > CANCTL1 |= 0x80;
> > > > CANCTL0 |= 0x01;
> > > >
> > > > while(!(CANCTL1 & 0x01))
> > > > ; // make sure in init mode
> > > >
> > > > /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> > > > CANCTL1 = 0xC0;
> > > > /* Set timing for .5Mbits/ sec */
> > > > CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> > > > CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> > > > (16 Tq total including sync seg (=1)) */
> > > >
> > > > CANIDAC &= ~0x30; /* no filters */
> > > >
> > > > /* clear init mode */
> > > > CANCTL0 &= 0xFE;
> > > > /* wait for synch to bus */
> > > > while(!(CANCTL0 & 0x10));
> > > >
> > > > /* no xmit yet */
> > > > CANTIER = 0x00;
> > > > /* clear RX flag to ready for CAN recv interrupt */
> > > > CANRFLG = 0xC3;
> > > > /* set CAN rcv full interrupt bit */
> > > > CANRIER = 0x01;
> > > > return;
> > > > }
> > > >
> > > > void CanSend(CAN_message* msg)
> > > > {
> > > > unsigned char txbuffer, i;
> > > > static unsigned char flag = 1;
> > > >
> > > > if (!flag)
> > > > return;
> > > > flag = 0;
> > > >
> > > > if (!CANTFLG)
> > > > return; // everything is more important than messages from the
> > > > ECU, so just drop out if we cannot send
> > > >
> > > > CANTBSEL = CANTFLG; // Select free buffer to use
> > > > txbuffer = CANTBSEL; // backup buffer
> > > >
> > > > CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of
> id
> > > > CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of
> id;
> > > > CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> > > > CAN_TB0_IDR2 = 0;
> > > > CAN_TB0_IDR3 = 0;
> > > >
> > > > for (i = 0; i < msg->length; i++) {
> > > > *(&CAN_TB0_DSR0 + i) = msg->data[i];
> > > > }
> > > >
> > > > CAN_TB0_DLR = msg->length; // Set length
> > > > CAN_TB0_TBPR = 0; // priority
> > > >
> > > > // Send message
> > > > CANTFLG = txbuffer;
> > > > }
> > > >
> > > > However, when I send a single CAN message, MSCAN floods the
> CAN-Bus
> > > with
> > > > messages (sending probably any us) and never stops. I checked on
> the
> > > > osci and there is an ACK on the bus so I guess everything should
> be
> > > > fine. Do I need to clear some buffer to make it stop sending
> > > messages?
> > > >
> > > > Thanks a lot for your help
> > > >
> > > > Johannes
> > > >
> > > > --
> > > > Johannes Schmid
> > > > High-Octane-Motorsports
> > > > Teamleiter Elektronik
> > > > j...@octanes.de > 40octanes.de>
> >
> > > > 0179 / 1674917
> > > >
> > > >
> > >
> > >
> > >
> > >
> > >
> > --
> > Johannes Schmid
> > High-Octane-Motorsports
> > Teamleiter Elektronik
> > j...@octanes.de
> > 0179 / 1674917
> >
> --
Johannes Schmid
High-Octane-Motorsports
Teamleiter Elektronik
j...@octanes.de
0179 / 1674917

yes, it did work on hardware. Is it possible you have a hardware rec
pin issue? That
would explain the correct Ack on the bus and the continuous sending. Is
there any
pin routing involved in your scheme, maybe?
S
Johannes Schmid wrote:
> Hi!
>
> Thanks, I think I found this in the mailing list archive before because
> this was the code I started from. I had to change some names because
> register definition were a bit different (only one MSCAN, so CAN0CTL
> becomes CANCTL, etc.) and we use short identifiers (11 bit) but in the
> end I implemented exactly this.
>
> Did this work correctly for you on real hardware?
>
> Thanks,
> Johannes
>
> Am Mittwoch, den 06.05.2009, 15:23 -0600 schrieb Steve Letkeman:
> >
> >
> > ok, I thought it was important to cover the basics first as you just
> > never know
> > where a person is starting from. Here is some very old and outdated
> > code
> > but it may point you in the right direction...
> > Steve
> >
> > // This file may be freely distributed as long as this header remains
> > // intact in order to encourage you to visit our web site
> > // at www.zanthic.com home of the CAN-4-USB interface
> > // This simple program was written as a quick and easy
> >
> > // example of initializing and testing the msCAN port (V2.14)
> > // on an MC9S12 processor. No warranty implied or given.
> > // This program was written as a single file for
> > // simplicity and only some of the registers are included.
> > // Written by Steve Letkeman Feb 2004
> >
> > // compiled using the ICC12 compiler from imagecraft
> > (www.imagecraft.com)
> > // Vector file not included but only contains two entries, start at
> > 0xFFFE
> > // and the CAN0 receive interrupt vector pointing to CAN_Receive()
> >
> > // sends CAN ID 1 (29 bit) at power up and receives ID 2 (29 bit) and
> > // echos back to ID 1 when received
> >
> > #define CAN0CTL0 *(unsigned char volatile *)(0x0140)
> > #define CAN0CTL1 *(unsigned char volatile *)(0x0141)
> > #define CAN0BTR0 *(unsigned char volatile *)(0x0142)
> > #define CAN0BTR1 *(unsigned char volatile *)(0x0143)
> > #define CAN0RFLG *(unsigned char volatile *)(0x0144)
> > #define CAN0RIER *(unsigned char volatile *)(0x0145)
> > #define CAN0TFLG *(unsigned char volatile *)(0x0146)
> > //#define CAN0TIER *(unsigned char volatile *)(0x0147)
> > //#define CAN0TARQ *(unsigned char volatile *)(0x0148)
> > //#define CAN0TAAK *(unsigned char volatile *)(0x0149)
> > #define CAN0TBSEL *(unsigned char volatile *)(0x014A)
> > #define CAN0IDAC *(unsigned char volatile *)(0x014B)
> > //#define CAN0RXERR *(unsigned char volatile *)(0x014E)
> > //#define CAN0TXERR *(unsigned char volatile *)(0x014F)
> > #define CAN0IDAR0 *(unsigned char volatile *)(0x0150)
> > #define CAN0IDAR1 *(unsigned char volatile *)(0x0151)
> > #define CAN0IDAR2 *(unsigned char volatile *)(0x0152)
> > #define CAN0IDAR3 *(unsigned char volatile *)(0x0153)
> > #define CAN0IDMR0 *(unsigned char volatile *)(0x0154)
> > #define CAN0IDMR1 *(unsigned char volatile *)(0x0155)
> > #define CAN0IDMR2 *(unsigned char volatile *)(0x0156)
> > #define CAN0IDMR3 *(unsigned char volatile *)(0x0157)
> > #define CAN0IDAR4 *(unsigned char volatile *)(0x0158)
> > #define CAN0IDAR5 *(unsigned char volatile *)(0x0159)
> > #define CAN0IDAR6 *(unsigned char volatile *)(0x015A)
> > #define CAN0IDAR7 *(unsigned char volatile *)(0x015B)
> > #define CAN0IDMR4 *(unsigned char volatile *)(0x015C)
> > #define CAN0IDMR5 *(unsigned char volatile *)(0x015D)
> > #define CAN0IDMR6 *(unsigned char volatile *)(0x015E)
> > #define CAN0IDMR7 *(unsigned char volatile *)(0x015F)
> > #define CAN0RXFG (unsigned char volatile *)(0x0160)
> > #define CAN0TXFG (unsigned char volatile *)(0x0170)
> >
> > #define CANE 0x80
> > #define INITAK 1
> > #define INITRQ 1
> > #define SLPRQ 2
> > #define SLPAK 2
> >
> > void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr);
> > void CANInit(void);
> >
> > void main(void)
> > {
> > unsigned char BufPntr[8];
> >
> > CANInit();
> >
> > asm("cli");
> >
> > BufPntr[0]=0x11;
> > BufPntr[1]=0x22;
> > BufPntr[2]=0x33;
> > BufPntr[3]=0x44;
> > BufPntr[4]=0x55;
> > BufPntr[5]=0x66;
> > BufPntr[6]=0x77;
> > BufPntr[7]=0x88;
> >
> > SendCANMessage(8, BufPntr); // send a CAN packet
> > with 8 bytes of data
> >
> > while(1); // wait here for
> > receive interupt
> >
> > }
> >
> > //
> >
> #############################################################################
>
> >
> > // Incoming CAN messages will be caught here
> > #pragma interrupt_handler CAN_Receive
> > void CAN_Receive(void)
> > {
> > unsigned char Temp[8];
> >
> > Temp[0]=*(CAN0RXFG+4); // Grab the first data byte
> > // currently no checking for
> > number of bytes etc
> > SendCANMessage(1, Temp); // send it back
> >
> > CAN0RFLG |=1; // clear rec flag
> > }
> >
> > //
> >
> #############################################################################
>
> >
> > void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr)
> > {
> > unsigned char NACAN,C;
> >
> > while(!CAN0TFLG); // wait for
> > available buffer
> > NACAN0TFLG; // get the
> > next available CAN buffer
> > CAN0TBSEL=NACAN;
> >
> > *(CAN0TXFG+0)=0x00; // set the
> > transmit ID
> > *(CAN0TXFG+1)=0x08; // extended ID
> > (29 bit)
> > *(CAN0TXFG+2)=0x00;
> > *(CAN0TXFG+3)=0x02; //
> > ID-00-00-01
> >
> > if (NumBytes>8) NumBytes=8;
> > for (C=0;C > > *(CAN0TXFG+4+C)=*BufPntr++; // store the data
> >
> > *(CAN0TXFG+0x0C)=NumBytes; // set number of
> > bytes to send
> >
> > NACAN0TBSEL;
> > CAN0TFLG =NACAN; // transmit
> > }
> >
> > //
> >
> #############################################################################
>
> >
> > void CANInit(void)
> > {
> > CAN0CTL0 |= INITRQ; // set
> > INITRQ, this will also set INITAK
> > while (!(CAN0CTL1 & INITAK)); // wait for init
> > mode to occur
> >
> > CAN0CTL1 = CANE; // Set CANE just
> > in case this is the first time after reset
> >
> > CAN0BTR0=0x03;
> > CAN0BTR1=0x32; // for a CAN
> > Baud of 500kbps at 16Mhz crystal
> >
> > CAN0IDMR0=0x00;
> > CAN0IDMR1=0x08; //IDE=1
> > CAN0IDMR2=0x00;
> > CAN0IDMR3=0x00;
> >
> > CAN0IDAR0=0x00;
> > CAN0IDAR1=0x18; // SRR&IDE=1
> > CAN0IDAR2=0x00;
> > CAN0IDAR3=0x04; // ID=2, remote
> > frame (bit 0)=0
> >
> > // set the second filter to must match 0xFFFFFFFF
> > CAN0IDMR4=0;
> > CAN0IDMR5=8; //IDE=1
> > CAN0IDMR6=0;
> > CAN0IDMR7=0;
> > CAN0IDAR4=0xFF;
> > CAN0IDAR5=0xFF;
> > CAN0IDAR6=0xFF;
> > CAN0IDAR7=0xFF;
> >
> > CAN0IDAC=0; // set filters to
> > 2 32 bit acceptance filters
> >
> > CAN0CTL0 &= ~INITRQ; // clear
> > INITRQ
> > while (CAN0CTL1 & INITAK);
> >
> > CAN0CTL1 |= CANE; // Set CANE
> > just in case this is the first time after reset
> > CAN0RIER |= 1; // enable
> > receive interrupt
> >
> > }
> >
> > Johannes Schmid wrote:
> > >
> > >
> > > Hi!
> > >
> > > > I didn't look over your code but your comments about the message
> > > > continuing to
> > > > send caught my attention. This might be an obvious question, but
> > do
> > > > you
> > > > have
> > > > at least two CAN nodes on the network? CAN is not like RS232 where
> > you
> > > > can just send a message to nobody, you must have another node with
> > > > the
> > > > correct
> > > > settings for the message to be ACK'd. It also requires a properly
> > > > terminated
> > > > network, two 120 ohm resistors on each end and a common ground.
> > Maybe
> > > > these have been covered but they are worth mentioning just in
> > case...
> > >
> > > Yes, we have two terminations and tried with various nodes. As
> > already
> > > said, we also checked the ACK on the Bus using a scope. The other
> > nodes
> > > are known to work flawlessly as well as the Peak PCAN usb Dongle we
> > use.
> > >
> > > I was also suspected the ACK first but seems that this isn't the
> > problem
> > > (or the MSCAN does not recognize the ACK for some reason).
> > >
> > > Regards,
> > > Johannes
> > >
> > > > --
> > > > Steven D. Letkeman BSc.
> > > > Zanthic Technologies Inc.
> > > > www.zanthic.com Embedded micro-controllers and CAN interfaces
> > > >
> > > > Johannes Schmid wrote:
> > > > >
> > > > >
> > > > > Hi everybody!
> > > > >
> > > > > I have a problem using the CAN-Bus interface of the HCS12 used
> > in
> > > > the
> > > > > MicroSquirt(tm) ECU we use on our Formula race car.
> > > > >
> > > > > Following the various data sheets I came up with the following
> > code:
> > > > >
> > > > > void CanInit(void)
> > > > > {
> > > > > /* Set up CAN communications */
> > > > > /* Enable CAN, set Init mode so can change registers */
> > > > > CANCTL1 |= 0x80;
> > > > > CANCTL0 |= 0x01;
> > > > >
> > > > > while(!(CANCTL1 & 0x01))
> > > > > ; // make sure in init mode
> > > > >
> > > > > /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> > > > > CANCTL1 = 0xC0;
> > > > > /* Set timing for .5Mbits/ sec */
> > > > > CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> > > > > CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> > > > > (16 Tq total including sync seg (=1)) */
> > > > >
> > > > > CANIDAC &= ~0x30; /* no filters */
> > > > >
> > > > > /* clear init mode */
> > > > > CANCTL0 &= 0xFE;
> > > > > /* wait for synch to bus */
> > > > > while(!(CANCTL0 & 0x10));
> > > > >
> > > > > /* no xmit yet */
> > > > > CANTIER = 0x00;
> > > > > /* clear RX flag to ready for CAN recv interrupt */
> > > > > CANRFLG = 0xC3;
> > > > > /* set CAN rcv full interrupt bit */
> > > > > CANRIER = 0x01;
> > > > > return;
> > > > > }
> > > > >
> > > > > void CanSend(CAN_message* msg)
> > > > > {
> > > > > unsigned char txbuffer, i;
> > > > > static unsigned char flag = 1;
> > > > >
> > > > > if (!flag)
> > > > > return;
> > > > > flag = 0;
> > > > >
> > > > > if (!CANTFLG)
> > > > > return; // everything is more important than messages from the
> > > > > ECU, so just drop out if we cannot send
> > > > >
> > > > > CANTBSEL = CANTFLG; // Select free buffer to use
> > > > > txbuffer = CANTBSEL; // backup buffer
> > > > >
> > > > > CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of
> > id
> > > > > CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of
> > id;
> > > > > CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> > > > > CAN_TB0_IDR2 = 0;
> > > > > CAN_TB0_IDR3 = 0;
> > > > >
> > > > > for (i = 0; i < msg->length; i++) {
> > > > > *(&CAN_TB0_DSR0 + i) = msg->data[i];
> > > > > }
> > > > >
> > > > > CAN_TB0_DLR = msg->length; // Set length
> > > > > CAN_TB0_TBPR = 0; // priority
> > > > >
> > > > > // Send message
> > > > > CANTFLG = txbuffer;
> > > > > }
> > > > >
> > > > > However, when I send a single CAN message, MSCAN floods the
> > CAN-Bus
> > > > with
> > > > > messages (sending probably any us) and never stops. I checked on
> > the
> > > > > osci and there is an ACK on the bus so I guess everything should
> > be
> > > > > fine. Do I need to clear some buffer to make it stop sending
> > > > messages?
> > > > >
> > > > > Thanks a lot for your help
> > > > >
> > > > > Johannes
> > > > >
> > > > > --
> > > > > Johannes Schmid
> > > > > High-Octane-Motorsports
> > > > > Teamleiter Elektronik
> > > > > j...@octanes.de
> > > 40octanes.de>
> > >
> > > > > 0179 / 1674917
> > > > >
> > > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > --
> > > Johannes Schmid
> > > High-Octane-Motorsports
> > > Teamleiter Elektronik
> > > j...@octanes.de
>
> > > 0179 / 1674917
> > >
> > >
> >
> >
> >
> >
> >
> --
> Johannes Schmid
> High-Octane-Motorsports
> Teamleiter Elektronik
> j...@octanes.de
> 0179 / 1674917

Bus could be flooded due to bitrate mismatch. If only one device is sending
at a time, then the width of the shortest pulse on the bus equals to the bit
time of this sening node. Just check if it's 2us (0.5Mbps) or not.

Edward

----- Original Message -----
From: "Johannes Schmid"
To: <6...>
Sent: Wednesday, May 06, 2009 21:33
Subject: [68HC12] MSCAN problem
> Hi everybody!
>
> I have a problem using the CAN-Bus interface of the HCS12 used in the
> MicroSquirt(tm) ECU we use on our Formula race car.
>
> Following the various data sheets I came up with the following code:
>
> void CanInit(void)
> {
> /* Set up CAN communications */
> /* Enable CAN, set Init mode so can change registers */
> CANCTL1 |= 0x80;
> CANCTL0 |= 0x01;
>
> while(!(CANCTL1 & 0x01))
> ; // make sure in init mode
>
> /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> CANCTL1 = 0xC0;
> /* Set timing for .5Mbits/ sec */
> CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> (16 Tq total including sync seg (=1)) */
>
> CANIDAC &= ~0x30; /* no filters */
>
> /* clear init mode */
> CANCTL0 &= 0xFE;
> /* wait for synch to bus */
> while(!(CANCTL0 & 0x10));
>
> /* no xmit yet */
> CANTIER = 0x00;
> /* clear RX flag to ready for CAN recv interrupt */
> CANRFLG = 0xC3;
> /* set CAN rcv full interrupt bit */
> CANRIER = 0x01;
> return;
> }
>
> void CanSend(CAN_message* msg)
> {
> unsigned char txbuffer, i;
> static unsigned char flag = 1;
>
> if (!flag)
> return;
> flag = 0;
>
> if (!CANTFLG)
> return; // everything is more important than messages from the
> ECU, so just drop out if we cannot send
>
> CANTBSEL = CANTFLG; // Select free buffer to use
> txbuffer = CANTBSEL; // backup buffer
>
> CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
> CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
> CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> CAN_TB0_IDR2 = 0;
> CAN_TB0_IDR3 = 0;
>
> for (i = 0; i < msg->length; i++) {
> *(&CAN_TB0_DSR0 + i) = msg->data[i];
> }
>
> CAN_TB0_DLR = msg->length; // Set length
> CAN_TB0_TBPR = 0; // priority
>
> // Send message
> CANTFLG = txbuffer;
> }
>
> However, when I send a single CAN message, MSCAN floods the CAN-Bus with
> messages (sending probably any us) and never stops. I checked on the
> osci and there is an ACK on the bus so I guess everything should be
> fine. Do I need to clear some buffer to make it stop sending messages?
>
> Thanks a lot for your help
>
> Johannes
> --
> Johannes Schmid
> High-Octane-Motorsports
> Teamleiter Elektronik
> j...@octanes.de
> 0179 / 1674917
>
>
Hi!
> yes, it did work on hardware. Is it possible you have a hardware rec
> pin issue? That
> would explain the correct Ack on the bus and the continuous sending.
> Is
> there any
> pin routing involved in your scheme, maybe?
> S
>
Well, the schemas are available here:
http://www.microsquirt.info/us_hardware.htm

We bought the pre-build device so I hope there are no routing errors. We
also checked that CANH/CANL are correctly wired on the CAN-driver-ic.
But if you say that this code should do than we probably really have
hardware issues or the bus timing is incorrect.

Thanks for your help so far!

Johannes

Hi!

> Bus could be flooded due to bitrate mismatch. If only one device is
> sending
> at a time, then the width of the shortest pulse on the bus equals to
> the bit
> time of this sening node. Just check if it's 2us (0.5Mbps) or not.
>
OK, I will check this. Unforntunately the bus timing documentation of
the hcs12 is a bit strage but I will have a second look at it.

Thanks,
Johannes
> Edward
>
> ----- Original Message -----
> From: "Johannes Schmid"
> To: <6...>
> Sent: Wednesday, May 06, 2009 21:33
> Subject: [68HC12] MSCAN problem
>
> > Hi everybody!
> >
> > I have a problem using the CAN-Bus interface of the HCS12 used in
> the
> > MicroSquirt(tm) ECU we use on our Formula race car.
> >
> > Following the various data sheets I came up with the following code:
> >
> > void CanInit(void)
> > {
> > /* Set up CAN communications */
> > /* Enable CAN, set Init mode so can change registers */
> > CANCTL1 |= 0x80;
> > CANCTL0 |= 0x01;
> >
> > while(!(CANCTL1 & 0x01))
> > ; // make sure in init mode
> >
> > /* Set Can enable, use IPBusclk (24 MHz),clear rest */
> > CANCTL1 = 0xC0;
> > /* Set timing for .5Mbits/ sec */
> > CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
> > CANBTR1 = 0x1C; /* Set time quanta: tseg2 =2,tseg1
> > (16 Tq total including sync seg (=1)) */
> >
> > CANIDAC &= ~0x30; /* no filters */
> >
> > /* clear init mode */
> > CANCTL0 &= 0xFE;
> > /* wait for synch to bus */
> > while(!(CANCTL0 & 0x10));
> >
> > /* no xmit yet */
> > CANTIER = 0x00;
> > /* clear RX flag to ready for CAN recv interrupt */
> > CANRFLG = 0xC3;
> > /* set CAN rcv full interrupt bit */
> > CANRIER = 0x01;
> > return;
> > }
> >
> > void CanSend(CAN_message* msg)
> > {
> > unsigned char txbuffer, i;
> > static unsigned char flag = 1;
> >
> > if (!flag)
> > return;
> > flag = 0;
> >
> > if (!CANTFLG)
> > return; // everything is more important than messages from the
> > ECU, so just drop out if we cannot send
> >
> > CANTBSEL = CANTFLG; // Select free buffer to use
> > txbuffer = CANTBSEL; // backup buffer
> >
> > CAN_TB0_IDR0 = (unsigned char) msg->id >> 3; // higher 8 bits of id
> > CAN_TB0_IDR1 = (unsigned char) msg->id << 5; // lower 3 bits of id;
> > CAN_TB0_IDR1 &= ~(0x18); // Set to standard frames (IDE = 0)
> > CAN_TB0_IDR2 = 0;
> > CAN_TB0_IDR3 = 0;
> >
> > for (i = 0; i < msg->length; i++) {
> > *(&CAN_TB0_DSR0 + i) = msg->data[i];
> > }
> >
> > CAN_TB0_DLR = msg->length; // Set length
> > CAN_TB0_TBPR = 0; // priority
> >
> > // Send message
> > CANTFLG = txbuffer;
> > }
> >
> > However, when I send a single CAN message, MSCAN floods the CAN-Bus
> with
> > messages (sending probably any us) and never stops. I checked on the
> > osci and there is an ACK on the bus so I guess everything should be
> > fine. Do I need to clear some buffer to make it stop sending
> messages?
> >
> > Thanks a lot for your help
> >
> > Johannes
> >
> >
> > --
> > Johannes Schmid
> > High-Octane-Motorsports
> > Teamleiter Elektronik
> > j...@octanes.de
> > 0179 / 1674917
> >
> >
> >
> >
> >
> >
Hi!

> Bus could be flooded due to bitrate mismatch. If only one device is sending
> at a time, then the width of the shortest pulse on the bus equals to the bit
> time of this sening node. Just check if it's 2us (0.5Mbps) or not.
>

OK, I checked the clock speed things again and it's absolutely correct. Here is the code:

/* Set Can enable, use IPBusclk (24 MHz),clear rest */
CANCTL1 = 0xC0; // CANE = 1, CLKRSRC = 1 (Bus Clock)

/* Set timing for .5Mbits/ sec */
CANBTR0 = 0xC2; /* SJW=4,BR Prescaler= 3(24MHz CAN clk) */
CANBTR1 = 0x58; /* Tseg2 = 6, Tseg1 = 9 (Tseg1 + Tseg1 + Sync(=1) = 16 => 8 Mhz / 16 = 0.5 Mhz */

I adjusted the Tseg timings a bit because the manual says that my original timings weren't standard compliant but I didn't make a difference. The bit width on the scope was also correct.

Johannes


The 2024 Embedded Online Conference