View previous topic :: View next topic |
Author |
Message |
guy
Joined: 21 Oct 2005 Posts: 297
|
CRC module |
Posted: Wed Sep 10, 2014 4:23 am |
|
|
I'm struggling all morning with the CRC commands of the PIC24. The hardware module plus CCS commands make it seem like child play but it's never as easy as it seems, isn't it?
I am trying to implement the following CRC scheme:
CRC16-CCITT, poly=0x1021 init=0xFFFF (x16 + x12 + x5 + 1)
To test, I get the data and result from online calculators such as http://www.lammertbies.nl/comm/info/crc-calculation.html
Let's try just the character 'Z' (0x5A). The calculator shows a result of 0x1A4F.
Code: |
//PIC24FJ64GA308
//compiler 5.026
int16 rslt;
setup_crc(16,12,5); // CRC16-CCITT, poly=0x1021 init=0xFFFF (x16 + x12 + x5 + 1)
crc_init(0xFFFF);
rslt=crc_calc8('Z');
|
The result I get is 0xE1AA
I've been fiddling with this all morning and I think it's better as a random number generator |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Sep 10, 2014 4:59 am |
|
|
I don't think you are handling the width right.
If you look at the crc_calc description, it says the input width defaults to the output width. You want to calculate a 16bit CRC, from an 8bit value, so I'd expect to have to use:
rslt=crc_calc16('Z',8);
May well be wrong, but worth a try. Haven't got anything running a PIC24 handy at the moment to have a play!....
It'd help if the example existed.... |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 10, 2014 5:07 am |
|
|
Hi Ttelmah!
crc_calc16('Z') returns 0x1D55 . My guess was that calc8/16/32 defines the input data size.
The length parameter talks about processing buffers. I found that
Code: | for(i=0;i<10;i++) {
rslt=crc_calc8(buf[i]);
} |
and
Code: | rslt=crc_calc8(buf,10); |
are equivalent. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Sep 10, 2014 9:03 am |
|
|
The calcx functions, specify _both_ the input size and the output size.
So for calc16, it generates a 16bit CRC from 16bit data. You want a 16bit CRC from 8bit data, so should have to use the calc16 as I show. Or as:
calc16((int16)'Z')
They specifically say the width value is in bits, so it should be 8 if used.
However your loop example, throws doubt upon everything....
I suggest you ask CCS to post an example. They refer to an example, but it doesn't exist, which is silly....
There is also the option CRC_LITTLE_ENDIAN, which will change the order of the result.
The other thing to do, would be to look at the generated assembler, to see if you can work out how they are using the hardware module. |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 10, 2014 9:28 am |
|
|
Quote: | The other thing to do. would be to look at the generated assembler, to see if you can work out how they are using the hardware module. |
I'd rather commit suicide than go into non-working assembler code that someone else wrote for CRC... LOL!!! But thanks.
I found this non-efficient un-cool code (22.5us per byte on 32MHz PIC24) which is 'good enough' and tested. I'd still rather use a more elegant HW solution.
It is based on http://stackoverflow.com/questions/7961964/android-crc-ccitt
Enjoy...
Code: |
//CRC16-CCITT, poly=0x1021 init=0xFFFF (x16 + x12 + x5 + 1)
// based on http://stackoverflow.com/questions/7961964/android-crc-ccitt
int16 crc;
void doCRC(byte ch) {
short bt,c15;
byte ii;
for (ii = 0; ii < 8; ii++) {
bt=bit_test(ch,7-ii);
//bt = ((b >> (7-ii) & 1) == 1);
c15=bit_test(crc,15);
//c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15^bt) crc ^= 0x1021;
}
}
///////////////////////////////////////
void main() {
byte i,ch;
crc=0xFFFF;
for(i=0;i<10;i++) {
ch=getc();
doCRC(ch);
}
// crc contains 16-bit result.
} |
Last edited by guy on Thu Sep 11, 2014 1:37 am; edited 2 times in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Sep 10, 2014 11:12 am |
|
|
There is a software CRC routine with the compiler. Look at ex_crc.c and the driver in crc.c
The actual assembler for the hardware routine is only about 20 lines. Not exactly large. Unfortunately the software simulator in MPLAB doesn't emulate the peripheral correctly, otherwise I'd see what it does. |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Thu Sep 11, 2014 1:35 am |
|
|
Quote: | There is a software CRC routine with the compiler. Look at ex_crc.c and the driver in crc.c |
I did. The code was a little too complicated... Anyway you saw the code I posted - same [un]efficiency but very straightforward.
Thanks! |
|
|
|