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: AustraliaPosts: 1593 |
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: AustraliaPosts: 844 |
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: AustraliaPosts: 1664 |
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. |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1593 |
@ 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: AustraliaPosts: 5905 |
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: AustraliaPosts: 1593 |
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: AustraliaPosts: 5905 |
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: NetherlandsPosts: 3534 |
@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: AustraliaPosts: 1593 |
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: AustraliaPosts: 5905 |
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: NetherlandsPosts: 3534 |
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 KingdomPosts: 5730 |
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: AustraliaPosts: 1593 |
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 |