EmbeddedRelated.com
Forums

MSCAN Identifier of a received message

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

this leads to side effects and should be considered wrong:

> CAN0RFLG |=1; // clear rec flag

Above line clears not only rec flag, but also WUPIF, CSCIF and OVRIF!
To clear only RXF, you should either

CAN0RFLG =1; // clear rec flag

or

CAN0RFLG &=1; // clear rec flag

Regards
Edward
----- Original Message -----
From: "Steve Letkeman"
To: <6...>
Sent: Saturday, November 15, 2008 1:30 AM
Subject: Re: [68HC12] Re: Re: MSCAN Identifier of a received message
> 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
>>>
>>>
>>>
>>>
>>> No virus found in this incoming message.
>>> Checked by AVG.
>>> Version: 7.5.549 / Virus Database: 270.9.2/1783 - Release Date:
>>> 12/11/2008 10:01 AM
>>
Hi Edward, to tell you the truth, I have always found some of the
methods for
clearing flags both confusing and inconsistent so I appreciate the
correction.
Can you explain why this is the case? I suspect that it has to do with
the fact
that an OR statement needs to read the register before writing but
looking at
the documentation doesn't make that clear to me.
Steve

Edward Karpicz wrote:
>
> Steve,
>
> this leads to side effects and should be considered wrong:
>
> > CAN0RFLG |=1; // clear rec flag
>
> Above line clears not only rec flag, but also WUPIF, CSCIF and OVRIF!
>
> To clear only RXF, you should either
>
> CAN0RFLG =1; // clear rec flag
>
> or
>
> CAN0RFLG &=1; // clear rec flag
>
> Regards
> Edward
>
> ----- Original Message -----
> From: "Steve Letkeman" > >
> To: <6...

























































































































































&















&IDE

















&

&






























&





















































&




















Hi Steve

CANRFLG flags, timer flags, key wake up flags etc, they all are clearable
writing '1' to them.
CANRFLG = 1; // this is simple and OK. You write flags register with only
one bit0 set, and you are sure only bit0-flag will be cleared.

CANRFLG |= 1; // Problem with this is that not only bit0 will be cleared,
but also all flags that are set. For example if RXF(bit0) and WUPIF(bit7)
are set, then both RXF and WUPIF will be cleared.
(1<<0)|(1<<7) | 1 = (1<<0)|(1<<7), and ones will be written to both
bits.
CANRFLG &= 1; // this unusual construct is OK with flags. (Please note it's
not X &= ~1, but X &= 1)
(1<<0)|(1<<7) & 1 = (1<<0), and '1' goes to bit0 only.
Are you using CW? Then don't use their bitfields to clear flags.
CAN0RFLG_RXF = 1 also clears more than just RXF. Why? Because all bits, that
don't belong to field you are accessing, all those "bits from outside"
should be and are preserved. And what happens if you keep (rewrite) WUPIF,
OVRIF etc in their current state? In case WUPIF = 0, WUPIF doesn't change
after CAN0RFLG_RXF = 1; because '0' is written back to WUPIF. But in case
WUPIF=1, CAN0RFLG_RXF=1 writes back '1' to WUPIF and resets it!
I don't know how to explain it better.
Edward

----- Original Message -----
From: "Steve Letkeman"
To: <6...>
Sent: Monday, November 17, 2008 7:21 PM
Subject: Re: [68HC12] Re: Re: MSCAN Identifier of a received message
> Hi Edward, to tell you the truth, I have always found some of the
> methods for
> clearing flags both confusing and inconsistent so I appreciate the
> correction.
> Can you explain why this is the case? I suspect that it has to do with
> the fact
> that an OR statement needs to read the register before writing but
> looking at
> the documentation doesn't make that clear to me.
> Steve
>
> Edward Karpicz wrote:
>>
>> Steve,
>>
>> this leads to side effects and should be considered wrong:
>>
>> > CAN0RFLG |=1; // clear rec flag
>>
>> Above line clears not only rec flag, but also WUPIF, CSCIF and OVRIF!
>>
>> To clear only RXF, you should either
>>
>> CAN0RFLG =1; // clear rec flag
>>
>> or
>>
>> CAN0RFLG &=1; // clear rec flag
>>
>> Regards
>> Edward
>>
>> ----- Original Message -----
>> From: "Steve Letkeman" >> >
>> To: <6...

























































































































































