Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 00:29 30 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Modbus CRC.

     Page 2 of 2    
Author Message
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 07:05am 28 Nov 2018
Copy link to clipboard 
Print this post

I have updated my Modbus CRC program to make it more user friendly. It now returns a string value (as Phil's version of Jim's code above does) and is formatted ready to append to a message string.


OPTION EXPLICIT

DIM INTEGER crc_table(255) ' lookup table for CRC generation

genCRCtable ' generate the lookup table


'------------------------------------------------------------
'generates a lookup table for fast crc calculation
SUB genCRCtable
LOCAL i%, j%, k%, crc_const% = &HA001
FOR i% = 0 TO 255
k% = i%
FOR j% = 1 TO 8
IF k% AND 1 THEN
k% = k% >> 1
k% = k% XOR crc_const%
ELSE
k% = k% >> 1
END IF
NEXT j%
crc_table(i%)=k%
NEXT i%
END SUB
'
' returns the CRC as a string
FUNCTION CRC16$(a$)
LOCAL CRC% = &HFFFF, n%
FOR n% = 1 TO LEN(a$)
CRC% = (CRC% >> 8) XOR crc_table(CRC% XOR ASC(MID$(a$, n%, 1)) AND &HFF)
NEXT n%
CRC16$ = CHR$(CRC% AND &HFF) + CHR$((CRC%>>8) AND &HFF)
END FUNCTION
'-------------------------------------------------------------

To use it: include the Subroutine and Function in your program (of course) and dimension the lookup table -

DIM INTEGER crc_table(255) ' lookup table for CRC generation

Run the table generation subroutine early in the program, at least before using the CRC16$() Function.

genCRCtable ' generate the lookup table

To use the CRC$16() function, first assemble a transmit message as a string (say TxMsg$). Then append the CRC to the end of the message by:

TxMsg$ = TxMsg$ + CRC16$(TxMsg$)

and transmit it.

To check that a received message (say RxMsg$) has the correct CRC and is otherwise not corrupted, test if by:

IF CRC16$(RxMsg$) = CHR$(0) + CHR$(0) THEN ' CRC is OK

Be aware that this routine requires a table of 256 bytes of 64 bit integers, if space is a problem and speed is not then use Phil's routine above. It is used in exactly the same way - except there is no table to initialise (and take up memory). Just use:

TxMsg$ = TxMsg$ + CrcStr(TxMsg$)

and

IF CrcStr(RxMsg$) = CHR$(0) + CHR$(0) THEN ' CRC is OK

instead.

If you want to see what is in the message as a debugging exercise you could use the subroutine below:

SUB PrintStr(b$)
LOCAL i%
FOR i% = 1 TO LEN(b$)
PRINT HEX$(ASC(MID$(b$,i%,1)),2); ", ";
NEXT i%
END SUB

For example:

PrintStr CRC16$(TxMsg$)

Please consider the use of a CRC for any communication programs. I hope the above explanation will encourage some of you to do so.

Bill

PS If someone could tell me how to get colour in the code I would be grateful. I printed to RTF in MMEdit but the colour did not come across when I copied and pasted.


Keep safe. Live long and prosper.
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 844
Posted: 11:09am 28 Nov 2018
Copy link to clipboard 
Print this post

File/Format for TBS Forum gets it into the clipboard.
Then paste into the forum.




Latest F4 Latest H7
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1664
Posted: 07:53pm 28 Nov 2018
Copy link to clipboard 
Print this post

Missed this continuation.

No issues at present, but more efficient is better on all scores.
Can't see any reason not to use the better code.

Incidentally, the 3 meters I'm reading have performed faultlessly for the past 8 of 9 months, 6378kWh used from the grid, 2715kWh of Solar production.

Haven't got back to the updated interface of SD logging yet.
It's that WIP that gets pushed to the bottom of the list.


Cheers.Edited by Phil23 2018-11-30
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 04:44am 01 Dec 2018
Copy link to clipboard 
Print this post

@ disco4now, thanks for that, it didn't work for me but I now realise that you have to use QUOTE instead of CODE.

