|
|
View previous topic :: View next topic |
Author |
Message |
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
crc 16 calculation help |
Posted: Tue Dec 15, 2020 4:20 am |
|
|
I am using dspic33ep512mu810.
I am new to CRC kindly guide me how to calculate 16bit crc
for example the Modbus RTU data is
01 05 00 02 FF 00
and CRC for the above is 2D FA
CASE 1: 01 05 00 02 FF 00 how to get 2D FA (generate crc)
CASE 2: how to check 2D FA is correct for 01 05 00 02 FF 00 ( check crc) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Dec 15, 2020 4:33 am |
|
|
If you look in the example physical layer. Modbus_phy_layer_rtu.c
it has a function modbus_calc_crc, that will calculate the CRC if called with
the data bytes one by one. You need to start the CRC set to 0xffff before
calling the first time. It does it quickly by using table look ups for the values.
By far the fastest and easiest way to do this.
You calculate the CRC as you receive the bytes, and then compare this
with what you receive for the CRC bytes. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Tue Dec 15, 2020 9:56 am |
|
|
Hello,
Here is sample test program for your example packet and how to setup serial port of this controller:
Code: |
#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz, clock=16MHz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOJTAG //JTAG disabled
/* HW UART1 */
#pin_select U1RX=PIN_E1 // Rx Com1.
#pin_select U1TX=PIN_E0 // Tx Com1.
#define EN1_485 PIN_D1 // RE/DE Com1.
#use rs232(UART1,baud=9600,errors)
const unsigned int16 wCRCTable[] = {
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 };
unsigned int16 CRC16 (BYTE *nData, unsigned int16 wLength){
BYTE nTemp;
unsigned int16 wCRCWord = 0xFFFF;
while (wLength--)
{
nTemp = *nData++ ^ wCRCWord;
wCRCWord >>= 8;
wCRCWord ^= wCRCTable[nTemp];
}
return wCRCWord;
}
void main(void){
delay_ms(1000); // some starup delay
printf("\r\n ModBus RTU CRC Example.\r\n");
unsigned int16 CalcW_CRC = 0;
unsigned int16 RecW_CRC = 0xFA2D; // MSB,LSB swapped!
BYTE data[] = {0x01,0x05,0x00,0x02,0xFF,0x00}; // 0x2DFA - Received wCRC sum.
CalcW_CRC = CRC16(data, sizeof(data)); //
printf("\r\n Recived CRC=0x%lX, Calc.CRC=0x%lX",RecW_CRC, CalcW_CRC);
if(CalcW_CRC == RecW_CRC)
printf("\r\n CRC-OK!");
else
printf("\r\n CRC-ERROR!");
while(TRUE){
//User Code ...
}
} |
Best Regards, |
|
|
steve__p
Joined: 09 Sep 2020 Posts: 2
|
|
Posted: Tue Dec 15, 2020 11:33 am |
|
|
For your info, here is my version without table, used with PIC24FJ128GA306:
Code: |
uint16 modbus_crc(uint8 *data,uint8 size)
{
uint16 crc;
uint8 i,z;
crc=0xFFFF;
for(i=0;i<size;i++)
{
crc=crc^data[i];
for(z=0;z<8;z++)
{
if(bit_test(crc,0))
{
crc=crc/2;
crc=crc^0xA001;
}
else crc=crc/2;
}
}
return(crc);
}
|
|
|
|
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
|
Posted: Tue Dec 15, 2020 11:33 pm |
|
|
kmp84 wrote: | Hello,
Here is sample test program for your example packet and how to setup serial port of this controller:
.
.
.
|
your code works great thanks for the help bro.
i have one doubt, what is the maximum number of bytes i can check.
wlength=? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Dec 16, 2020 2:10 am |
|
|
Potentially 32KB!....
wlength is an int16, which on a PIC24/33 is a signed int16, so maximum
supported length would be 32767 bytes, However obviously real limits on how
much data you can actually store would override this. Modbus itself limits
the maximum packet size. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 354
|
|
Posted: Wed Dec 16, 2020 4:20 am |
|
|
Hi,
Here is Modbus specification:
https://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf
I think max. data field length are 125 registers x 2 bytes =250 bytes, but read info from link above. It's also depend from external factors like line length, baud rate if using rs485 interface etc.
P.S. CCS's modbus rtu driver work very well for me, but when packets are long they don't use transmit interrupts! I don't know why.
Best Regards! |
|
|
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
|
Posted: Thu Dec 17, 2020 3:42 am |
|
|
sir where can i find CCS's modbus rtu driver?
any link ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Dec 17, 2020 3:56 am |
|
|
It is with the compiler.
Sub-directories of the the compiler directory. Examples, and drivers.
There is a master and slave modbus example. The physical hardware driver
changes for RTU, and is modbus_phy_layer_rtu.c This is automatically
loaded if you specify the MODBUS_SERIAL_TYPE as MODBUS_RTU. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|