Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 07:07 03 Dec 2025 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 : Request: Micromite Modbus CRC CFunction

Author Message
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1647
Posted: 05:36am 02 Dec 2025
Copy link to clipboard 
Print this post

Hello All,

I would like to use the Modbus CRC in a Micromite MK2. I am aware of the MMBasic versions on The Fruit Of The Shed (I put them there) but I would like to use a CFunction for extra speed. I also Know that it is available in the PicoMite but I want to use the Micomite.

Claude AI has written the C code for me but I don't have the software or the knowledge to compile the code.

If there is someone out there who could do that for I would be very grateful.

The code:
/*
* Modbus CRC-16 CFunction for Micromite Mk2 MMBasic
*
* Compile this with MPLAB X and XC32 compiler using the settings:
* - Position independent code (-mno-abicalls -fno-pic)
* - Optimization level -O1 or -O2
* - Target: PIC32MX470F512H (for Micromite Mk2)
*
* After compiling, extract the hex codes and insert into MMBasic as:
*
* CFunction modbus_crc(STRING) INTEGER
*   [hex codes here]
* End CFunction
*
* Usage in MMBasic:
*   data$ = CHR$(&h01) + CHR$(&h03) + CHR$(&h00) + CHR$(&h00) + CHR$(&h00) + CHR$(&h0A)
*   crc% = modbus_crc(data$)
*   PRINT "CRC: "; HEX$(crc%, 4)
*/

#include "CFunction.h"

/*
* Calculate Modbus CRC-16
* Input: Pointer to MMBasic string (first byte = length, followed by data)
* Returns: 16-bit CRC value as long long int
*/
long long int modbus_crc(unsigned char *str) {
   unsigned char len;
   unsigned char *data;
   unsigned short crc;
   int i, j;
   
   // Get string length (first byte)
   len = *str;
   
   // Point to actual data (skip length byte)
   data = str + 1;
   
   // Initialize CRC to 0xFFFF
   crc = 0xFFFF;
   
   // Process each byte
   for (i = 0; i < len; i++) {
       crc = crc ^ data[i];
       
       // Process each bit
       for (j = 0; j < 8; j++) {
           if (crc & 0x0001) {
               crc = (crc >> 1) ^ 0xA001;
           } else {
               crc = crc >> 1;
           }
       }
   }
   
   // Return as long long int (MMBasic integer type)
   return (long long int)crc;
}

/*
* Example usage in MMBasic:
*
* ' Define the CFunction (after compiling and extracting hex codes)
* CFunction modbus_crc(STRING) INTEGER
*   00000000
*   [your hex codes here]
* End CFunction
*
* ' Use it in your program
* data$ = CHR$(&h01) + CHR$(&h03) + CHR$(&h00) + CHR$(&h00) + CHR$(&h00) + CHR$(&h0A)
* crc% = modbus_crc(data$)
*
* PRINT "CRC value: "; HEX$(crc%, 4)
*
* ' Append CRC to message (Modbus uses little-endian: low byte first)
* message$ = data$ + CHR$(crc% AND &hFF) + CHR$((crc% >> 8) AND &hFF)
*
* ' Send the complete message with CRC
* PRINT "Complete message with CRC: ";
* FOR i = 1 TO LEN(message$)
*   PRINT HEX$(ASC(MID$(message$, i, 1)), 2); " ";
* NEXT i
* PRINT
*/


If someone can do it for me I will ask Geoff to include it in the documentation and/or put it on The Fruit Of The Shed.

Thank you in anticipation.

Bill
Keep safe. Live long and prosper.
 
Print this page


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

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025