At the manual of xc164cm it is simply noted that there is a CRC calculation coming from node A and node B with no more informations.
You have not access to the way of this CRC calculation.
Here I am using the C code of CRC16-CCITT as in article no 39 with the following functions:
unsigned int crc16(unsigned long int message ) {
unsigned int j=0;
unsigned long int d=0x1021 ;
d=d<<16; // we don't want the 16 zeros in front
crc=message;
for (j=0;j<=15;j++)
{
test=crc>>16; // to test the #31 bit of crc. see the #define above.
//A warning about value truncated here but ignore it
if (CRC31)
{
crc=crc<<1;
crc=crc^d ;
}
else crc= crc<<1;
}
crc=crc>>16;
return crc;
}
===========================
void crc16_table (void){
unsigned int t ;
unsigned int long i;
for (i=0;i<256;i++)
{
t=crc16(i<<16);
t1[(unsigned char)i]=(unsigned char)(t>>8);
t2[(unsigned char)i]=(unsigned char) t;
}
}
====================
unsigned int crc16_table_calculator (unsigned char *m, unsigned int k) {
unsigned char a=0;
unsigned int v=0; // v the crc
unsigned int j;
for(j=0; j<=k;j++) {
v=( (unsigned int ) (t1[a]^(unsigned char) v ) ) <<8 ^( t2[a] ^ *(m+j) );
a= (unsigned char) (v>>8) ;
}
return v;
}
The complete project is
here.
Observe the "VIEWS" word file enclosed.
To be clear the above procedure of writing to the FIFO buffer I insert a
1 msec time delay before the next CANBUS message object transmition, using the following function for T5 timer:
void delay_T5 (unsigned int t)
{
GPT12E_T5IC_IR =0; // Reset IR bit
GPT2_vLoadTmr_GPT2_TIMER_5(t);
GPT2_vStartTmr_GPT2_TIMER_5(); // GPT2_vStartTmr_GPT2_TIMER_5()
while (GPT12E_T5IC_IR!=1 ); //wait for timer T5 to overflow
GPT2_vStopTmr_GPT2_TIMER_5();
}
I changed the data of mo2 amd mo4. Data of mo3 is the crc16 of mo2,
it is 0x45BF (in memory 0xBF45 that is the printable characters ΩΕ)
Seting breakpoints at the delay calls observe the changes at memory window. Watch the enclosed "VIEWS" word file.
The project is here.
canbus transmit and receive interrupts <25/June/2016>
Today I am presenting CANBUS transmit and receive interrupts.
I am using:
mo0 and mo1 configured as receive and assigned to node A.
mo2 and mo3 configured as transmit objects and assigned to node B , mo3 includes in its data space and the crc16 of mo2 that is 0xBF45.
All interrupts are serviced by peripheral evevnt controller (PEC) FOR A FAST service. PEC is the analogous of direct memory access,
The Main transmit interrupt is that of nod B and the nested interrupts included are those of transmit objects mo2 and mo3. This interrupt is serviced by PEC channel1. When something is transmitted by nod B a led is blinking.
The main receive interrupt is that of node A and the nested interrupts included are those of receive objects mo0 and mo1. This interrupt is serviced by PEC channel0. When something is received by node A a led is blinking.
To see what a message object IS READY TO DO (transmit or rceive) the interrupt pending bitfield INTPND of the control register of a message object ( 2 BITS LONG) is checked.
The transmit interrupt C code for nod B and mo2 and mo3 is:
void CAN_viSRN1(void) interrupt CAN_SRN1INT
{
uword uwStatusB;
// USER CODE BEGIN (SRN1,2)
// USER CODE END
while((( ((ulong)CAN_TXIPNDH << 16) + CAN_TXIPNDL) & 0x0000000C) || (CAN_BSR & 0x0018))
{
// status change interrupt of node B
uwStatusB = CAN_BSR;
if (uwStatusB & 0x0008) // if TXOK
{
// Indicates that a message has been transmitted successfully
// (error free and acknowledged by at least one other node).
uwStatusB &= 0xfff7;
CAN_BSR = uwStatusB; // reset TXOK
// USER CODE BEGIN (SRN1_NODEB,3)
P1L_P1= ~P1L_P1 ; // blink led
// USER CODE END
}
if (uwStatusB & 0x0010) // if RXOK
{
// Indicates that a message has been received successfully.
uwStatusB &= 0xffef;
CAN_BSR = uwStatusB; // reset RXOK
// USER CODE BEGIN (SRN1_NODEB,4)
// USER CODE END
}
// USER CODE BEGIN (SRN1_NODEB,13)
// USER CODE END
// message object 2 interrupt
if((CAN_HWOBJ[2].uwMSGCTR & 0x0003) == 0x0002) // if INTPND
{
if(CAN_TXIPNDL & CAN_TXIPNDL_TXIPND2) // message object 2 transmit interrupt
{
// The transmission of the last message object
// was successful.
// USER CODE BEGIN (SRN1_OBJ2,4)
// USER CODE END
CAN_HWOBJ[2].uwMSGCTR = 0xfdff; // reset NEWDAT
} // End of TXIPND2
CAN_HWOBJ[2].uwMSGCTR = 0xfffd; // reset INTPND
// USER CODE BEGIN (SRN1_OBJ2,6)
// USER CODE END
}
// message object 3 interrupt
if((CAN_HWOBJ[3].uwMSGCTR & 0x0003) == 0x0002) // if INTPND
{
if(CAN_TXIPNDL & CAN_TXIPNDL_TXIPND3) // message object 3 transmit interrupt
{
// The transmission of the last message object
// was successful.
// USER CODE BEGIN (SRN1_OBJ3,4)
// USER CODE END
CAN_HWOBJ[3].uwMSGCTR = 0xfdff; // reset NEWDAT
} // End of TXIPND3
CAN_HWOBJ[3].uwMSGCTR = 0xfffd; // reset INTPND
// USER CODE BEGIN (SRN1_OBJ3,6)
// USER CODE END
}
// USER CODE BEGIN (SRN1,3)
// USER CODE END
} // End of while()
// USER CODE BEGIN (SRN1,7)
// USER CODE END
} // End of function CAN_viSRN1
// USER CODE BEGIN (CAN_General,10)
// USER CODE END
The receive interrupt C code for node A and mo0 and mo1 is :
void CAN_viSRN0(void) interrupt CAN_SRN0INT
{
uword uwStatusA;
// USER CODE BEGIN (SRN0,2)
// USER CODE END
while((( ((ulong)CAN_RXIPNDH << 16) + CAN_RXIPNDL) & 0x00000003) || (CAN_ASR & 0x0018))
{
// status change interrupt of node A
uwStatusA = CAN_ASR;
if (uwStatusA & 0x0008) // if TXOK
{
// Indicates that a message has been transmitted successfully
// (error free and acknowledged by at least one other node).
uwStatusA &= 0xfff7;
CAN_ASR = uwStatusA; // reset TXOK
// USER CODE BEGIN (SRN0_NODEA,3)
// USER CODE END
}
if (uwStatusA & 0x0010) // if RXOK
{
// Indicates that a message has been received successfully.
uwStatusA &= 0xffef;
CAN_ASR = uwStatusA; // reset RXOK
// USER CODE BEGIN (SRN0_NODEA,4)
P1L_P0= ~P1L_P0 ; // blink led
// USER CODE END
}
// USER CODE BEGIN (SRN0_NODEA,13)
// USER CODE END
// message object 0 interrupt
if((CAN_HWOBJ[0].uwMSGCTR & 0x0003) == 0x0002) // if INTPND
{
if(CAN_RXIPNDL & CAN_RXIPNDL_RXIPND0) // message object 0 receive interrupt
{
if((CAN_HWOBJ[0].uwMSGCTR & 0x0300) == 0x0200) // if NEWDAT is set
{
if ((CAN_HWOBJ[0].uwMSGCTR & 0x0c00) == 0x0800) // if MSGLST is set
{
// Indicates that the CAN controller has stored a new
// message into this object, while NEWDAT was still set,
// ie. the previously stored message is lost.
CAN_HWOBJ[0].uwMSGCTR = 0xf7ff; // reset MSGLST
// USER CODE BEGIN (SRN0_OBJ0,1)
// USER CODE END
}
else
{
// The CAN controller has stored a new message
// into this object.
// USER CODE BEGIN (SRN0_OBJ0,2)
// USER CODE END
}
CAN_HWOBJ[0].uwMSGCTR = 0xfdff; // reset NEWDAT
}
} // End of RXIPND0
CAN_HWOBJ[0].uwMSGCTR = 0xfffd; // reset INTPND
// USER CODE BEGIN (SRN0_OBJ0,6)
// USER CODE END
}
// message object 1 interrupt
if((CAN_HWOBJ[1].uwMSGCTR & 0x0003) == 0x0002) // if INTPND
{
if(CAN_RXIPNDL & CAN_RXIPNDL_RXIPND1) // message object 1 receive interrupt
{
if((CAN_HWOBJ[1].uwMSGCTR & 0x0300) == 0x0200) // if NEWDAT is set
{
if ((CAN_HWOBJ[1].uwMSGCTR & 0x0c00) == 0x0800) // if MSGLST is set
{
// Indicates that the CAN controller has stored a new
// message into this object, while NEWDAT was still set,
// ie. the previously stored message is lost.
CAN_HWOBJ[1].uwMSGCTR = 0xf7ff; // reset MSGLST
// USER CODE BEGIN (SRN0_OBJ1,1)
// USER CODE END
}
else
{
// The CAN controller has stored a new message
// into this object.
// USER CODE BEGIN (SRN0_OBJ1,2)
// USER CODE END
}
CAN_HWOBJ[1].uwMSGCTR = 0xfdff; // reset NEWDAT
}
} // End of RXIPND1
CAN_HWOBJ[1].uwMSGCTR = 0xfffd; // reset INTPND
// USER CODE BEGIN (SRN0_OBJ1,6)
// USER CODE END
}
// USER CODE BEGIN (SRN0,3)
// USER CODE END
} // End of while()
// USER CODE BEGIN (SRN0,7)
// USER CODE END
} // End of function CAN_viSRN0
The complete project is