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
NACAN=CAN0TFLG; // 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-00-01
if (NumBytes>8) NumBytes=8;
for (C=0;C<NumBytes;C++)
*(CAN0TXFG+4+C)=*BufPntr++; // store the data
*(CAN0TXFG+0x0C)=NumBytes; // set number of
bytes to send
NACAN=CAN0TBSEL;
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=13
> > > (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
> > >
johannes.schmid@... <mailto:johannes.schmid%40octanes.de>
> <mailto:johannes.schmid%40octanes.de>
> > > 0179 / 1674917
> > >
> > >
> >
> >
> >
> >
> >
> --
> Johannes Schmid
> High-Octane-Motorsports
> Teamleiter Elektronik
>
johannes.schmid@... <mailto:johannes.schmid%40octanes.de>
> 0179 / 1674917
>
>