2022-02-15 04:02 AM
Hi,
I am trying to run the CRC calculation with the STM32G031 but the results do not match. The result of the CRC16_CCITT_FALSE should be 0x29B1 according to http://www.sunshine2k.de/coding/javascript/crc/crc_js.html but I get 0x277F.
You can find my implementation below.
unsigned short CRC_16Bit_Polynom(unsigned char *Data, unsigned char Size);
void CRC_Init(void);
int main(void)
{
unsigned char Buffer[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
CRC_16Bit_Polynom(Buffer, 9);
}
void CRC_Init(void)
{
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = 0x00000000;
CRC->CR |= CRC_CR_POLYSIZE_0;
CRC->INIT = 0xFFFF;
CRC->POL = 0x1021;
}
unsigned short CRC_16Bit_Polynom(unsigned char *Data, unsigned char Size)
{
unsigned short Ergebnis = 0;
CRC->CR |= CRC_CR_RESET;
for(unsigned char i = 1; i <= Size; i++)
{
CRC->DR = (unsigned short) *Data;
Data++;
}
Ergebnis = (unsigned short)CRC->DR;
return Ergebnis;
}
Please kindly help to find the mistake.
Solved! Go to Solution.
2022-02-15 03:41 PM
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define POLY 0x1021
#define INIT 0xFFFF
int main(int argc, char **argv)
{
int i, j, k;
unsigned short crc;
unsigned char test[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
crc = INIT;
for(j=0; j<sizeof(test); j++)
{
crc = crc ^ (test[j] << 8);
for(i=0; i<8; i++)
{
if (crc & 0x8000)
crc = (crc << 1) ^ POLY;
else
crc = (crc << 1);
}
}
printf("crc=%04X\n", crc);
return(1);
}
2022-02-15 04:21 AM
Sure you have the length loop right?
Shift direction and ending ordering?
2022-02-15 04:30 AM
Yes, the loop length is correct.
Do you mean the order in which the bytes are written to CRC->DR? Then I am not sure.
The "Reverse Input Data" and the "Reverse Output Data" should be right.
2022-02-15 05:44 AM
unsigned short for your compiler means uint16_t?
CRC->DR is usually defined as *(uint32_t*) i.e. essentially uint32_t.
> CRC->DR = (unsigned short) *Data;
Data you have declared as unsigned char * so *Data picks a byte, extends it to unsigned short (whatever that is), and then stores it into uint32_t register, i.e. it adds up 3x 0x00 to the the read data.
Read CRC operation subchapter of CRC chapter in RM.
JW
2022-02-15 05:50 AM
That's right unsigned short means uint16_t. CRC->DR is the 32 bit CRC data register configured for 16 bit polynomial.
2022-02-15 06:17 AM
> That's right unsigned short means uint16_t.
You still read bytes from the array, and advance pointer, byte-by-byte. The cast to uint16_t extends the byte by 0x00.
> CRC->DR is the 32 bit CRC data register configured for 16 bit polynomial.
But that does not mean CRC->DR acts as a 16-bit register. Writing a 16-bit value to CRC->DR as it's defined in the device header, i.e. 32-bit, means that the 16 bits (which was a byte extended by 0x00) is extended by further 0x0000.
Read CRC operation subchapter of CRC chapter in RM.
If you want to write CRC->DR as 16-bit, in C you need to cast:
*(volatile uint16_t *)&CRC->DR = 16-bit-value;
but you still need to assemble the bytes into 16-bit values.
Or, write byte by byte
*(volatile uint8_t *)&CRC->DR = *Data;
Less efficient, but should work OK, without the problems with outstanding data in odd-length buffers.
JW
2022-02-15 03:37 PM
while(Size--) *(volatile uint8_t *)&CRC->DR = *Data++;
2022-02-15 03:41 PM
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define POLY 0x1021
#define INIT 0xFFFF
int main(int argc, char **argv)
{
int i, j, k;
unsigned short crc;
unsigned char test[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
crc = INIT;
for(j=0; j<sizeof(test); j++)
{
crc = crc ^ (test[j] << 8);
for(i=0; i<8; i++)
{
if (crc & 0x8000)
crc = (crc << 1) ^ POLY;
else
crc = (crc << 1);
}
}
printf("crc=%04X\n", crc);
return(1);
}