Modbus source code in Pascal or C

R

Thread Starter

Rob Perry

Can any one tell me where I can get (or buy!) Turbo Pascal or C++ source code to make a PC into a Modbus slave. Physical interface is RS-485.
 
M

Michael Reed

One would think it is readily available. I searched and searched to no avail. I then asked if there was an ap note on how to write my own. Still nothing. I then asked for help on what I would need to do, and got lots of help!

Below is a brief flow chart on how I would program it. I haven't finished it, and you will have to consult the Modicon Modbus Protocol Reference Guide (try searching for "PI-MBUS-300") for details for each specific function. Program is based on Modbus RTU using assembly, but should be pretty generic if using C, and I don't think you will have much trouble starting from scratch.

Interrupt. If 3.5 character times have elapsed since last incoming data, assume message is complete, and set flag to decode and respond to message in main program.

Interrupt. Serial Data In. Buffer data. Start 3.5 character timer to trigger above interrupt.

Interrupt. Serial Data Out. Send the next byte of data if any more.

Main Program
Initilization
:Loop
If flag is set in 3.5 character interrupt, then
Confirm CRC. If wrong, don't respond
Confirm address. If wrong, don't respond
Based on function code, execute routine
If response message is required, output data (I plan on buffering data and enabling Serial Data Out interrupt so that I can output next byte in buffer)
Do other non-Modbus routines
Goto Loop

Hope this helps,
Michael
 
Yeah, I think if you do an internet search for some software called ModScan32, you will find a company that makes both host and slave software. They have a trail package that last for 10 min but you can close it and start it back up. Try that.
 
C
Hi Rob,
I'm currently in the same situation! I've got a RS485 serial slave and I'm beginning to get the first sensible communication back... I'm having some problems in calculating the CRC values. I'm using two different CRC-16 utility classes, both return different data for the same set of data, not matching the CRC values that the modbus device requires...

Do you know of some code that could do the CRC calculations for me?

(Incidentally, I'm using Java as the main language)

Many thanks!
Chris
[email protected]
 
C

Curt Wuollet

I think the sample source code on the Modicon site covers this. If not, the modbus driver in our source tree should. "mat.sf.net":http://mat.sf.net

If worse comes to worse, I could probably dig up what I used when I was playing with it. As I recall you had to be careful which parts are checked. And data types are very important with bitwise operations.

Regards
cww
 
R

Rob Hulsebos

Chris Douce wrote:
>I'm using two different CRC-16 utility classes, both return different data for the same set of data, not matching the CRC values that the modbus device requires...

That is very well possible, as there are several variant of a 16 bit CRC and Modbus uses only one of them. In the Modbus specification there is an
elaborate description and even some sample source code, and you can check your code against the sample-messages given with all the functioncodes.
That's how I did it (a long time ago).

Rob Hulsebos
 
P

Panu-Kristian Poiksalo

> Do you know of some code that could do the CRC calculations for me?

Hi, here's an ObjectPascal or Delphi function for generating the CRC.

Have fun!
Panu-Kristian Poiksalo

{MODBUS CRC-16 ObjectPascal (Delphi) Routine by Panu-Kristian Poiksalo 2003
This function calculates a checksum STRING for a message STRING for maximum
usability for me... example call for this function would be something like...

var message:string;
begin
message:=#1#5#0#0#255#0;
ModbusSerialPort.Output:= message + crc16string (message);
end;

happy coding! send me a greeting at [email protected] when you get it to
work and share this code freely with everyone at any web site!}

function crc16string(msg:string):string;
var crc: word;
n,i: integer;
b:byte;
begin
crc := $FFFF;
for i:=1 to length (msg) do begin
b:=ord(msg);
crc := crc xor b;
for n:=1 to 8 do begin
if (crc and 1)<>0
then crc:=(crc shr 1) xor $A001
else crc:=crc shr 1;
end;
end;
result:=chr(crc and $ff)+chr(crc shr 8);
end;
 
Top