EmbeddedRelated.com
Forums

MSCAN Identifier of a received message

Started by foru...@gmx.net November 4, 2008
Hello,

I have a communication between a HCS12 and a Computer. I receive CAN messages with the HCS12. That works fine so far, sending messages, too.

Is it possible to get the identifier of an received CAN message? Is it stored in a register or something like that so that I can read out the identifier of the last received CAN message?

Best Regards
Folgli

yes you CAN! The incoming CAN ID is stored in the first 4 bytes of the
receive
buffer but you'll have to rearrange the bits a little to get it into a
nice 11 or 29 bit
format as they mix the SSR, IDE and RTR bits in there as well.

Steve

--
Steven D. Letkeman BSc.
Zanthic Technologies Inc.
www.zanthic.com Embedded micro-controllers and CAN interfaces
www.brightan.com HC12 I/O boards with CAN firmware downloading built in

>
> f...@gmx.net wrote:
>>
>> Hello,
>>
>> I have a communication between a HCS12 and a Computer. I receive CAN
>> messages with the HCS12. That works fine so far, sending messages, too.
>>
>> Is it possible to get the identifier of an received CAN message? Is
>> it stored in a register or something like that so that I can read out
>> the identifier of the last received CAN message?
>>
>> Best Regards
>> Folgli
>>
>>
>> 8:26 AM
>>
>
Hello,

I tried to read out the Identifier but it does not really work.
Perhaps someone could tell me what is wrong.

Best regards

Here is my ISR:

@interrupt void CANReceive(void)
{
unsigned char RXData[8];
unsigned char ii, NumBytes;
unsigned char data1, data2;
char ausg_str[]="0000";

for(ii = 0; ii < NumBytes; ii++)
RXData[ii] = CAN0RXFG[ii];
ThirdLine();
SpaceOut(3);
for(ii = 0; ii < 4; ii++)
{
data1= (RXData[ii]/16);
data2= (RXData[ii]%16);
if(data1 <= 9)
data1= data1+48;
else
data1= data1 - 10 + 65;
if(data2 <= 9)
data2= data2 + 48;
else
data2= data2 - 10 + 65;
LCDOutc(data1);
LCDOutc(data2);
}

CAN0RFLG |= 0x01; // Clear Receive Interrupt
}/* void CANReceive(void) */

I'm not sure what exactly you're trying to do in your code or what your
defines look like, but just as an example, if you had
#define CAN0ID(b) *(volatile unsigned char *)(0x00000160+b)
and ID is a 4 byte integer, then
ID0ID(0)<<21;
ID|=(CAN0ID(1) & 0xE0)<<13; //work around SRR and IDE
ID|=(CAN0ID(1) & 0x07)<<15;
ID|0ID(2)<<7;
ID|=(CAN0ID(3) & 0xFE)>>1; // skip RTR

this assumes a 29 bit ID that is right shifted into a 32 bit variable
oh ya, one thing I noticed is that in your code you are not initializing
NumBytes

Steve

f...@gmx.net wrote:
>
> Hello,
>
> I tried to read out the Identifier but it does not really work.
> Perhaps someone could tell me what is wrong.
>
> Best regards
>
> Here is my ISR:
>
> @interrupt void CANReceive(void)
> {
> unsigned char RXData[8];
> unsigned char ii, NumBytes;
> unsigned char data1, data2;
> char ausg_str[]="0000";
>
> for(ii = 0; ii < NumBytes; ii++)
> RXData[ii] = CAN0RXFG[ii];
> ThirdLine();
> SpaceOut(3);
> for(ii = 0; ii < 4; ii++)
> {
> data1= (RXData[ii]/16);
> data2= (RXData[ii]%16);
> if(data1 <= 9)
> data1= data1+48;
> else
> data1= data1 - 10 + 65;
> if(data2 <= 9)
> data2= data2 + 48;
> else
> data2= data2 - 10 + 65;
> LCDOutc(data1);
> LCDOutc(data2);
> }
>
> CAN0RFLG |= 0x01; // Clear Receive Interrupt
> }/* void CANReceive(void) */
>
>
> 8:26 AM
>
Hello,

I try to read out the ID and show it on a LCD. At the moment I am using 11 bit ID. The incoming CAN ID is stored in the first 4 bytes of the
receive buffer. So I want to red out the first 4 bytes.

for(ii = 0; ii < 3; ii++)
RXData[ii] = CAN0RXFG[ii];
Byte 0 up to 3.

A 29 bit ID:

ID is a 4 byte integer, then
ID=RXData[0]<<21;
ID|=(RXData[1] & 0xE0)<<13; //work around SRR and IDE
ID|=(RXData[1] & 0x07)<<15;
ID|=RXData[2]<<7;
ID|=(RXData[3] & 0xFE)>>1; // skip RTR

Is this right?

