2011-01-12 04:46 AM
2012-06-17 06:13 AM
// 16-Bit CRC of Right Shifting MODBUS Polynomial 0xA001
#include <
windows.h
>
#include <
stdio.h
>
WORD Crc16Modbus(WORD Crc, BYTE Data)
{
int i;
Crc = Crc ^ Data;
for(i=0; i<
8
; i++)
if (Crc & 0x0001)
Crc = (Crc >> 1) ^ 0xA001; // Polynomial used by MODBUS
else
Crc = (Crc >> 1); // Right shifting algorithm
return(Crc);
}
int main(int argc, char **argv)
{
BYTE TestData[] = { 0x01,0x04,0x75,0x54,0x00,0x02 };
WORD crc;
int i;
crc = 0xFFFF; // Initial state
for(i=0; i<sizeof(TestData); i++)
crc = Crc16Modbus(crc, TestData[i]);
printf(''CRC = %04
X'', crc);
return(1);
}
2012-06-17 06:38 AM
Faster algorithm using nibble table lookup, trade off between speed and size.
WORD Crc16ModbusFast(WORD Crc, BYTE Data) // sourcer32@gmail.com
{
static const WORD CrcTable[16] = { // Nibble lookup for 0xA001 polynomial
0x0000,0xCC01,0xD801,0x1400,0xF001,0x3C00,0x2800,0xE401,
0xA001,0x6C00,0x7800,0xB401,0x5000,0x9C01,0x8801,0x4400 };
Crc = Crc ^ Data;
// Process 8-bits, 4 at a time, or 2 rounds
Crc = (Crc >> 4) ^ CrcTable[Crc & 0xF];
Crc = (Crc >> 4) ^ CrcTable[Crc & 0xF];
return(Crc);
}
Could use a 256 entry table, but would eat 512 bytes of ROM/FLASH
2012-06-18 09:19 AM
this works perfectly
MANY THANKS!2013-05-28 12:19 AM
Thank you clive1!
A very good post. Maybe ST can make an appnote about this subject. After all, CRC is not a trivial subject. So many ways to do it and only one correct.2013-11-02 01:20 PM
Fully hardware method:
<code>uint32_t reverse_32(uint32_t data)
{
asm(''rbit r0,r0'');
return data;
};
uint32_t crc32_ether(char *buf, int len, int clear)
{
uint32_t *p = (uint32_t*) buf;
uint32_t crc, crc_reg;
if(clear) CRC_ResetDR();
while(len >= 4) {
crc_reg = CRC_CalcCRC(reverse_32(*p++));
len -= 4;
}
crc = reverse_32(crc_reg);
if(len) {
CRC_CalcCRC(crc_reg);
switch(len) {
case 1:
crc_reg = CRC_CalcCRC(reverse_32((*p & 0xFF) ^ crc) >> 24);
crc = ( crc >> 8 ) ^ reverse_32(crc_reg);
break;
case 2:
crc_reg = CRC_CalcCRC(reverse_32((*p & 0xFFFF) ^ crc) >> 16);
crc = ( crc >> 16 ) ^ reverse_32(crc_reg);
break;
case 3:
crc_reg = CRC_CalcCRC(reverse_32((*p & 0xFFFFFF) ^ crc) >> 8);
crc = ( crc >> 24 ) ^ reverse_32(crc_reg);
break;
}
}
return ~crc;
}
</code>
2013-11-13 06:01 AM
Maybe ST can make an appnote about this subject. After all, CRC is not a trivial subject.
There is a new application note''
http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/PF259064
'', hoping it will bring some help for CRC users. -Mayla-To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2014-07-16 07:22 AM
Dear Sir:
We want to calculate the CRC check sum for program code which write to the FLASH memory address 0x08010000, we use the CRC peripheral in the STM32 family (Suggested by Mayla) but we get an error message (HardFault Stack_dump registers ) during processing to 27xxxx Bytes. No matter we add more stack size, it always the same result. We do not what the reason? Can anyone help us, thanks! The example is as below~BRAlan=============================#define FLASH_ADDRESS 0x08010000#define PROGRAM_SIZE 358068.....RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);CRCValue = CRC_CalcBlockCRC((uint32_t *), PROGRAM_SIZE ); //It will cause error inside this subroutine.......RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE);printf(''\r\n CRC Value = 0x%0x\r\n'', CRCValue);2014-07-16 07:25 AM
Dear Sir:
We want to calculate the CRC check sum for program code which write to the FLASH memory address 0x08010000, we use the CRC peripheral in the STM32 family (Suggested by Mayla) but we get an error message (HardFault Stack_dump registers ) during processing to 27xxxx Bytes. No matter we add more stack size, it always the same result. We do not what the reason? Can anyone help us, thanks! The example is as below~BRAlan=============================#define FLASH_ADDRESS 0x08010000#define PROGRAM_SIZE 358068.....RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);CRCValue = CRC_CalcBlockCRC((uint32_t *)FLASH_ADDRESS
, PROGRAM_SIZE ); //It will cause error inside this subroutine.......RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE);printf(''\r\n CRC Value = 0x%0x\r\n'', CRCValue);2014-07-16 09:18 AM
The ST Library function has a count of 32-bit words, not bytes. Scale your length parameter accordingly.
/**
* @brief Computes the 32-bit CRC of a given buffer of data word(32-bit).
* @param pBuffer: pointer to the buffer containing the data to be computed
* @param BufferLength: length of the buffer to be computed
* @retval 32-bit CRC
*/
uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength)
{
uint32_t index = 0;
for(index = 0; index <
BufferLength
; index++)
{
CRC->DR = pBuffer[index];
}
return (CRC->DR);
}
2014-07-18 12:54 AM
Dear Clive1
:
Thanks for your reminder!BRAlan