Reply by Steve Letkeman February 16, 20042004-02-16
A number of people have asked me for some sample code for the
newest version of msCAN, here it is... // 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<NumBytes;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

}

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