Could you explain in detail in what order the CAN ID, SSR, IDE and RTR are stored in the buffer or give an example because I do not understand the operations....& 0xE0)<<13.....& 0x07)<<15.
'<<' is clear but why & 0xE0 and so on and <<21?

Thank you very much....

Best regards

ultimately you are going to have to dig into the mscan manual and
become familiar with all of the registers. Take a look in the manual
for the figure labeled "Receive / Transmit Message Buffer Extended
Identifier"

Bit 7 6 5 4 3 2 1 Bit 0
IDR0 ID28 ID27 ID26 ID25 ID24 ID23 ID22 ID21
IDR1 ID20 ID19 ID18 SRR IDE ID17 ID16 ID15
IDR2 ID14 ID13 ID12 ID11 ID10 ID9 ID8 ID7
IDR3 ID6 ID5 ID4 ID3 ID2 ID1 ID0 RTR

The & 0xE0 is to get rid of the SRR bit and the & 0x07 is to get rid of
the IDE bit. The <<21 is bit shifting because ID28 is in the 8th bit
position
of IDR0 and it needs to be in the 29th bit position of the final ID value.
You may not want to store the ID as a long if you are going to display
its value on an LCD, maybe you want to keep it as separate bytes, that
is up to you.
If you are interested in some HC12 boards that have all of the CAN
interfacing done for you and you can download your firmware right across
the CAN bus, check out my I/O boards at www.brightan.com

Steve
f...@yahoo.com wrote:
>
> Hello,
>
> I try to read out the ID and show it on a LCD. At the moment I am
> using 11 bit ID. The incoming CAN ID is stored in the first 4 bytes of the
> receive buffer. So I want to red out the first 4 bytes.
>
> for(ii = 0; ii < 3; ii++)
> RXData[ii] = CAN0RXFG[ii];
> Byte 0 up to 3.
>
> A 29 bit ID:
>
> ID is a 4 byte integer, then
> ID=RXData[0]<<21;
> ID|=(RXData[1] & 0xE0)<<13; //work around SRR and IDE
> ID|=(RXData[1] & 0x07)<<15;
> ID|=RXData[2]<<7;
> ID|=(RXData[3] & 0xFE)>>1; // skip RTR
>
> Is this right?
>
> Could you explain in detail in what order the CAN ID, SSR, IDE and RTR
> are stored in the buffer or give an example because I do not
> understand the operations....& 0xE0)<<13.....& 0x07)<<15.
> '<<' is clear but why & 0xE0 and so on and <<21?
>
> Thank you very much....
>
> Best regards
>
>
> 7:17 AM
>
> f...@yahoo.com wrote:
> >
> > Hello,
> >
> > I try to read out the ID and show it on a LCD. At the moment I am
> > using 11 bit ID. The incoming CAN ID is stored in the first 4 bytes of the
> > receive buffer. So I want to red out the first 4 bytes.
> >
> > for(ii = 0; ii < 3; ii++)
> > RXData[ii] = CAN0RXFG[ii];
> > Byte 0 up to 3.
> >

If you want to read 4 bytes, that should be ii <= 3 (or ii < 4 if you prefere
that). Otherwise you will only read 3 bytes and RXData[3] will be uninitialized

/Ruben
=============================Ruben Jsson
AB Liros Electronic
Box 9124, 200 39 Malm Sweden
TEL INT +46 40142078
FAX INT +46 40947388
r...@pp.sbbs.se
=============================
Hello,

thank you very much. I think that I understand now. I tried to write some programms to test the settings and so on. It works fine now with 11bit ID. I will try now to read out an extended identifier but i think that it is not difficult if you understand how it works.

Thank you very much.

Best Regards

Hello,

I tried to read out a 29 bit identifier. But it seems that I have problems to initialize the can module becausse I can not receive any CAN message. I get no error while sending but I do not get an interrupt at the hcs12.

Could someone tell me whether my CAN initialization is wrong? I tried to read the manual and so on but I do not find what could be wrong.