&















&IDE

















&

&






























&





















































&




















thanks for the explanation Edward. The reality is sometimes code is
written and copied and if there isn't an (apparent) issue it isn't
looked at again. Thanks for pointing my error out on such a public
forum...(haha, just kidding) I am always open to correction and
learning something new
Steve
Edward Karpicz wrote:
>
> Hi Steve
>
> CANRFLG flags, timer flags, key wake up flags etc, they all are clearable
> writing '1' to them.
>
> CANRFLG = 1; // this is simple and OK. You write flags register with only
> one bit0 set, and you are sure only bit0-flag will be cleared.
>
> CANRFLG |= 1; // Problem with this is that not only bit0 will be cleared,
> but also all flags that are set. For example if RXF(bit0) and WUPIF(bit7)
> are set, then both RXF and WUPIF will be cleared.
> (1<<0)|(1<<7) | 1 = (1<<0)|(1<<7), and ones will be written to both
> bits.
>
> CANRFLG &= 1; // this unusual construct is OK with flags. (Please note
> it's
> not X &= ~1, but X &= 1)
> (1<<0)|(1<<7) & 1 = (1<<0), and '1' goes to bit0 only.
>
> Are you using CW? Then don't use their bitfields to clear flags.
> CAN0RFLG_RXF = 1 also clears more than just RXF. Why? Because all
> bits, that
> don't belong to field you are accessing, all those "bits from outside"
> should be and are preserved. And what happens if you keep (rewrite)
> WUPIF,
> OVRIF etc in their current state? In case WUPIF = 0, WUPIF doesn't change
> after CAN0RFLG_RXF = 1; because '0' is written back to WUPIF. But in case
> WUPIF=1, CAN0RFLG_RXF=1 writes back '1' to WUPIF and resets it!
>
> I don't know how to explain it better.
>
> Edward
>
Hello,

thank you very much. It works fine know with 29 bit identifier.

Thank you.

Best regards.

Hello,
I still have a problem.
I read the 29 bit ID. I store the data in two variables to display the Identifier on a LCD. I want to disply the ID binary. But it does not work completely yet.
I use the ID 1FFFFFFF so the 29 bit shoud be 1 I think, but that does not work.
The display shows 00000011111100 (data11) and 000000001111111 (data22).

Could you have a look at the code. Does anybody know where the mistake is?

Best Regards
*************************
unsigned char data1[15], data2[16], data11, data22;

for(ii = 0; ii <= 3; ii++)
RXData[ii] = CAN0RXFG[ii];

data11= ( RXData[0] << 8) | (RXData[1] & 0xE0) | ((RXData[1] & 0x07) << 2);
data22= ( RXData[2] << 8) | (RXData[3] & 0xFE) >> 1;

data1[14]='\0';
for(i; i>=0; i--) {
data1[i]=(data11 % 2) + '0';
data11 /= 2;
}

data2[15]='\0';
for(i; i>=0; i--) {
data2[i]=(data22 % 2) + '0';
data22 /= 2;
}
*************************
Hello,

I solved the problem.

unsigned char RXData[8];
unsigned char ii;
unsigned char data1[17], data2[17];
unsigned int data11,data22;
int i;

for(ii = 0; ii <= 3; ii++)
RXData[ii] = CAN0RXFG[ii];

data11 = ( (unsigned int)RXData[0] << 8) | (RXData[1] & 0xE0) | ((RXData[1] & 0x07) << 2);
data22 = ( (unsigned int)RXData[2] << 8) | (RXData[3] & 0xFE) ;

for(i; i>=0; i--) {
data1[i]=(data11 % 2) + '0';
data11 /= 2;
}
data1[14]='\0';

for(i; i>=0; i--) {
data2[i]=(data22 % 2) + '0';
data22 /= 2;
}
data2[15]='\0';