@ Phil23, I did spot the deliberate mistake in your (and Jim's original) CrcStr(a$) function. ByteVal is assigned a value in line 5 but not used, the byte value itself is calculated again and used in line 6 where ByteVal was probably meant to be used. ByteVal is redundant.

Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5905
Posted: 06:21am 01 Dec 2018
Copy link to clipboard 
Print this post

  Turbo46 said   @ disco4now, thanks for that, it didn't work for me but I now realise that you have to use QUOTE instead of CODE.

Bill

You shouldn't use anything. MMEdit adds the required QUOTE /QUOTE for you.

Jim
VK7JH
MMedit   MMBasic Help
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 06:28am 01 Dec 2018
Copy link to clipboard 
Print this post

Ah, OK - thanks Jim,

I put it inside a CODE format thingy and a preview showed it as black lettering on a grey background. I'll try again next time. So it's just a straight paste from the clipboard then? No format codes.

Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5905
Posted: 06:35am 01 Dec 2018
Copy link to clipboard 
Print this post

  Turbo46 said   So it's just a straight paste from the clipboard then? No format codes.

Bill

Yes. I tried to keep it simple.

If you select some code, that is what gets pasted or if you don't select any, the full program gets copied to the clipboard.

Jim

VK7JH
MMedit   MMBasic Help
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3534
Posted: 12:12pm 15 Jul 2021
Copy link to clipboard 
Print this post

@Phil. TassyJim, Turbo46,

On this forum I see several threads concerning CRC, and these are all related to the modbus CRC algorythm (well, the algorythm is CRC, but the seed, poly, and endianess of data are different, that is what I thought).

This is one example of the (slower) code found on this forum. This doesn't use tables. I tried to convert the below code to do CCITT CRC (16 bit). But just changing the poly and seed doesn't pull it (it does not give the correct CRC's on test strings).
I noticed below code uses a bit reversed poly (&h8005 -> &hA001) and shifts right (divide by 2). The CCITT does not use bit reversal. The seed is &hFFFF and the poly is &h1021. So theoretically you should use the poly as is (&h1021), change the mask from &h0001 to &h8000, left shift (multiply by 2, that will automatically shift a zero in).
Anyway, I failed to make the altered version match the correct CRC of online tools like:

https://crccalc.com/

Function CRC(a$) 'validated modbus CRC
 Local ErrorWord% = &HFFFF, n, j, ByteVal, LSB
 For n = 1 To Len(A$)
   ByteVal = Asc(Mid$(a$, n, 1))
   ErrorWord% = (ErrorWord% And &HFFFF) Xor Asc(Mid$(a$, n, 1))
   For j = 1 To 8
     LSB = ErrorWord% And &H0001
     If LSB = 1 Then ErrorWord% = ErrorWord% - 1
     ErrorWord% = ErrorWord% / 2
     If LSB = 1 Then ErrorWord% = ErrorWord% Xor &HA001
   Next j
 Next n
 CRC = ErrorWord% And &HFFFF
 'CRC = (ErrorWord% Mod 256)*256 + Int(ErrorWord%/256) Mod 256
End Function


Has anyone a working version of a CRC 16 that does not use bit reversal ?
PicomiteVGA PETSCII ROBOTS
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 05:51am 16 Jul 2021
Copy link to clipboard 
Print this post

I found some examples on the web: here,  here and here and tried to convert them to MMBasic but could not get the 'correct' results either.

I'm not sure which one you are after but neither of my efforts gave the same result as any of the results shown. I can paste the two versions I did if you want to look for the 'deliberate' mistake(s).

Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5905
Posted: 06:53am 16 Jul 2021
Copy link to clipboard 
Print this post

Just to be sure we are looking at the same "standard", can you provide a test string and correct CRC

Jim
VK7JH
MMedit   MMBasic Help
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3534
Posted: 06:56am 16 Jul 2021
Copy link to clipboard 
Print this post

Hi Turbo46,

I decided to give it another shot. Looked at your 3'rd example (the C-code) and used that to create following that works:

Function CCITT(a$)
 Local i%,j%,crc%=&hffff 'seed
 For j%=1 To Len(a$)
   crc% = crc% Xor (Asc(Mid$(a$,j%,1)) * 256)
   For i%=8 To 1 Step -1
     If (crc% And &h8000) Then
       crc% = (crc% * 2) Xor &h1021 'poly
     Else
       crc% = crc% * 2
     End If
   Next i%,j%
 CCITT = crc% And &hffff
End Function


Now I have to look what CRC-16 I need to implement, but I have the reverse (modbus) and the normal (CCITT) algorythm both working, so it is playing with seed and poly and all are covered.

Sorry if I have poluted the modbus thread.

Volhout
Edited 2021-07-16 16:56 by Volhout
PicomiteVGA PETSCII ROBOTS
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5730
Posted: 03:42pm 16 Jul 2021
Copy link to clipboard 
Print this post

Any use to anyone?
https://rosettacode.org/wiki/CRC-32
There's a freeBASIC implementation there.
Edited 2021-07-17 01:53 by Mixtel90
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 07:34pm 16 Jul 2021
Copy link to clipboard 
Print this post

Thanks Volhout, another one for the collection. There is also the Xmodem CRC link

Bill
Keep safe. Live long and prosper.
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024