Best Regards
void CANInit(unsigned int BaudRate)
{
CAN0CTL0 = 0x01; // Enter Initialization Mode
// INITAK = 1 Initialization Mode Active

while (!(CAN0CTL1 & 0x01)); // Wait for Initialization Mode
// acknowledge (INITRQ bit = 1)
// INITAK - Site 20

CAN0CTL1 = 0x80; // CANE = 1 THE MSCAN module is enabled
// CLKSRC = 0 THE MSCAN clock source is
// the Oscillator Clock
// LOOPB = 0 Loop Back Self Test disabled
switch(BaudRate)
{
case 20000: // Baud rate 20kBit/s
CAN0BTR0 = 0x31; // Prescaler 50
CAN0BTR1 = 0x76; // 1+TimeSegment1+Timesegment2 = 1+8+7 = 16
// For a CAN Baud of 20kbps at 16MHz
// crystal
break;

case 50000: // Baud rate 50kBit/s
CAN0BTR0 = 0x28; // Prescaler 40
CAN0BTR1 = 0x32; // 1+TimeSegment1+Timesegment2 = 1+3+4 = 8
// For a CAN Baud of 50kbps at 16MHz
// crystal
break;
.......
}/* switch */

CAN0IDMR0 = 0xFF;
CAN0IDAR0 = 0x00;

CAN0IDMR1 = 0xFF;
CAN0IDAR1 = 0x00;

CAN0IDMR2 = 0xFF;
CAN0IDAR2 = 0x00;

CAN0IDMR3 = 0xFF;
CAN0IDAR3 = 0x00;

CAN0IDMR4 = 0xFF;
CAN0IDAR4 = 0x00;

CAN0IDMR5 = 0xFF;
CAN0IDAR5 = 0x00;

CAN0IDMR6 = 0xFF;
CAN0IDAR6 = 0x00;

CAN0IDMR7 = 0xFF;
CAN0IDAR7 = 0x00;

CAN0IDAC |= 0x00; // Set flters to 2 32 bit acceptanc filters
// IDAM0 = 0, IDAM1 = 0

CAN0CTL0 = 0x00; // Exit Initialization Mode Request
while((CAN0CTL1 & 0x01) != 0); // Wait for Normal Mode

CAN0CTL1 |= 0x80; // CANE = 1 THE MSCAN module is enabled

CAN0RIER |= 0x01; // Enable receive interrupt
// RXFIE = 1 receiver Full Interrupt Enable
CAN0RFLG |= 0x01; // Clear Receive Interrupt
Here is a simple example of setting the CAN controller up. It is
getting a little
old but still might help you out.
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

}

> f...@yahoo.com wrote:
>>
>> Hello,
>>
>> I tried to read out a 29 bit identifier. But it seems that I have
>> problems to initialize the can module becausse I can not receive any
>> CAN message. I get no error while sending but I do not get an
>> interrupt at the hcs12.
>>
>> Could someone tell me whether my CAN initialization is wrong? I tried
>> to read the manual and so on but I do not find what could be wrong.
>>
>> Best Regards
>>
>> void CANInit(unsigned int BaudRate)
>> {
>> CAN0CTL0 = 0x01; // Enter Initialization Mode
>> // INITAK = 1 Initialization Mode Active
>>
>> while (!(CAN0CTL1 & 0x01)); // Wait for Initialization Mode
>> // acknowledge (INITRQ bit = 1)
>> // INITAK - Site 20
>>
>> CAN0CTL1 = 0x80; // CANE = 1 THE MSCAN module is enabled
>> // CLKSRC = 0 THE MSCAN clock source is
>> // the Oscillator Clock
>> // LOOPB = 0 Loop Back Self Test disabled
>> switch(BaudRate)
>> {
>> case 20000: // Baud rate 20kBit/s
>> CAN0BTR0 = 0x31; // Prescaler 50
>> CAN0BTR1 = 0x76; // 1+TimeSegment1+Timesegment2 = 1+8+7 = 16
>> // For a CAN Baud of 20kbps at 16MHz
>> // crystal
>> break;
>>
>> case 50000: // Baud rate 50kBit/s
>> CAN0BTR0 = 0x28; // Prescaler 40
>> CAN0BTR1 = 0x32; // 1+TimeSegment1+Timesegment2 = 1+3+4 = 8
>> // For a CAN Baud of 50kbps at 16MHz
>> // crystal
>> break;
>> .......
>> }/* switch */
>>
>> CAN0IDMR0 = 0xFF;
>> CAN0IDAR0 = 0x00;
>>
>> CAN0IDMR1 = 0xFF;
>> CAN0IDAR1 = 0x00;
>>
>> CAN0IDMR2 = 0xFF;
>> CAN0IDAR2 = 0x00;
>>
>> CAN0IDMR3 = 0xFF;
>> CAN0IDAR3 = 0x00;
>>
>> CAN0IDMR4 = 0xFF;
>> CAN0IDAR4 = 0x00;
>>
>> CAN0IDMR5 = 0xFF;
>> CAN0IDAR5 = 0x00;
>>
>> CAN0IDMR6 = 0xFF;
>> CAN0IDAR6 = 0x00;
>>
>> CAN0IDMR7 = 0xFF;
>> CAN0IDAR7 = 0x00;
>>
>> CAN0IDAC |= 0x00; // Set flters to 2 32 bit acceptanc filters
>> // IDAM0 = 0, IDAM1 = 0
>>
>> CAN0CTL0 = 0x00; // Exit Initialization Mode Request
>> while((CAN0CTL1 & 0x01) != 0); // Wait for Normal Mode
>>
>> CAN0CTL1 |= 0x80; // CANE = 1 THE MSCAN module is enabled
>>
>> CAN0RIER |= 0x01; // Enable receive interrupt
>> // RXFIE = 1 receiver Full Interrupt Enable
>> CAN0RFLG |= 0x01; // Clear Receive Interrupt
>>
>>
>> 10:01 AM
>>
>