Are there any working examples using the CRC for MODBUS RTU? I cannot get a reasonable result out if the CRC device on the STM32L443
According to Wikipedia The MODBUS uses the CRC-16-ANSI also known as CRC-16-IBM.
The normal hexadecimal algebraic polynomial being 8005 and reversed A001
Initial value: 65,535.
Example of frame in hexadecimal:
01 04 02 FF FF B8 80
(CRC-16-ANSI calculation for the 5 bytes from 01 to FF gives 80B8 which is transmitted least significant byte first).
I found some code that does the CRC16 with lookup tables, and it provides the same answer. So I believe the Wiki example is correct.
Reading the RM0394 Reference manual it appears it is a pretty simple peripheral. Only a few registers to set up.
CRC->DR is the data register.You write to this register and it holds the result.
the CRC->IDR is not clear what it is used for. Looks like 8-bit memory.
The CRC->INIT has a reset value of FFFFFFFF which is the sme as what I need.
The Only register that is not clear is the CRC->CR register. Bit 0 loads the CRC->INIT register value into the CRC->DR register for a new calculation. The POLYSIZE bits should be 01 for a 16 bit polynomial. The REV_OUT and REV_IN bytes are not clear. I tried both with 0 or bit order not affected. But the answer was not correct, so I tried every combination (only 8) none generated the right answer.
Here is my code:
void test_cr(uint32_t CR)
{
char buf[100];
CRC->POL = 0x8005;
CRC->CR = CR;
uint16_t i;
uint8_t data[7] = { 1, 4, 2, 0xFF, 0xFF, 0, 0};
for (i=0;i<5;i++)
{
CRC->DR = data[i];
HAL_Delay(1);
}
sprintf(buf,"CRC_CR: 0x%08lX, Result: 0x%08lX -- should be 0x80B8\r\n", CRC->CR,CRC->DR);
print_debug_str(buf);
}
void test_crc16(void)
{
char buf[100];
uint8_t data[7] = { 1, 4, 2, 0xFF, 0xFF, 0, 0};
uint16_t crc = Calculate_CRC16(data, 5); // this was from a routine I found that did it by table lookup.
sprintf(buf,"Wikipedia CRC 0x%04X -- should be 0x80B8\r\n",crc);
print_debug_str(buf);
test_cr(0x19);
test_cr(0x39);
test_cr(0x59);
test_cr(0x79);
test_cr(0x99);
test_cr(0xB9);
test_cr(0xD9);
test_cr(0xE9);
__NOP();
}I ran it and got:
Wikipedia CRC 0x80B8 -- should be 0x80B8
CRC_CR: 0x00000018, Result: 0x0000004E -- should be 0x80B8
CRC_CR: 0x00000038, Result: 0x00000009 -- should be 0x80B8
CRC_CR: 0x00000058, Result: 0x00000029 -- should be 0x80B8
CRC_CR: 0x00000078, Result: 0x00000036 -- should be 0x80B8
CRC_CR: 0x00000098, Result: 0x00000039 -- should be 0x80B8
CRC_CR: 0x000000B8, Result: 0x00000048 -- should be 0x80B8
CRC_CR: 0x000000D8, Result: 0x0000004A -- should be 0x80B8
CRC_CR: 0x000000E8, Result: 0x0000DE9D -- should be 0x80B8
None of the answers were right.
So then I wondered if the Polynomial had to be reversed or A001
Wikipedia CRC 0x80B8 -- should be 0x80B8
CRC_CR: 0x00000018, Result: 0x0000006F -- should be 0x80B8
CRC_CR: 0x00000038, Result: 0x00000063 -- should be 0x80B8
CRC_CR: 0x00000058, Result: 0x00000047 -- should be 0x80B8
CRC_CR: 0x00000078, Result: 0x0000001E -- should be 0x80B8
CRC_CR: 0x00000098, Result: 0x0000007B -- should be 0x80B8
CRC_CR: 0x000000B8, Result: 0x00000063 -- should be 0x80B8
CRC_CR: 0x000000D8, Result: 0x00000071 -- should be 0x80B8
CRC_CR: 0x000000E8, Result: 0x000090CD -- should be 0x80B8
With more reading I found something about a clock having to be started. I could not find anything about a CRC clock in RM0394 or nothing in the setup for CRC in the Device Configuration Tool, or in the RCC Device. It must be for another processor.
This should be pretty simple. What am I missing?
Thanks,
