You are on page 1of 189

www.plcworld.

cn

Communication
Protocol

PLCProgrammable Logical Controller


PLC
PLC Modbus
Modicon PLC Modicon PLC

(1-1)

RS232C

Ethernet

2.1
Start
BitData BitParity BitStop Bit
Byte

z Bit
z Byte

www.plcworld.cn

1111001

(1-2)

Start - Stop
/

1
0
/
Byte
1

0 1
z Baud Rate
0 1
z ParityNoneOddEven
z Data Bits
5678

z Stop Bits 11.52

1 7 None
9600 bps ABC
ASCII Code(0) 8 8
7 ASCII 1

www.plcworld.cn

1 0
7 ASCII

2.2

SDLCHDLC

SYN

SYN

(1-3)
F

(1-4)

8
SYN16 0x16

SYN

www.plcworld.cn

20% HDLC
48 1000
48 / 1048 * 100% = 4.6%
Modbus
PLC
Modbus Plus
Modbus
Modbus
2.3 Ethernet
Ethernet Broadcast

Ethernet 48 Ethernet Frame


64 1518
CRC Check

Frame type

Data

CRC

46 - 1500

(1-5)Ethernet Frame format

Frame type
TCPUDP . CRC
CRC Frame CRC

Ethernet IP Address Station No.CRC


Frame Ethernet Ethernet

API
TCP/IP socket
WindowsUnixDOS

www.plcworld.cn

Modbus/TCP 6 byte
Modbus/232 TCP
socket RS232
CRC Frame .

Communication Protocol

3.1 PLC
PLC

PLC

Modicon
Modbus/232

Modbus Plus

Modbus/TCP
Ethernet TCP/IP
Allen-Brandley
DF1

EtherentIP
Ethernet
Profibus
SimaticSiemens
Ethernet
MPI

Simatic TI PLC
Task Code

GE
SNP
Ethernet
Mitsubishi MelsecA
PC-Link
Ethernet
Mitsubishi FX2
PC-Link

OMRON
HostLink

FINS
Ethernet
Koyo
U-01DM/G-01DM

(1-6)

3.2 Modbus
Modbus Modicon PLC
1979 Modbus Modbus Plus
1997 Modbus/TCP OSI

www.plcworld.cn

Application Layer Client/Server


Master/Slave Modbus

Modbus Modbus Plus

Modbus/TCP Ethernet
Modbus Plus
Modbus Modbus/TCP

www.plcworld.cn

Modbus
Modbus Master and Slave
Master Query Message Slave
Slave Query Message Response Message
Master
Modbus Master Slave
(HMI) MasterPLC
SlaveHMI Polling Slave relay and register

1
1.1 Query and Response Cycle
Device Address

Device Address
Query message from Master

Function code
Eight-Bit
Data Bytes

Function code
Eight-Bit
Data Bytes
Response message from Slave

Error Check

Error Check

Master

Slave

(2-1)Master / Slave and Query / Response Cycle

Device Address
TCP/IP IP Address Device Address

Function Code Slave Command


Function Number
Eight-Bit Data Bytes Function Code Slave

Error Check
Error Check Code message
Code
CRC and LRC TCP/IP Error Check
TCP/IP Modbus/TCP
1.2 Data Format
Query and Response Message
256

z RTU

www.plcworld.cn

T1-T2-T3-T4

Device

Function

Address

Code

8 Bits

8 Bits

Data

CRC check

Number of 8

16 Bits

T1-T2-T3-T4

Bits
(2-2)RTU data format

T1-T2-T3-T4RTU Query Response Message


3.5
9600 bps 8 bits
1 start bit 1 stop bit 10 bits 3.5
(3.5 * 10) / 9600 = 0.00365
T1-T2-T3-T4
8 Bits
DataNumber of 8 Bits Function Code

Error Check CRC

z ASCII

Device

Function

Address

Code

Data

LRC check

2
<CR> <LF>

(2-3)ASCII data format

ASCII
0123456789ABCDEF 16 ASCII

Device Address Data 8 bits


ASCII RTU

Data Function Code

Error Check LRC

z TCP/IP

www.plcworld.cn

Device

Function

Address

Code

8 Bits

8 Bits

Data

Error check

Number of 8

Bits
(2-4)TCP/IP data format

6 TCP/IP

Byte 0 Message 2 bytes Byte 01


byte Master
Message Slave Master Query
Message Response Message
Byte 1 Message
Byte 2 2 bytes Byte 23 byte

Byte 3
Byte 4Message 2 bytes Byte 45 byte
Device Address Data
256
Byte 5Message Device Address Data
Device Address Data RTU
Modbus IP Port No. 502

z
Function Code-3 Output Register Device address6Start Address
40123Modbus Output Register 40001 40001
122 0x007A3
Query Message
ASCII
RTU
TCP

Code
8-bits
field
8-bits
field

TCP Byte-0
0000 0000
TCP Byte-1
0000 0001
TCP Byte-2
0000 0000
TCP Byte-3
0000 0000
TCP Byte-4
0000 0000
TCP Byte-5
0000 0110
:
ASCII
Device Address
06
06
0000 0110
0000 0110

www.plcworld.cn

Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of registers (Hi byte)
No. of register (Lo byte)
Error Check Byte-0
Error Check Byte-1

03
00
7A
00
03

03
00
7A
00
03

0000 0011
0000 0000
0111 1010
0000 0000
0000 0011

0000 0011
0000 0000
0111 1010
0000 0000
0000 0011

<CR><LF>

(2-5)Example of Query Message

3 register 78912345-567 0x03150x3039


0xFDC9
Response Message
ASCII
RTU
TCP

Code
8-bits field
8-bits field

TCP Byte-0
0000 0000
TCP Byte-1
0000 0001
TCP Byte-2
0000 0000
TCP Byte-3
0000 0000
TCP Byte-4
0000 0000
TCP Byte-5
0000 1001
:
ASCII
Device Address
06
06
0000 0110
0000 0110
Function Code
03
03
0000 0011
0000 0011
Byte count
06
06
0000 0110
0000 0110
Data-1 (Hi byte)
03
03
0000 0011
0000 0011
Data-1 (Lo byte)
15
15
0001 0101
0001 0101
Data-2 (Hi byte)
30
30
0011 0000
0011 0000
Data-2 (Lo byte)
39
39
0011 1001
0011 1001
Data-3 (Hi byte)
FD
FD
1111 1101
1111 1101
Data-3 (Lo byte)
C9
C9
1100 1001
1100 1001
Error Check Byte-0
Error Check Byte-1
<CR><LF>

(2-6)Example of Response Message

1.3 Function Code


Function Code 123456
1516 2021 General
Reference Register Modbus Register PLC
Function Code

www.plcworld.cn

z DIDigital Input bit On/Off


switch
PLC Input relayinput coil
z DODigital Output bit On/Off
PLC Output
relayOutput coil
z AIAnalog Input 16 bits integer

PLC Input register


z AOAnalog Output 16 bits integer

PLC Output registerHolding


register
Modbus Function Code
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
43
65 to 72
100 to 110

Read Coil Status (output relay)


Read Input Status (input relay)
Read Holding Registers (output register)
Read Input Registers
Force Single Coil
Preset Single Register
Read Exception Status
Diagnostics
Program 484
Poll 484
Fetch Comm. Event Ctr.
Fetch Comm. Event Log
Program Controller
Poll Controller
Force Multiple Coils
Preset Multiple Registers
Report Slave ID
Program 884/M84
Reset Comm. Link
Read General Reference
Write General Reference
Mask Write 4x Register
Read/Write 4x Register
Read FIFO Queue
Read Device Identication

www.plcworld.cn

(2-7)Modbus Function Code

10 Function Code Function Code


Message TCP ByteASCII Error
Check
Function Code-1 DI Modbus Relay Address 00001

Relay Address 00345


Address 344
Device Address 17 Relay Address 20 32 DI
Start Address 19 13
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of points (Hi byte)
No. of points (Lo byte)

11
01
00
13
00
0D

Byte 8 bits Bit Relay On/Off

Data(Relay 27 20) ON-ON-OFF-ON-OFF-OFF-ON-ON


Data(Relay 32 28) OFF-ON-OFF-ON-ON-ON 3 bit
Relay 32
Relay Relay 27 ONRelay 31 ONRelay 23
OFF
Response Message
Device Address
Function Code
Byte count
Data (Relay 27 20)
Data (Relay 32 28)

11
01
02
D3
17

(2-8)Example of Function Code - 1 Message

www.plcworld.cn

Function Code-2 DO Modbus Relay Address 10001


Relay Address
10678 Address 677
Device Address 23 Relay Address 10102 10134 D0
Start Address 101 33
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of points (Hi byte)
No. of points (Lo byte)

17
02
00
65
00
21

Byte 8 bits Bit Relay On/Off

Data(Relay 109 102) ON-OFF-ON-OFF-ON-OFF-ON-OFF


Data(Relay 117 110) OFF-ON-OFF-OFF-OFF-ON-OFF-ON
Data(Relay 125 118) OFF-OFF-ON-OFF-OFF-ON-ON-ON
Data(Relay 133 126) ON-OFF-OFF-OFF-OFF-OFF-ON-ON
Data(Relay 134 134) ON
7 bit Relay
134
Response Message
Device Address
Function Code
Byte count
Data (Relay 109 102)
Data (Relay 117 110)
Data (Relay 125 118)
Data (Relay 133 126)
Data (Relay 134 134)

17
02
05
AA
45
27
83
01

(2-9)Example of Function Code - 2 Message

www.plcworld.cn

Function Code-3 AO Modbus Register Address 40001

Register Address 44321


Address 4320
Device Address 41 Register Address 40765 40770 A0
Start Address 764 6
Query Message

Device Address
29
Function Code
03
Start Address (Hi byte)
02
Start Address (Lo byte)
FC
No. of registers (Hi byte)
00
No. of registers (Lo byte)
06
Bytes 16 bits
Register 40765 99
Register 40766 12336
Register 40767 1417
Register 40768 789
Register 40769 767
Register 40770 1
Response Message

Device Address
29
Function Code
03
Byte count
0C
Data-1 (Hi byte)
00
Data-1 (Lo byte)
63
Data-2 (Hi byte)
30
Data-2 (Lo byte)
30
Data-3 (Hi byte)
FA
Data-3 (Lo byte)
77
Data-4 (Hi byte)
03
Data-4 (Lo byte)
15
Data-5 (Hi byte)
02
Data-5 (Lo byte)
FF
Data-6 (Hi byte)
00
Data-6 (Lo byte)
01
(2-10)Example of Function Code - 3 Message

www.plcworld.cn

Function Code-4 AI Modbus Register Address 30001

Relay Address 30988


Address 987
Device Address 30 Register Address 30123 30127 AI
Start Address 122 5
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of registers (Hi byte)
No. of registers (Lo byte)

1E
04
00
7A
00
05

Bytes 16 bits
Register 30123 2581
Register 30124 57
Register 30125 969
Register 30126 24544
Register 30127 170
Response Message
Device Address
Function Code
Byte count
Data-1 (Hi byte)
Data-1 (Lo byte)
Data-2 (Hi byte)
Data-2 (Lo byte)
Data-3 (Hi byte)
Data-3 (Lo byte)
Data-4 (Hi byte)
Data-4 (Lo byte)
Data-5 (Hi byte)
Data-5 (Lo byte)

1E
04
0A
0A
15
00
39
03
C9
A0
20
00
AA

(2-11)Example of Function Code - 4 Message

www.plcworld.cn

Function Code-5 DO Address Function Code-2

Device Address 10 Relay Address 10012 D0


Start Address 11 ON Force Data 0xFF00
OFF Force Data 0x0000
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Force Data (Hi byte)
Force Data (Lo byte)

0A
05
00
0B
FF
00

Query Message Response Message


Response Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Force Data (Hi byte)
Force Data (Lo byte)

0A
05
00
0B
FF
00

(2-12)Example of Function Code - 5 Message

www.plcworld.cn

Function Code-6 AO Address Function Code-3

Device Address 13 Register Address 40112 A0


Start Address 111 16 bits 999 0x03E7
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Preset Data (Hi byte)
Preset Data (Lo byte)

0D
06
00
6F
03
E7

Query Message Response Message


Response Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Preset Data (Hi byte)
Preset Data (Lo byte)

0D
06
00
6F
03
E7

(2-13)Example of Function Code - 6 Message

www.plcworld.cn

Function Code-15 DO Address Function Code-2

Device Address 17 Relay Address 10011 10022 D0


Start Address 10 12
Force Data byte
Bit
0
1
0
1
0
1
0
1
Relay
18 17 16 15 14 13 12 11
Force Data byte
Bit
0
0
0
0
0
0
1
1
Relay
22 21 20 19
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of relay (Hi byte)
No. of relay (Lo byte)
Byte Count
Force Data (Relay 18 11)
Force Data (Relay 22 19)

11
0F
00
0A
00
0C
02
55
03

Query Message 6 bytes Response Message


Response Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of relay (Hi byte)
No. of relay (Lo byte)

11
0F
00
12
00
03

(2-14)Example of Function Code - 15 Message

www.plcworld.cn

Function Code-16 AO Address Function Code-3

Device Address 39 Register Address 40310 40312 A0


Start Address 309 3
register 16 bits
Register 40310 784
Register 40311 12706
Register 40312 16183
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of registers (Hi byte)
No. of register (Lo byte)
Byte count
Data-1 (Hi byte)
Data-1 (Lo byte)
Data-2 (Hi byte)
Data-2 (Lo byte)
Data-3 (Hi byte)
Data-3 (Lo byte)

27
10
01
35
00
03
06
03
10
31
A2
C0
C9

Query Message 6 bytes Response Message


Response Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
No. of registers (Hi byte)
No. of register (Lo byte)

27
10
01
35
00
03

(2-15)Example of Function Code - 16 Message

www.plcworld.cn

Function Code-20 General Reference Register Extended Memory


File Register 10 File File No. 1 - 10
File Address 600000 Register
Register Address
600000 Protocol offset 0 Holding
Regsiter 40001 Protocol offset
0 Function Code Group
Address
Device Address 17 Group Register
Group 1 File 4 Address offset 1 2 Register
Group 2 File 3 Address offset 9 2 Register
Query Message
Device Address
Function Code
Byte Count
Group-1 Reference Type
Group-1 File No. (Hi byte)
Group-1 File No. (Lo byte)
Group-1 Start Addr. (Hi byte)
Group-1 Start Addr.(Lo byte)
Group-1 Registers Count (Hi
byte)
Group-1 Registers Count (Lo
byte)
Group-2 Reference Type
Group-2 File No. (Hi byte)
Group-2 File No. (Lo byte)
Group-2 Start Addr. (Hi byte)
Group-2 Start Addr.(Lo byte)
Group-2 Registers Count (Hi
byte)
Group-2 Registers Count (Lo
byte)

11
14
0E
06
00
04
00
01
00
02
06
00
03
00
09
00
02

www.plcworld.cn

Response Message
Response Message
Device Address
Function Code
Byte Count
Group-1 Byte Count
Group-1 Reference Type
Group-1 Data-1 (Hi byte)
Group-1 Data-1 (Lo byte)
Group-1 Data-2 (Hi byte)
Group-1 Data-2 (Lo byte)
Group-2 Byte Count
Group-2 Reference Type
Group-2 Data-1 (Hi byte)
Group-2 Data-1 (Lo byte)
Group-2 Data-2 (Hi byte)
Group-2 Data-2 (Lo byte)

11
14
0C
05
06
0D
FE
00
20
05
06
33
CD
00
40

(2-16)Example of Function Code - 20 Message

www.plcworld.cn

Function Code-21 General Reference RegisterAddress Function


Code-20
Device Address 17 Group Register
Group 1 File 4 Address offset 7 3 Register
Register 600007 1711
Register 600008 1214
Register 600009 4109
Query Message
Device Address
Function Code
Byte Count
Group-1 Reference Type
Group-1 File No. (Hi byte)
Group-1 File No. (Lo byte)
Group-1 Start Address (Hi byte)
Group-1 Start Address (Lo byte)
Group-1 Registers Count (Hi
byte)
Group-1 Registers Count (Lo
byte)
Group-1 Data-1 (Hi byte)
Group-1 Data-1 (Lo byte)
Group-1 Data-2 (Hi byte)
Group-1 Data-2 (Lo byte)
Group-1 Data-3 (Hi byte)
Group-1 Data-3 (Lo byte)

11
15
0D
06
00
04
00
07
00
03
06
AF
04
BE
10
0D

Query Message bytes Response Message

(2-17)Example of Function Code - 21 Message

www.plcworld.cn

1.4 Exception Code


Exception Code
Slave Error Code Master
Message
Device Address 13 Register Address 42450 A0
Start Address 2449 16 bits 999 0x03E7
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Preset Data (Hi byte)
Preset Data (Lo byte)

0D
06
09
91
03
E7

Modbus Register Address42048


Error Code2ILLEGAL DATA ADDRESS Function
Code Bit 1 FunctionException Code
Response Message

Device Address
0D
Function Code
86
Error Code
02
(2-18)Exception Message format

Exception Code Function Code Bit


1 Error code
Error Code

1
ILLEGAL FUNCTION
Function Code Slave Function Code Slave
Function
2
ILLEGAL DATA ADDRESS
Address Start Address
Address
3
ILLEGAL DATA VALUE
Slave Function Code-6
Coil ON OFF Value ON: 0xFF00OFF: 0x0000

www.plcworld.cn

4
5

9
10

11

SLAVE DEVICE FAILURE


Slave Function Code
ACKNOWLEDGE
Slave Function Code Master
Response Message Code
Master Polling Program Function Code
SLAVE DEVICE BUSY
Slave Function Code
Error Code Master Query Message
NEGATIVE ACKNOWLEDGE
Function Code-1314 Slave Error
code Slave Slave diagnostic
MEMORY PARITY ERROR
Function Code-2021 extension memory memory
parity Error Code

GATEWAY PATH UNAVAILABLE


Gateway Gateway input port
output port Gateway
configuration
GATEWAY TARGET DEVICE
FAILED TO RESPOND
Gateway Master Query Message Slave
Error code Slave
Slave

(2-19)Exception Code

2.1 Device Address


Device Address Modbus Device
Modbus Device
Modbus Message ASCII 2 bytes RTU 1 byte (8
bits) 0 - 247 1- 247 Modbus Device 0
broadcast Slave Device
broadcast Modbus Device
Device Address

2.2 RTU ASCII

www.plcworld.cn

RTU
Message

ASCII
2
ASCII Code RTU


Message Message
3.5
Message
Device

Message

1 start bit
1 start bit
8 data bits, least significant bit send first
7 data bits, least significant bit send first
1 bit for parity check
1 bit for parity check
1 stop bit if parity is used; 2 bits if no parity 1 stop bit if parity is used; 2 bits if no parity

(2-20)RTU and ASCII format

2.3 CRC LRC check


Message Message
CRC LRC
Message Message

Bit 1 0
Message
z CRC checkRTU CRC Cyclical Redundancy Check
16 bits
1. 0xFFFF unsigned short
CRC Register
2. Message 8 bits byte CRC Register low byte Exclusive
OR CRC Register low byte
3. CRC Register 1 bitLSB bit 0MSB

4. LSB bit 0 3 1 CRC


Register 0xA001 Exclusive OR
5. 34 byte 8 bits
6. Message 8 bits byte 16 bits
Low byte and High byte Message

www.plcworld.cn

7. Low byte and High byte Message High byte and


Low byte
Query Message
Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Preset Data (Hi byte)
Preset Data (Lo byte)
CRC Check (Lo Byte)
CRC Check (Hi Byte)

0D
06
09
91
03
E7

RTU

0000 1101
0000 0110
0000 1001
1001 0001
0000 0011
1110 0111
1001 1011
1100 1101

(2-21)CRC

z LRC check ASCII LRC Longitudinal Redundancy


Check Message
<CR><LF>

8 bit carries 8 bits


1
ASCII Message
Query Message

Device Address
Function Code
Start Address (Hi byte)
Start Address (Lo byte)
Preset Data (Hi byte)
Preset Data (Lo byte)
LRC Check 1
LRC Check 2
1

(2-22)LRC

0D
06
09
91
03
E7

ASCII
Code

0D
06
09
91
03
E7
6
9
<CR>

0x0D
<LF>

0x0A

www.plcworld.cn

3 TCP/IP
Modbus/TCP 1.2.
IP Address Modbus Address Slave
Master
3.1 IP Address Modbus Address
Ethernet IP Address
Modbus Address
IP Address Modbus Address
Modbus/TCP Modbus Address
Modbus/TCP

3.2 Modbus Slave Master


Modbus Master
Modbus SlaveModbus Master
Query MessageSlaveResponse Message
EthernetModbus Master
Modbus SlaveSlave
Modbus/TCP SlaveMaster

www.plcworld.cn

C++Builder Modbus
Windows Modbus
Borland C++ Builder V5.0 Sample Porgram
source program
API
Multi-Thread C
1 DLL
Modbus RS232C
LRCCRC C
DLL C++ VB

MB_SUB.DLL Windows
1.1 RS232C
Subroutine Name BOOL seropen( int nPort, int nBaud, char parity, int
data_bit, int stop_bit, int flow)
Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
Open COM port
Parameter int nPort open port no.COM1 port=1

int Baud baud rate 12002400115200

char parityN:NoneOOddEEven
int data_bit: bits 7 or 8
int stop_bit: stop bits1 or 2
int flow: flow control0:1
Return Code truefalse
1open COM port
2 CreateFile()GetCommState()SetCommState()
GetCommTimeouts()SetCommTimeouts() RS232C
Windows System API
int port, baud, parity, data_bit, stop_bit, flow;
BOOL rc;
port=1; //COM1 port
baud= 19200; parity=N; data_bit=8; stop_bit=1;
flow= 0;
rc= seropen(port, baud, parity, data_bit, stop_bit,
flow);

www.plcworld.cn

Subroutine Name BOOL serclose( int nPort)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
Open COM port
Parameter int nPort close port no.COM1 port=1
Return Code True
false
1close COM port
2 CloseHandle() Windows System API
int port, baud, parity, data_bit, stop_bit, flow;
BOOL rc;
port=1; //COM1 port
rc= serclose(port);

Subroutine Name int serwrite(int nPort, char *data, int len)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port n bytes data
parameter int nPort port no.COM1 port=1

char *data data buffer area


int len: data byte
Return Code data byte
1 data COM port
2 WriteFile () Windows System API
int port, len, rc;
char buff[80];
port=1; //COM1 port
len= 10;
strcpy(buff, ABCDEFGHIJ);
rc= serwrite(port, buff, len);

www.plcworld.cn

Subroutine Name BOOL sersend(int nPort, char Byte)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port byte data
parameter int nPort port no.COM1 port=1

char Byte byte data


Return Code True
false
1 byte COM port
2 WriteFile () Windows System API
int port;
BOOL rc;
char data;
port=1; //COM1 port
data= A;
rc= sersend(port, data);

Subroutine Name short serrecv(int nPort)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port byte data
parameter int nPort port no.COM1 port=1

Return Code 1 byte data


-1 byte data
1 data COM port
2 ReadFile () Windows System API
int port;
short ch;
port=1; //COM1 port
ch= serrecv(port);

www.plcworld.cn

Subroutine Name int serread(int nPort, void *buffer, int limit )


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port n bytes data
Parameter int nPort COM port dataCOM1
port=1
void buffer: data buffer area
int limit
Return Code 0 byte data
>0 byte data
1 data COM port
2 ReadFile () Windows System API
int port, limit, rc;
char buff[80];
port=1; //COM1 port
limit= 80;
rc= serread(port, buff, limit);

Subroutine Name void serflush(int nPort)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port buffer area
parameter int nPort port no.COM1 port=1

Return Code
1 PurgeComm () Windows System API
int port;
port=1; //COM1 port
ch= serrecv(port);

www.plcworld.cn

Subroutine Name int serloc(int nPort)


Source Name RS232_SUB.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
COM port buffer byte data

Parameter int nPort port no.COM1 port=1

Return Code buffer byte data


1 ClearCommError () Windows System API
int port;
int len;
port=1; //COM1 port
len= serloc(port);

1.2 LRC CRC Check


Subroutine Name void LRC_check(buff, len, chk)
Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
LRC ckeck code2 ASCII code
Parameter unsigned char *buff
int len:
unsigned char *chk
Return Code
1 2.3
unsigned char buff[80], chk[2];
int len;
// buff
LRC_check(buff, len, chk);

www.plcworld.cn

Subroutine Name void CRC_check(buff, len, chk)


Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
CRC ckeck code2 bytes(8 bits) code
Parameter unsigned char *buff
int len:
unsigned char *chk
Return Code
1 2.3
unsigned char buff[80], chk[2];
int len;
// buff
CRC_check(buff, len, chk);

Subroutine Name void CRC_calc(c, crc)


Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
CRC byte CRC_check
Parameter unsigned char c
unsigned short *crcCRC
Return Code
1 2.3

www.plcworld.cn

1.3
Subroutine Name int tsleep(interval)
Source Name winsys.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0

para. long interval, millsecond.
Return Code -1
0
1 Windows System API Sleep()
2 interval return

long interval;
interval=20000; // 20
tsleep(interval);

Subroutine Name int get_date_time(year, month, day, hour, minute, second,


msec, week)
Source Name winsys.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0

para. short
short
short
short
short
short
short
short

*year(4 )
*month
*day
*hour
*minute
*second
*msecmilliseconds
*week

Return Code -1
0
1 Windows System API GetLocalTime()
short year, month, day, hour, minute, second, msec, week;
get_date_time(&year, &month, &day, &hour, &minute,
&second, &msec, &week);

www.plcworld.cn

Subroutine Name int set_date_time(year, month, day, hour, minute, second)


Source Name winsys.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0

para. short
short
short
short
short
short

year(4 )
month
day
hour
minute
second

Return Code -1
0
1 Windows System API SetLocalTime()

short year, month, day, hour, minute, second;


year=1997; month=12; day=30;
hour=8; minute=59; second=0;
set_date_time(year, month, day, hour, minute, second);

www.plcworld.cn

Subroutine Name itascxr(data, n, buf)


Source Name Error_check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
16 bits Hex.ASCII code

Parameter unsigned short data


short n HEX
char buf[] HEX Buffer
Return Code 0
-1 n
1 16 bits HEX
2 buf[]
3 *
4 N > data HEX
N N ASCII Code 0

unsigned short data;


short n;
char buff[10];
data= 1234;
n= 4;
itascxr(data, n, buff);
// buff 4D2 buff[0]
ASCII Code
data= 1234;
n= -4;
itascxr(data, n, buff);
// buff 04D2 buff[0] 0
ASCII Code

www.plcworld.cn

Subroutine Name ascxti(buf, n, data)


Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
ASCII Code 16 bits
para. char buf[] HEX
short n HEX
unsigned short *data 16 bits
Return Code 0
-1 ASCII Code
-2Overflow
1 HEX 16 bits
unsigned short data;
short n, rc;
char buff[10];
strcpy(buff, 012A, 4);
n=4;
ascxti(buff, n, &data);
// data 298 ()
strcpy(buff, ST34, 4);
n=4;
rc= ascxti(buff, 4, &data);
// ASCII Code rc
-1

www.plcworld.cn

Subroutine Name bitrd(data, top, end)


Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
data bit
para. unsigned short *data bit
short top Bit No.(0 -15, )
short end Bit No.(0 -15, )
Return Code
1 top end Bit
data=0x01F0;
I=bitrd(&data, 1, 5);
i=24

www.plcworld.cn

Subroutine Name bitwt(data1, top, end, data2)


Source Name Error_Check.c
Library Name MB_SUB.LIBMB_SUB.DLLMB_SUB.h
C++ Builder V5.0
data1 bit
para. unsigned short *data1 bit
short top Bit No.(0 -15, )
short end Bit No.(0 -15, )
short data2
Return Code
1 data1 top end Bit data2

www.plcworld.cn

Borland C++Builder 5.0 Modbus


2.1 Utility
Utility Modbus Master Slave
PC RTUASCIITCP Modbus
Slave Modicon PLCModbus .
Slave Server Modbus Master Driver
Modbus Relay/Register Modbus
Modbus
z Modbus Master 1234 Function Code
Relay Register 56 Function Code
Relay Register
z Modbus Slave 1234561516 Function
Code Output CoilInput RelayHolding RegisterInput
Register
z Modbus Slave

Output Coil 1024


Input Relay 1024
Holding Register 1024
Input Register 1024
z Modbus Master/Slave Modbus RTU ASCII
Modbus/TCP
z Master RTUMaster ASCIIMaster TCPSlave RTU
Slave ASCIISlave TCP Modbus
Multi-Document

z Message

www.plcworld.cn

(3-1)Utility

Menu
z [Master][Master RTU] Modbus Master RTU type
z [Master][Master ASCII] Modbus Master ASCII type
z [Master][Master TCP] Modbus/TCP Master type
z [Master][Exit]Utility
z [Slave][Slave RTU] Modbus Slave RTU type
z [Slave][Slave ASCII] Modbus Slave ASCII type
z [Slave][Slave TCP] Modbus/TCP Slave type
z [Windows][Cascade] Multi-Document
z [Windows][Tite Horizontally] Multi-Document

z [Windows][Tite Vertically] Multi-Document

z [About]

www.plcworld.cn

(3-2)Multi-Document

(3-3)Master RTU

www.plcworld.cn

Master RTU
z [Port Define] Button RS232C baud
rateparitydata bitsstop bits COM Port
Button
z [Open] ButtonOpen COM Port
z [Close] ButtonClose COM Port
z Function Code Output CoilInput RelayHolding RegisterInput
Register
z Modbus Device Address Modbus Slave Address
1 247
z Register/Relay Address 1 9999

z Communication Words/BitsRegister 120


wordsRelay 1920 bits
z [Send command] Button Modbus Query Command
Button Query Message

z [Set data value] Button Query Message


Mouse Button
Set Data valueDialog Box
Query Command Modbus Slave
Device Mouse Double click

(3-4) (Relay )

www.plcworld.cn

(3-5) (Register ) Decimal Hex.

(3-6)Master RTU (Relay )

www.plcworld.cn

(3-7)Master RTU (Register )

(3-8)RS232C

z COM Port COM Port COM1 COM8

www.plcworld.cn

z
z
z
z
z

Baud Rate1200240048009600192003840057600115200

ParityNoneOddEven
Data Bit78
Stop Bit12
Used COM Port COM Port

(3-9)Master ASCII

Master ASCII Master RTU

z Communication Words/BitsRegister 60
wordsRelay 960 bitsModbus Message
256 bytes Message Header
240 bytes

www.plcworld.cn

(3-10)Master TCP

Master TCP Master TCP


COM Port TCP/IP Port
z [Open] ButtonConnect Remote Modbus Slave Server
z [Close] ButtonDisconnect Remote Modbus Slave Server
z IP AddressRemote Modbus Slave Server IP Address
z Port No.Remote Modbus Slave Server TCP Port No. 502
z Modbus Device Address Modbus Slave Address
1 247
z Register/Relay Address 1 9999

z Communication Words/BitsRegister 120


wordsRelay 1920 bits

www.plcworld.cn

(3-11)Slave RTU

Slave Server RTU


z [Port Define] Button RS232C baud
rateparitydata bitsstop bits COM Port
Button
z [Open Server] ButtonOpen COM Port Query Message

z [Close Server] ButtonClose COM Port Query


Message
z Output CoilInput RelayHodling Register
Input Register Page Mouse
Double click Set Relay/Register
ValueDialog Box
z Modbus Master Driver Slave Server
Response Message
Modbus Device

www.plcworld.cn

(3-12)Slave Server (Relay )

(3-13)Slave Server (Relay ) Decimal Hex.

www.plcworld.cn

(3-14)Slave ASCII

Slave Server ASCII Slave


Server RTU

www.plcworld.cn

(3-15)Slave TCP

Slave Server TCP Slave Server


RTU Open/Close TCP/IP Port COM Port
RS232C Modbus Slave
Modbus Address IP Address
RS232C time out errorTCP connect error rtc=10060

2.2 Utility
Utility
Modbus

PC Modbus_Tool

PC Modbus_Tool

Master RTU

Slave RTU

Master ASCII PC

Slave ASCII PC

Slave Server
Modbus Device

(3-16)Utility

Open Port

PC-1 Master RTU[Port Define] Button


COM1 19200 N 8 1
PC-1 Master ASCII[Port Define]

Button COM2 9600 O 7 1


PC-2 Slave RTU[Port Define] Button
COM1 19200 N 8 1
PC-2 Slave RTU[Port Define] Button
COM2 9600 O 7 1
PC-1 Master RTU and Master ASCII [Close] Button
[Open] Button

www.plcworld.cn

PC-2 Master RTU and Master ASCII


[Open] Button
SlavePC PC-2 Slave RTU and Slave ASCII
Relay/Register

Master
Master PC-1 Master RTU Function Code PC-1 Query Message

Modbus deviceRelay/Register Addressand Response Message


Communication Words/Bits
[Send command] Button PC-2 Slave RTU
Query Message and Response

Relay/Register Slave

0
PC-1 Master ASCII Function Code PC-1 Query Message
Modbus device Relay/Register and Response Message
AddressCommunication Words/Bits
[Send command] Button PC-2 Slave ASCII
Query Message and Response

Relay/Register Slave

0
Master PC-1 Master RTU PC-1 Query Message

Mouse and Response Message


[Set data value]
PC-2 Slave RTU
[OK]
Query Message and Response

PC-1 Master ASCII PC-1 Query Message


Mouse and Response Message
[Set data value]
PC-2 Slave ASCII
[OK]
Query Message and Response

PC [Port Define] Baud rate PC-1 time out error


Master PC-2

www.plcworld.cn

PC-1
Matser RTU

Modbus Device Address1 247


Relay/Register Address1 9999
Communication Words/Bits
Relay 1920
Register 120
Matser ASCII
Modbus Device Address1 247
Relay/Register Address1 9999
Communication Words/Bits
Relay 960
Register 60
Relay/Register Slave 1024
PC-1 Exception
Address Modbus Message
Slave Device
PC-2

Master
PC-1

Driver Slave PC-1

Super Terminal Program


PC-2 Message
Message

CRC/LRC Check error


RS232C
Modbus/TCP

(3-17)Utility

www.plcworld.cn

2.3 Utility
MB_Sub.DLL

MB_Sub.bpr
Project
MB_Sub.DLL
Modbus Basic Subroutine DLL
MB_Sub.Lib
Modbus Basic Subroutine Link Library
MB_Sub.h
Modbus Basic Subroutine Defined Header
RS232_Sub.cpp
COM Port
Error_Check.cpp
Modbus Protocol
Winsys.cpp
Windows API
Modbus_Tool Utility

Modbus_Tool.bpr
Project
Modbus_MAIN.cpp

MB_Sub.DLL
Modbus Basic Subroutine DLL
MB_Sub.Lib
Modbus Basic Subroutine Link Library
MB_Sub.h
Modbus Basic Subroutine Defined Header
Port_Def.cpp

Master_RTU.cpp
Modbus Matser RTU
Master_ASCII.cpp
Modbus Master ASCII
Master_TCP.cpp
Modbus/TCP Master
Slave_RTU.cpp
Modbus Slave RTU
Slave_ASCII.cpp
Modbus Slave ASCII
Slave_TCP.cpp
Modbus/TCP Slave
Set_Data.cpp
Relay Register
Set_Value.cpp
Slave Server Relay
Register
STD_SUB.cpp

STD_SUB.h

About.cpp
About Dialog Box
(3-18)C++ Utility

www.plcworld.cn

Modbus_Tool
Menu

Master_RTU

Master_ASCII

Master_TCP

Multi-Documents Form

Multi-Documents Form

Multi-Documents Form

Timer1

Timer1

Socket

Timer1 RTU

Timer1 ASCII

Socket Event

Response Message

Response Message

Response Message

STD_SUB.cpp

Slave_RTU

Slave_ASCII

Slave_TCP

Multi-Documents Form

Multi-Documents Form

Multi-Documents Form

Open port Timer1

Open port Timer1

Open TCP/IP

Query

Query

Event Query

Message

Message

Message

Relay/Register

Relay/Register

Relay/Register

Response

Response

Response

Timer1

Timer1

Event

STD_SUB.cpp

www.plcworld.cn

(3-19)C++ Utility

z
Master RTU Master ASCII COM Port Query
Message Timer 5 msec Response Message

Master TCP Cbuilder Client Socket


z
Event
Driven Query Message
Event Response Message
Slave RTU Slave ASCII Timer 5 msec
z
Query Message
Response Message Timer

Slave TCP Cbuilder Server Socket


z
Event
Driven Modbus Master

6 Multi-Document
z

Header File Class RS232 IP


AddressSlave Server Relay/Register
z

z
Query Message Response
Message RelayRegister CRC
LRC MB_SUB.DLL

z RS232C RS232C
MB_SUB.DLL Query Message serwrite()
Response Message

PC Based
Controller

www.plcworld.cn

www.plcworld.cn

RTU Query Message Timer


Response Message

Timer 5msec

timer

Byte

byte

byte
timer

Byte

byte

Byte

Timer

byte
Response Messager
Memo

CRC

CRC Code

CRC
CRC code error
Memo

Response Messager
Relay
Register

Timer
Timer1->Enabled= false;

(3-20)Master RTU Response Message

www.plcworld.cn

void __fastcall TSerial_Form::Timer1Timer(TObject *Sender)


{
// RTU receive
int i;
short ch, old_nsec, tt;
unsigned short data;
char buff[40];
unsigned char crc[4];
AnsiString s;
// control RTU format
get_date_time(&YEAR, &MONTH, &DAY, &HOUR, &MINUTE, &SECOND,
&NSEC, &WEEK);
switch(STEP)
{
case 0:
CNT=0;
memset(INBUFF, 0, sizeof(INBUFF));
STEP=10;
TMCNT=0;
break;
case 10:
ch= serrecv(MB_PORT);
if(ch != -1)
{
CNT=0;
INBUFF[CNT++]=ch;
STEP=20;
OLD_NSEC= SECOND*100 + NSEC/10;
}
else
{
TMCNT++;
if(TMCNT >=100)
STEP= 990;
else return;
}
break;
case 20:
ch= serrecv(MB_PORT);
if(ch != -1)
{
INBUFF[CNT++]=ch;
OLD_NSEC= SECOND*100 + NSEC/10;
}
else
{
old_nsec= SECOND * 100 + NSEC/10;
tt= old_nsec - OLD_NSEC;
if( tt <0) tt= tt + 6000;
if( tt >= (MB_RTU_TIME/10) ) STEP= 30;
else STEP= 20;
}
break;
case 30:
s= "Response Message: ";
memset(buff, 0, sizeof(buff));
buff[2]= ' '; // space code
for(i=0; i<CNT; i++)

www.plcworld.cn

{
data= INBUFF[i];
itascxr(data, -2, buff);
s= s+ buff;
}
Memo2->Lines->Clear();
Memo2->Lines->Add(s);
CRC_check(&INBUFF[0], CNT-2, crc);
if(INBUFF[CNT-2]==crc[0] && INBUFF[CNT-1]==crc[1])
{
MB_LEN= CNT;
display_RTU_Response(StringGrid1, INBUFF, MB_LEN,
MB_WORDS, MB_SET_ROW, MB_SET_COL, MB_SET_VALUE);
}
else
{
sprintf(buff, "CRC error: Recv[%d %d] Calc[%d %d]",
INBUFF[CNT-2], INBUFF[CNT-1], crc[0], crc[1]);
Memo2->Lines->Add(buff);
}
STEP= 1000;
break;
case 990:
Timer1->Enabled= false;
serclose(MB_PORT);
Memo2->Lines->Add("Time out error");
MessageBox(NULL, "RS232C comm. time out error", "MBMaster_A",
MB_OK);
STEP=0;
break;
case 1000:
Timer1->Enabled= false;
serclose(MB_PORT);
STEP= 0;
// to set data value enabled or not
if(MB_FUN==0 || MB_FUN==2) // to set data
{
StringGrid1->ShowHint= true;
BitBtn2->Enabled= true;
}
else
{
StringGrid1->ShowHint= false;
BitBtn2->Enabled= false;
}
// set StringGrid selected cells
if(MB_FUN==0 || MB_FUN==1) // relay
{
StringGrid1->Row=1;
StringGrid1->Col=8;
}
else
{
StringGrid1->Row=1;
StringGrid1->Col=1;
}
StringGrid1->SetFocus();
return;
}
}

www.plcworld.cn

ASCII Query Message


Timer
Response Message

Timer 10msec

timer

Start code :

:
:

timer

End code <CR><LF>

Timer

< CR><LF>
Response Messager
Memo

LRC

LRC Code

LRC
LRC code error Memo

Response Messager
RelayRegister

Timer
Timer1->Enabled= false;

(3-21)Master ASCII Response Message

www.plcworld.cn

void __fastcall TSerial_Form::Timer2Timer(TObject *Sender)


{
// ASCII receive
int i;
short ch;
char buff[80], lrc[4];
AnsiString s;
// control ASCII format
get_date_time(&YEAR, &MONTH, &DAY, &HOUR, &MINUTE, &SECOND,
&NSEC, &WEEK);
switch(STEP)
{
case 0:
CNT=0;
memset(INBUFF, 0, sizeof(INBUFF));
STEP=10;
TMCNT=0;
break;
case 10:
ch= serrecv(MB_PORT);
if(ch != -1)
{
if(ch==':')
{ CNT=0;
INBUFF[CNT++]=ch; STEP= 20; }
else STEP=10;
}
else
{
TMCNT++;
if(TMCNT >=100)
STEP= 990;
else return;
}
break;
case 20:
ch= serrecv(MB_PORT);
if(ch != -1)
{
INBUFF[CNT++]=ch;
if( ch == 0x0A) STEP=30;
}
else
{
TMCNT++;
if(TMCNT >=100)
STEP= 990;
else return;
}
break;
case 30:
s= "Response Message: ";
for(i=0; i<CNT; i++)
{
sprintf(buff, "%02X ", INBUFF[i]);
s= s+ (char *)buff;

www.plcworld.cn

}
Memo2->Lines->Clear();
Memo2->Lines->Add(s);
LRC_check(&INBUFF[1], CNT-5, lrc);
if(INBUFF[CNT-4]==lrc[0] && INBUFF[CNT-3]==lrc[1])
{
MB_LEN= CNT;
display_ASCII_Response(StringGrid1, INBUFF, MB_LEN,
MB_WORDS, MB_SET_ROW, MB_SET_COL, MB_SET_VALUE);
}
else
{
sprintf(buff, "LRC error: Recv[%d %d] Calc[%d %d]",
INBUFF[CNT-4], INBUFF[CNT-3], lrc[0], lrc[1]);
Memo2->Lines->Add(buff);
}
STEP= 1000;
break;
case 990:
Timer2->Enabled= false;
serclose(MB_PORT);
Memo2->Lines->Add("Time out error");
MessageBox(NULL, "RS232C comm. time out error", "MBMaster_A",
MB_OK);
STEP=0;
break;
case 1000:
Timer2->Enabled= false;
serclose(MB_PORT);
STEP= 0;
// to set data value enabled or not
if(MB_FUN==0 || MB_FUN==2)
{
StringGrid1->ShowHint= true;
BitBtn2->Enabled= true;
}
else
{
StringGrid1->ShowHint= false;
BitBtn2->Enabled= false;
}
// set StringGrid selected cells
if(MB_FUN==0 || MB_FUN==1) // relay
{
StringGrid1->Row=1;
StringGrid1->Col=8;
}
else
{
StringGrid1->Row=1;
StringGrid1->Col=1;
}
StringGrid1->SetFocus();
return;
}
}

www.plcworld.cn

ClientSocket()->Host= IP_Address
ClientSocket()->Port= IP_Port_No
CleintSocket()->Open();
Client connect

OnConnet Event connect

OnError Event connect

ClientSocket()->Socket->SendBuf();

Query Message

Windows Event

OnRead Event Response

OnDisconnect Event

Message RelayRegister

(3-22)Master TCP Client Socket

//--------------------------------------------------------------------------void __fastcall TMSTCP_Form::BitBtn1Click(TObject *Sender)


{
// send command
unsigned short value, data;
int i, rc;
AnsiString s;
char buff[128];
if(BitBtn4->Enabled== false)
{
MessageBox(NULL, "TCP Port is not open yet !!!!!",
MODBUS_TOOL, MB_OK);
return;
}
if( get_para() != 0) return;
value= 0;
MB_LEN= 0;
StringGrid1->ShowHint= false;
BitBtn2->Enabled= false;
memset(OUTBUFF, 0, sizeof(OUTBUFF));
rc= prepare_TCP_Query(MB_FUN+1, MB_ID, MB_ADDR, MB_WORDS,
value, &MB_LEN, OUTBUFF);
if(rc != 0)
{
MessageBox(NULL, "Prepare Modbus/TCP Query Message error !!!",

www.plcworld.cn

MODBUS_TOOL, MB_OK);
return;
}
s= "Query message: ";
memset(buff, 0, sizeof(buff));
buff[2]= ' '; // space code
for(i=0; i<MB_LEN; i++)
{
data= OUTBUFF[i];
itascxr(data, -2, buff);
s= s + buff;
}
Memo1->Lines->Clear();
Memo1->Lines->Add(s);
ClientSocket1->Socket->SendBuf(OUTBUFF, MB_LEN);
}
//--------------------------------------------------------------------------void __fastcall TMSTCP_Form::ClientSocket1Connect(TObject *Sender,
TCustomWinSocket *Socket)
{
AnsiString s;
s= Socket->RemoteHost ;
s= "Connect To: " + s;
s= s + " OK";
display_status_message(s);
BitBtn3->Enabled= false;
BitBtn4->Enabled= true;
}
//--------------------------------------------------------------------------void __fastcall TMSTCP_Form::ClientSocket1Disconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
AnsiString s;
s= "Disconnect OK ";
display_status_message(s);
BitBtn3->Enabled= true;
BitBtn4->Enabled= false;
ClientSocket1->Host= "";
ClientSocket1->Port= 0;
}
//--------------------------------------------------------------------------void __fastcall TMSTCP_Form::ClientSocket1Error(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
char buff[80];
AnsiString s;
sprintf(buff, "TCP connect error rtc=%d", ErrorCode);
s= buff;
display_status_message(s);
BitBtn3->Enabled= true;
BitBtn4->Enabled= false;
ClientSocket1->Close();
ClientSocket1->Host= "";
ClientSocket1->Port= 0;
MessageBox(NULL, s.c_str(), MODBUS_TOOL, MB_OK);
}
//---------------------------------------------------------------------------

www.plcworld.cn

void __fastcall TMSTCP_Form::ClientSocket1Read(TObject *Sender,


TCustomWinSocket *Socket)
{
int i, len;
AnsiString s;
char buff[128];
unsigned short data;
len= 256;
MB_LEN= ClientSocket1->Socket->ReceiveBuf(INBUFF, len);
sprintf(buff, "Receive data length= %d", MB_LEN);
s= buff;
display_status_message(s);
s= "Response message: ";
memset(buff, 0, sizeof(buff));
buff[2]= ' '; // space code
for(i=0; i<MB_LEN; i++)
{
data= INBUFF[i];
itascxr(data, -2, buff);
s= s + buff;
}
Memo2->Lines->Clear();
Memo2->Lines->Add(s);
display_TCP_Response(StringGrid1, INBUFF, MB_LEN, MB_WORDS,
MB_SET_ROW, MB_SET_COL,
MB_SET_VALUE);
// to set data value enabled or not
if(MB_FUN==0 || MB_FUN==2) // to set data
{
StringGrid1->ShowHint= true;
BitBtn2->Enabled= true;
}
else
{
StringGrid1->ShowHint= false;
BitBtn2->Enabled= false;
}
// set StringGrid selected cells
if(MB_FUN==0 || MB_FUN==1) // relay
{
StringGrid1->Row=1;
StringGrid1->Col=8;
}
else
{
StringGrid1->Row=1;
StringGrid1->Col=1;
}
}

www.plcworld.cn

[Open] Button open COM


Port Timer Query
Message

Timer 5msec

Byte
Timer
Byte
byte
byte
timer

Byte

byte

Byte

Timer

byte
Query Messager
Memo

CRC

CRC Code

CRC
CRC code error
Memo

Response Messager

Timer

(3-23)Slave RTU Query Message

www.plcworld.cn

void __fastcall TSLRTU_Form::Timer1Timer(TObject *Sender)


{
//
int i;
short ch, old_nsec, tt;
char buff[40];
AnsiString s;
// control RTU format
while(1)
{
get_date_time(&YEAR, &MONTH, &DAY, &HOUR, &MINUTE, &SECOND,
&NSEC, &WEEK);
switch(STEP)
{
case 0:
CNT=0;
memset(inbuff_RTU, 0, sizeof(inbuff_RTU));
memset(outbuff_RTU, 0, sizeof(outbuff_RTU));
STEP=10;
TMCNT=0;
break;
case 10:
ch= serrecv(MB_PORT);
if(ch != -1)
{
CNT=0;
inbuff_RTU[CNT++]=ch;
STEP=20;
OLD_NSEC= SECOND*100 + NSEC/10;
}
else return;
break;
case 20:
ch= serrecv(MB_PORT);
if(ch != -1)
{
inbuff_RTU[CNT++]=ch;
OLD_NSEC= SECOND*100 + NSEC/10;
}
else
{
old_nsec= SECOND * 100 + NSEC/10;
tt= old_nsec - OLD_NSEC;
if( tt <0) tt= tt + 6000;
if( tt >= (MB_RTU_TIME/10) ) STEP= 30;
else STEP= 20;
}
break;
case 30:
RTU_response();
STEP= 1000;
break;
case 990:
Memo1->Lines->Add("Time out error");
STEP=0;
break;
case 1000:

www.plcworld.cn

//

STEP= 0;
return;
break;

}
} // while()
}

www.plcworld.cn

[Open] Button open COM


Port Timer Query
Message

Timer 5msec
Byte

Timer
Start code :
:

:
timer

End code <CR><LF>

Timer

< CR><LF>
Query Messager Memo

LRC

LRC Code

LRC
LRC code error Memo

Response Messager

Timer

(3-24)Slave ASCII Query Message

www.plcworld.cn

void __fastcall TSLASC_Form::Timer1Timer(TObject *Sender)


{
//
int i;
short ch;
char buff[40];
AnsiString s;
// control ASCII format
while(1)
{
get_date_time(&YEAR, &MONTH, &DAY, &HOUR, &MINUTE, &SECOND,
&NSEC, &WEEK);
switch(STEP)
{
case 0:
CNT=0;
memset(inbuff_ASC, 0, sizeof(inbuff_ASC));
memset(outbuff_ASC, 0, sizeof(outbuff_ASC));
STEP=10;
TMCNT=3;
break;
case 10:
ch= serrecv(MB_PORT);
if(ch != -1)
{
if(ch==':')
{ CNT=0;
inbuff_ASC[CNT++]=ch;
TMCNT= 3;
OLD_SECOND= MINUTE * 60 + SECOND;
STEP= 20; }
else STEP=10;
}
else return;
break;
case 20:
ch= serrecv(MB_PORT);
if(ch == -1)
{
if( time_out_check(OLD_SECOND, TMCNT)==0 )
{ return; } // during comm.
else
{ // timeout error
STEP= 999; // go back waiting next request message
sprintf(buff, "Mod Slave ASC req. cmd is not finished "
"recv. len=%d", CNT);
Memo1->Lines->Add(buff);
return;
}
}
else if(ch== 0x0a)
{
inbuff_ASC[CNT++]= ch;
STEP= 30;
}
else
{

www.plcworld.cn

//

inbuff_ASC[CNT++]= ch;
}
break;
case 30:
ASC_response();
STEP= 1000;
break;
case 990:
Memo1->Lines->Add("Time out error");
STEP=0;
break;
case 1000:
STEP= 0;
return;
break;

}
} // while()
}

www.plcworld.cn

[Open Server] button


ServerSocket1->Open();
ServerSocket1->Port= 502;
Server accept
Client connect

OnConnet Event client

OnError Event

connect Memo

Memo

Windows Event

OnRead Event Query Message

OnDisconnect Event

RelayRegister

client Memo

(3-25)Slave TCP Query Message

//--------------------------------------------------------------------------void __fastcall TSLTCP_Form::ServerSocket1ClientConnect(TObject *Sender,


TCustomWinSocket *Socket)
{
AnsiString s;
s= Socket->RemoteHost + "Client Connect";
Memo1->Lines->Add(s);
Client= Socket;
// save client Socket pointer
}
//--------------------------------------------------------------------------void __fastcall TSLTCP_Form::ServerSocket1ClientDisconnect(TObject
*Sender,
TCustomWinSocket *Socket)
{
AnsiString s;
s= Socket->RemoteHost + "Client DisConnect";
Memo1->Lines->Add(s);
}
//--------------------------------------------------------------------------void __fastcall TSLTCP_Form::ServerSocket1ClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
char buff[80];
sprintf(buff, "TCP Server Client error rtc=%d", ErrorCode);

www.plcworld.cn

Memo1->Lines->Add(buff);
MessageBox(NULL, buff, MODBUS_TOOL, MB_OK);
}
//--------------------------------------------------------------------------void __fastcall TSLTCP_Form::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
// receive data from client

len= Socket->ReceiveLength();
// Relay/Register response
// Source Porgram

Socket->SendBuf(outbuff_TCP, cnt);
}

www.plcworld.cn

2.4
RS232C Ethernet

Window Socket API

Event Driven
Polling

Buffer

Buffer

buffer

(3-26)

Bug
Bug 24

www.plcworld.cn

A. Utility Modbus Master


Query Message Response Message
Utility Query Message
B. Utility Query Message
Windows API Message
C. Utility
buffer area
D. buffer
KB
1 4 KB Modbus Message
256 bytes buffer
E. buffer
Byte
buffer byte
byte

RS232C Baud Rate Ethernet


Query Message 100 bytes byte 8 bits start bit
stop bitparity bit 1 bit 11 bits / byte
RS232C Baud Rate 9600 bps
100 11/ 9600 0.1145 second
Ethernet Baud Rate 100 Mbps
100 11/100 * 1000000 0.000011 second
F. Utility Query Message Modbus Slave
Response Message
1 3 Message

G. Response Message Event Driven


Polling
H.
Modbus Slave Response Message
byte
byte buffer
I. Event Driven Windows
Message Event
TCP TCP
CRC byte Address

www.plcworld.cn

J.

K.

L.

Event buffer
Polling buffer
byte buffer
RS232C
RS232C

Message CRCLRC Code


Start CodeEnd Code Message

byte byte
byte Message
CRCLRC Code byte

Utility Modbus Slave


Query Message Query Response Message
Modbus Master RS232C Timer
5 msec Polling buffer
Byte RS232C 5 msec
TCP/IP Event Driven
Read Event
Response Message
Polling
mill-second

// old_nsec
// SECONDNSEC PC
old_nsec= SECOND * 1000 + NSEC;
timeout = 200;
// 200 millsecond
//
rc= check_nsec_timeout(old_nsec, timeout);
if( rc == 0) //
else //
int check_nsec_timeout(int old_nsec, int timeout)
{
int tt, new_nsec;
new_nsec = SECOND * 1000 + NSEC; // millsecond

www.plcworld.cn

tt = new_nsec old_nsec;
// new_nsec
// 60000
if( tt < 0) tt = tt + 60000;
if( tt >= timeout) return(-1); //
return(0); //
}
M. second
short time_out_check(short old_t, short timeout)
{
short tm, new_t;
new_t= MINUTE*60 + SECOND; //
tm= new_t - old_t;
// new_t
// 3600
if(tm < 0) tm= tm + 3600;
if(tm >= timeout) return(-1); //
else return(0); //
}

www.plcworld.cn

PC Based Controller Modbus


PC Based Controller
Modbus Slave
Modbus Master Query Message
Response Message ICP 7524 ICP 7188E5
Modbus RTUASCII Modbus/TCP Slave

Modbus RTUASCII Modbus/TCP Master


Modbus device

Sample Program
1 ICP 7524ICP 7188E5
1.1
ICP 7524 COM
Port RS232 RS485 Port

Model Number I-7521/


I-7522/ I-7522A/ I-7523/
I-7524/
I-7527/
7521D
7522D
7522AD
7523D
7524D
7527D
CPU(80188)
20M
20M
40M
20M
40M
40M
SRAM
128K
128K
256K
128K
256K
256K
Flash
256K
256K
256K
256K
512K
512K
COM1 Port
RS232/
RS232/
RS232/
RS232/
RS232/
RS232/
Program
RS485
RS485
RS485
RS485
RS485
RS485
Download
COM2 Port
RS485
RS485
RS485
RS485
RS485
RS485
COM3 Port
RS232
RS422
RS232
RS232
RS232

COM4 Port
RS232
RS232
RS232

COM5 Port
RS232
RS232

COM6 Port

RS232

COM7 Port

RS232

COM8 Port

RS232
1

DO (Digital
Output)
DI (Digital
3
3
5
1
1

Input)
User defined
3

I/O
Y
Y
Y
Real Time

Clock
Embedded O.S. MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7
(4-1)ICP-752X

www.plcworld.cn

Model Number D LED Display


ICP 7188E Ethernet
RS232C Ethernet

Model Number I-7188E1 I-7188E2 I-7188E3 I-7188E3 I-7188E4 I-7188E5 I-7188E8


-232
CPU(80188)
40M
40M
40M
40M
40M
40M
40M
SRAM
256K
256K
256K
256K
256K
256K
256K
Flash

512K

Ethernet Port

512K

512K

512K

512K

512K

512K

10 BaseT 10 BaseT 10 BaseT 10 BaseT 10 BaseT 10 BaseT 10 BaseT

COM1 Port
Program
Download
COM2 Port

RS232

RS232

RS232

RS232

RS232

RS232

RS232

RS485

RS485

RS485

RS485

RS485

RS485

COM3 Port

RS422

RS232

RS232

RS232

RS232

COM4 Port

RS232

RS232

RS232

COM5 Port

RS232

RS232

COM6 Port
COM7 Port

RS232

RS232

COM8 Port

RS232

DO (Digital

Output)
DI (Digital
4
4
4

Input)
RTC
N
N
N
N
N
N
N
Embedded O.S. MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7 MiniOS 7
(4-2)ICP-7188E

1.2
ICP 7524 7188E OS MiniOS 7 OS
DOS DOS
DOS

z RS232C Ethernet Port


MiniOS 7 Library
DOS
z
millsecond millsecond
Real Time Clock

www.plcworld.cn

z
z

OS delay API
millsecond Watchdog timer

DIDO LED DO

DI LED
Flash EEPROM Hard Disk
DOS DOS

C
Borland Turbo C++ 3.0
PC Compiler
ICP 7524 7188XW
Flash Memory
Debug

z PC Based Controller
Power On
24
RS232CEthernet DO

PC Based Controller
I/O
While Loop

z Timing Real Time Control

z
Baud RateParityStop
BitData BitsIP Address
DOS Hard Disk
PC based Controller Flash EEPROM

www.plcworld.cn

24

ICP 7524ICP 7188E


ICP 75247188E MiniOS 7 DOS
ICP 75247188E

2.1 7188XW
MiniOS 7 7188XW
RS232C COM1 Port PC
COM1 Port PC 7188XW

(4-3)7188XW

ICP 75247188E 7524 7188E


Demo Power On
INITGND Power On Demo
7188XW Command
dir Demo Program File List

www.plcworld.cn

2.2 Command
MiniOS 7 Command
Command

Dir

Del

Date

Time

Load
PC
Typefile file
ver
MiniOS 7
Ip
Ethernet IP Address

(4-4)7188XW Command

2.3 BC 3.0 Project


Borland Tubor C++ 3.0BC 3.0
BC 3.0
Complier and Link Project
BC 3.0

DEMO7524.C
7188XBL.LIBICP 7524 Library

(4-5)BC 3.0 Compiler

Project Library
Project C Small Model Large Model

www.plcworld.cn

640KB 64KB
ICP 75247188E SRAM 256KB
256KB Complier and Link 2.5.

2.4 MiniOS 7 Library


MiniOS 7 Library

COM Port
RS232422485 API
LED
LED API
Memory
EEPROM Flash Memory API
Timer
Timer OpenCloseDelayWatchdog API
Ethernet
TCP/IPUDP Socket PC
Stdio
Printgetchkbhit MiniOS 7 API

API API
(4-6)MiniOS 7 API Function

API DOS INT 21


Regsiter
INT 21 RS232 COM Port
Register
API Function name parameter DOS
WindowsMiniOS 7 API
Library
COM Port API
Win 2000
2.5

z del
DOS

z loadALT+E

z dir

www.plcworld.cn

(4-7)7188XW

autoexec.bat
7524 Power On DOS
MiniOS 7 autoexec.bat INIT
GNDMiniOS 7 autoexec.bat

www.plcworld.cn

3.1

Modbus

Common Variable

Driver

Modbus Relay and

RTU Master/Slave Sub.

Register

ASCII Master/Slave Sub.


TCP Master/Slave Sub.

Sub.

7000 I/O

ESC

Module
Common Varaible
7000 I/O

(4-8)

Modbus

www.plcworld.cn

3.2
demo7524
Sample Program
z include file define
7524sys.h Head File mod_sub.c
COM Port RS232xb.cMbascDR.c MbrtuDR.c
Modbus
#include "7188xb.h" // MiniOS 7 API head file
#include "7524sys.h" // Common variable and define file
#include "mod_sub.c" // Subroutine
#include "RS232xb.c" // MiniOS 7 API COM Port Subroutine
#include "MBascDR.c" // Modbus Slave ASCII format driver
#include "MBrtuDR.c" // Modbus Slave RTU format driver
main()
//
{
//
es= 1;
while(es)
{
//
// MbascDR MbrtuDR
// ESC es=0while loop
}
// COM port Timer Table
return; //
}

C main()
7524sys.h
BC 3.0 static
Memory
Memory

static int YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, NSEC,


OLD_NSEC; //

www.plcworld.cn

static struct RS232C_WORK


RSCOMM; //
#define ED_MAX
1024
#define DD_BIT_MAX
1024
#define DD_BYTE_MAX
DD_BIT_MAX/8
static unsigned char DI[DD_BYTE_MAX]; // Modbus Coil Relay
static unsigned char DO[DD_BYTE_MAX]; // Modbus Input status
static int AI[ED_MAX]; // Modbus Input register
static int AO[ED_MAX]; // Modbus Holding register
static char MSG[128]; // display error or any message on CRT
static int portA;
// current COM port No.
z

Modbus COM Port Baud


RateParityData bitStop bitRTU/ASCII Format TCP
IP AddressPort No. Demo

Driver Windows
Utility
MiniOS 7 DOS
Windows Multi-ProcessMulti-Thread
While Loop
Driver
Windows CPU Time
Shareing Driver
Driver
driver
Driver 20 millseccond Driver
10 millseccond

(Real time
control) Driver

MiniOS 7 API
GetDate(&year,&month,&date);
GetTime(&hour,&minute,&second);
SetDate(year,month,second);
SetTime(hour,minute,second);
API millseccnd
Timer Tick Value API millseccond
mod_sub.c get_time()

www.plcworld.cn

TimerOpen(void);
TimerOpen(void);
TimerResetValue(void);
new_msec= TimerReadValue(void);
Windows API millsecond
DOS INT 21 millsecond 10
z

Driver

LRCCRC

Kbhit()
Getch() C

Kbhit()
Getch() Kbhit()
Getch()

if(Kbhit()) // use ICP stdio fun.


{
ch= Getch();
// use ICP stdio fun.
if( ch == 0x1B)
{
Print("\n\r7524 Modbus Slave Type Demo Program Stop......\n\r");
es= 0;
}
}

Open COM Port Timer Table


close()
MiniOS 7

Modbus Slave
4.1 Demo7524
ICP 7524 Demo demo7524

Modbus
z Modbus RTU ASCII Slave Type Driver
z COM3 Port Modbus ASCII Slave driver
9600 O 7 1
z COM4 Port Modbus RTU Slave driver

www.plcworld.cn

z
z
z
z
z
z

9600 N 8 1
Modbus Driver
Modbus Function1234561516
7188XW
Modbus
Modbus
Power On
Modbus
Output CoilDO1024 bit
Input StatusDI1024 bit
Input RegisterAI1024 16 bit integer
Output RegisterAO1024 16 bit integer

Modbus Message
256 Byte
Output CoilDORTU 1920 ASCII 960
Input StatusDIRTU 1920 ASCII 960
Input RegisterAIRTU 120 ASCII 60
Output RegisterAORTU 120 ASCII 60

(4-9)Demo7524

Open COM3
COM4 Port [ESC]
Address
Modbus Exception code
Function Code561516

www.plcworld.cn

Address
Power On Demo
Demo7524.exe autoexec.bat
demo7524 autoexec.bat
4.2 Demo7524

Demo7524.prj
Demo7524 BC 3.0 Project file
Demo7524.c

7188xb.h
7524 System API Head File
7188xbl.lib
7524 System API Library Large Model
7524sys.h
Modbus Common Varaible and constant define
head file
MBascDR.c
Modbus ASCII Slave driver
MBrtuDR.c
Modbus RTU Slave driver
MOD_Sub.c
Modbus Common Subroutine
RS232XB.c
7524 Common COM port Subroutine
(4-10)Demo7524

RS232XB.c Subroutine
Subroutine
int seropen(int port,long baud,char
parity,int stop,int data,int xonoff)
int serclose(int port)

Open COM port Open

Close COM Port Close

Byte
Byte
(n) Bytes

int sersend(int port, int code)


int serrecv(int port)
int serread(int port, char *buf, int
n)
int serwrite(int port, char *buf, int (n) Bytes
n)
int serflush(int port)
COM Port Buffer

(4-11)RS232XB

Mod_Sub.c Subroutine
Subroutine

int get_date(int *year, int *month,

www.plcworld.cn

int *day)
int get_time(int *hour, int *minute, millsecond
int *second, int *nsec)
int set_date(int year, int month, int
day)
int set_time(int hour, int minute, millsecond
int second)
void LRC_check(unsigned char
Modbus LRC
*buff, int len, unsigned char *chk)
void CRC_check(unsigned char
Modbus CRC
*buff, int len, unsigned char *chk)
void CRC_calc(unsigned char c, CRC_check() Byte
unsigned short *crc)
int itascxr(unsigned int idata, int ASCII Code
nn, char* buf)
int ascxti(char* ch, int n, unsigned ASCII Code
int* data)
int bitrd(unsigned int* data, int
bit
top, int end)

int bitwt(unsigned int* data, int


bit
top, int end, int pattern)

Void msg_log(char *msg)


7188XW
int time_out_check(int old_t, int
timeout)
int nsec_out_check(int old_t, int 10 millseccond
timeout)
int set_DI_bit(int addr, int onoff) Common Variable DI bit
int get_DI_bit(int addr)
Common Variable DI bit
int set_DO_bit(int addr, int onoff) Common Variable DO bit
int get_DO_bit(int addr)
Common Variable DO bit

(4-12)Mod_SUB

Subroutine Win2000

z BC 3.0 integer 16 bit data


32767 32768 Windows Borland Cbuilder
integer 32 bit data BC 3.0 long short
16 bit data
z Modbus OnOff
1 bit Output CoilDO Input RelayDI
16 bits Holding RegisterAO Input

www.plcworld.cn

RegisterAI 7524sys.h Common Variable

#define ED_MAX
1024 // AI, AO
#define DD_BIT_MAX
1024 // DI, DO
#define DD_BYTE_MAX
DD_BIT_MAX/8 // DI,DO
byte
static unsigned char DI[DD_BYTE_MAX]; // Modbus Coil Relay
static unsigned char DO[DD_BYTE_MAX]; // Modbus Input status
static int AI[ED_MAX]; // Modbus Input register
static int AO[ED_MAX]; // Modbus Holding register
AIAO int
DIDO C 1 bit
BOOL byte
unsigned char unsigned
1 bit Address
bit DO

DO[0]

15

14

13

12

11

10

DO[1]

1017

1016

DO[127]

1023

1022

1021

1020

1019

1018

(4-13)Coil Relay Address

Byte 8 bits DO[0] bit Coil Address


0 DO[127] bit Coil Address 1023 Address
Modbus Protocol 0 OPC Server
Coil Address 1 Coil Address 1 - 1024
DO bit set_DO_bit() get_DO_bit()

int set_DO_bit(int addr, int onoff)


// addr: Coil Address
// onoffCoil value1On0Off
{
int words, bits;
unsigned int val;

www.plcworld.cn

words= addr / 8; // 8 DO[words]


bits= addr % 8; // 8 DO[words] bit
val= DO[words]; // DO[words] unsigned int
bitwt
bitwt(&val, bits, bits, onoff);
DO[words]= val;
return;
}
int get_DO_bit(int addr)
{
int i, words, bits;
unsigned int val;
words= addr / 8; // 8 DO[words]
bits= addr % 8; // 8 DO[words] bit
val= DO[words]; // DO[words] unsigned int
bitwt
i= bitrd(&val, bits, bits);
return(i); Coil return
}

second millscond

// second
int time_out_check(int old_t, int timeout)
{
int tm, new_t;
new_t= MINUTE*60 + SECOND;
tm= new_t - old_t;
if(tm < 0) tm= tm + 3600;
if(tm >= timeout) return(-1); // timeout error
else return(0);
}
//
//
//
//

10 millsecond
new_t= SECOND * 100 + NSEC SECOND * 100
* 1000 * 1000
59 * 1000 + 999 = 59999 int 32767

www.plcworld.cn

// long miniOS 7 16 bit


// long
// CPU
int nsec_out_check(int old_t, int timeout)
{
int tm, new_t;
new_t= SECOND * 100 + NSEC;
tm= new_t - old_t;
if(tm < 0) tm= tm + 6000;
if(tm >= timeout) return(-1); // timeout error
else return(0);
}
MINUTESECONDNSEC Common Variable
get_date()get_time()
z

void msg_log(char *msg)


{
Print("%04d/%02d/%02d %02d:%02d %.60s\n\r",
YEAR, MONTH, DAY, HOUR, MINUTE, msg);
return;
}
Print MiniOS 7 stdio API C Function
format \n\r <Carriage Return><Line Feed>
ASCII Code
YEARMONTHDAYHOURMINUTESECOND Common
Variable get_date()get_time()

www.plcworld.cn

4.3 Demo7524Modbus Slave


MbrtuDR.cModbus RTU Slave Subroutine

stepB

stepB0

stepB5

stepB10

stepB20

Open Port

byte

byte

Command

stepB

Response

bytestepB

bytewhile

stepB 5

10

loop

bytestepB

byte

millscond

stepB 20

CPU

(4-14)RTU

MbrtuDR.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
//
//
#define
stepB
RSCOMM_B.step
#define
commflagB RSCOMM_B.comm_flag

www.plcworld.cn

#define
#define
#define

countB
old_timeB
timeoutB

RSCOMM_B.count
RSCOMM_B.old_time
RSCOMM_B.rs.timeout

// buffer static
//
static unsigned char outbuff_B[256]; // comm. data output buffer
static unsigned char inbuff_B[256]; // comm. data input buffer
modbus_slave_RTU_main()
{
int ch;
switch(stepB) // stepB case
{
case 0:
// Open COM Port
ch= seropen(portB, RSCOMM_B.rs.baud, RSCOMM_B.rs.parity,
RSCOMM_B.rs.stop_bit, RSCOMM_B.rs.data_bit, 0);
stepB= 5; //
serflush(portB);
sprintf(MSG, "Open COM%d port= %ld %c %d %d "
"Slave RTU rtc=%d ",
portB, RSCOMM_B.rs.baud, RSCOMM_B.rs.parity,
RSCOMM_B.rs.data_bit, RSCOMM_B.rs.stop_bit, ch);
msg_log(MSG); // open port
// 0.05 sec. byte
timeoutB= 50;
break;
case 5: // start code check
ch = serrecv(portB);
if( ch == -1) return; //
else
{
// byte stepB=10
stepB= 10;
memset(inbuff_B, 0, sizeof(inbuff_B));
countB= 0; // byte
inbuff_B[countB++]= (char)ch; //
OLD_NSEC= SECOND * 100 + NSEC; //
}
break;
case 10: // end code check
while(1)

www.plcworld.cn

{
ch= serrecv(portB);
if(ch == -1)
{
if( nsec_out_check(OLD_NSEC, timeoutB)==0 )
{ return; } // byte
else
{ // command
stepB= 20; // stepB=20
return;
}
}
else
{
if( countB > (sizeof(inbuff_B) - 2) )
{
sprintf(MSG, "Mod Slave RTU Receive buffer over count=%d"
,countB);
msg_log(MSG);
countB= 0;
stepB= 5;
return;
}
inbuff_B[countB++]= (char)ch; // byte
stepB= 10;
OLD_NSEC= SECOND * 100 + NSEC; //
}
}
//

break;
case 20:
mod_request_RTU(); // RTU Command
stepB= 5;
break;
}
return;

// Command Response Message


//
int mod_request_RTU()
{

www.plcworld.cn

// Local Variable
// Command Message function code
// 16 bit integer byte
funno= inbuff_B[1]; // Modbus Function Code
bf[0]= inbuff_B[3];
bf[1]= inbuff_B[2];
memcpy((char *)&addr, &bf[0], 2); // Relay or Register Address
bf[0]= inbuff_B[5];
bf[1]= inbuff_B[4];
memcpy((char *)&no, &bf[0], 2); //
// CRC Message CRC
CRC_check(inbuff_B, countB-2, chk);
if( chk[0]!=inbuff_B[countB-2] || chk[1]!=inbuff_B[countB-1])
{
// CRC Response
sprintf(MSG, "Mod Slave RTU CRC err CRC_RECV=%d %d
CRC_CALC=%d %d len=%d"
,inbuff_B[countB-2], inbuff_B[countB-1], chk[0], chk[1], countB);
msg_log(MSG);
return(-1);
}
// Function Code Response Message
switch(funno)
{
case 01:
// RELAY Coil read
case 02:
// RELAY Intput read
// addr + no 1024
// illegal addree exception code
// no 1920
// illegal addree exception code
// DI or DO CommonVairable Response
memset(outbuff_B, 0, sizeof(outbuff_B));
memcpy(&outbuff_B[0], &inbuff_B[0], 2); // ID No. and Fun. No.
len= 2;
m= no/8; // no. of bytes
n= no%8; // residue of bits
if(n >0) i= m +1; // calc. byte count
else i= m;
outbuff_B[len]= i;
len= len +1;

www.plcworld.cn

// Byte 8 bit
for(i=0; i<m; i++) // one byte DD treatment
{
code= 0;
for(j=0; j<8; j++)
{
if(funno==1) // Coil relay
dd= get_DO_bit(addr);
else
dd= get_DI_bit(addr);
// Relay outbuff_B
if( dd==1)
{ bitwt(&code, j, j, 1); }
else
{ bitwt(&code, j, j, 0); }
addr++;
}
outbuff_B[len]= code;
len= len +1;
}
// 8 bit
if( n >0) // the residue of bits treatment
{
code= 0;
for(j=0; j<n; j++)
{
if(funno==1) // Coil relay
dd= get_DO_bit(addr);
else
dd= get_DI_bit(addr);
if( dd==1)
{ bitwt(&code, j, j, 1); }
else
{ bitwt(&code, j, j, 0); }
addr++;
}
outbuff_B[len]= code;
len= len +1;
}

www.plcworld.cn

CRC_check(outbuff_B, len, &outbuff_B[len]);


len= len+2;
serwrite(portB, outbuff_B, len); // Response Message
break;
case 03:
// Holding Regsiter read
case 04:
// Input Regsiter read
// addr + no 1024
// illegal addree exception code
// no 120
// illegal addree exception code
// AI or AO CommonVairable Response
for(i=0; i<no; i++)
{
if(funno==3) // Holding register
val= AO[addr];
else
val= AI[addr];
// 16 bit integer Byte
cptr=(unsigned char *)&val;
outbuff_B[len]= *(cptr+1); // High Byte
outbuff_B[len+1]= *(cptr); // Low Byte
len= len + 2;
addr++;
}
CRC_check(outbuff_B, len, &outbuff_B[len]);
len= len+2;
serwrite(portB, outbuff_B, len); // Response Message
case 05:
// RELAY Coil write
// addr 1024
// illegal addree exception code
// On or Off
if( inbuff_B[4]== 0xFF ) dd= 1;
else dd= 0;
set_DO_bit(addr, dd);
// DO Address and Value
sprintf(MSG, "Fun-05 Coil set addr=%d set=%02X", addr, inbuff_B[4]);
msg_log(MSG);

www.plcworld.cn

// Command Message Response Message


memset(outbuff_B, 0, sizeof(outbuff_B));
memcpy(&outbuff_B[0], &inbuff_B[0], countB);
serwrite(portB, outbuff_B, countB);
break;
case 06:
// single Register write
// addr 1024
// illegal addree exception code
// it is integer
cptr=(unsigned char *)change;
*(cptr)= inbuff_B[5]; // Low Byte
*(cptr+1)= inbuff_B[4]; // High Byte
memcpy((char *)&val, cptr, 2);
AO[addr]= val;
// AO Address and Value
sprintf(MSG, "Fun-06 Register set addr=%d value=%d", addr, AO[addr]);
msg_log(MSG);
// Command Message Response Message
memset(outbuff_B, 0, sizeof(outbuff_B));
memcpy(&outbuff_B[0], &inbuff_B[0], 6);
len= 6;
CRC_check(outbuff_B, len, &outbuff_B[len]);
len= len+2;
serwrite(portB, outbuff_B, len);
break;
case 15:
// Multiple Relay write
// addr+no 1024
// illegal addree exception code
// DO Address
sprintf(MSG, "Fun-15 Multi-Point Coil set addr=%d bits=%d", addr, no);
msg_log(MSG);
// Byte 8 bit
m= no/8; // no. of bytes
n= no%8; // residue of bits
for(i=0; i<m; i++)
{
j= i + 7;
code= inbuff_B[j];
for(j=0; j<8; j++)

www.plcworld.cn

{
dd= bitrd(&code, j, j);
set_DO_bit(addr, dd);
addr++;
}
}
// 8 bit
if(n >0)
{
j= m + 7;
code= inbuff_B[j];
for(j=0; j<n; j++)
{
dd= bitrd(&code, j, j);
set_DO_bit(addr, dd);
addr++;
}
}
// Command Message 6 bytes Response Message
memset(outbuff_B, 0, sizeof(outbuff_B));
memcpy(&outbuff_B[0], &inbuff_B[0], 6);
len= 6;
CRC_check(outbuff_B, len, &outbuff_B[len]);
len= len+2;
serwrite(portB, outbuff_B, len);
break;
case 16:
// Multiple Registers write
// addr+no 1024
// illegal addree exception code
// AO Address
sprintf(MSG, "Fun-16 Multi-Point Register set addr=%d words=%d", addr, no);
msg_log(MSG);
cptr= (unsigned char *)&val;
for(i=0; i<no; i++)
{
j= i*2 +7;
*(cptr+1)= inbuff_B[j]; //Low Byte
*(cptr)= inbuff_B[j+1]; // High byte
AO[addr+i]= val;
}

www.plcworld.cn

// Command Message 6 bytes Response Message


memset(outbuff_B, 0, sizeof(outbuff_B));
memcpy(&outbuff_B[0], &inbuff_B[0], 6);
len= 6;
CRC_check(outbuff_B, len, &outbuff_B[len]);
len= len+2;
serwrite(portB, outbuff_B, len);
break;
default:
send_exception_RTU(funno, 0x01, inbuff_B); // illegal function
sprintf(MSG, "RTU illegal function fun no.=%d ", funno);
msg_log(MSG);
break;
}
return(0);
} // switch(funno)

www.plcworld.cn

MbascDR.cModbus ASCII Slave Subroutine

stepA

stepA0

stepA5

stepA10

stepA20

Open Port

Code :

Code <LF>

Command

stepA

while loop

Response

stepA 10

stepA 5

stepA 5

stepA 20

Code

CPU
(4-15)ASCII

MbascDR.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#define
start_code ':'
//
//
#define
stepA
RSCOMM_A.step
#define
commflagA
RSCOMM_A.comm_flag
#define
countA
RSCOMM_A.count
#define
old_timeA RSCOMM_A.old_time

www.plcworld.cn

#define

timeoutA

RSCOMM_A.rs.timeout

// buffer static
//
static unsigned char outbuff_A[256]; // comm. data output buffer
static unsigned char inbuff_A[256]; // comm. data input buffer
modbus_slave_ASCII_main()
{
int ch;
switch(stepA) // stepA case
{
case 0:
ch= seropen(portA, RSCOMM_A.rs.baud, RSCOMM_A.rs.parity,
RSCOMM_A.rs.stop_bit, RSCOMM_A.rs.data_bit, 0);
stepA= 5; //
serflush(portA);
sprintf(MSG, "Open COM%d port= %ld %c %d %d "
"Slave ASCII rtc=%d ",
portA, RSCOMM_A.rs.baud, RSCOMM_A.rs.parity,
RSCOMM_A.rs.data_bit, RSCOMM_A.rs.stop_bit, ch);
msg_log(MSG); // open port
timeoutA= 3; // 3 second
break;
case 5: // start code check
ch = serrecv(portA);
if( ch == -1) return; // Byte
else if( ch== start_code)
{
// Start Code stepA=10
stepA= 10;
memset(inbuff_A, 0, sizeof(inbuff_A));
countA= 0; // byte
inbuff_A[countA++]= (char)ch; //
old_timeA= MINUTE * 60 + SECOND; //
}
break;
case 10: // end code check
ch= serrecv(portA);
if(ch == -1)
{
if( time_out_check(old_timeA, timeoutA)==0 )
{ return; } //

www.plcworld.cn

else
{ //
stepA= 5; // Start code
//
sprintf(MSG, "Mod Slave ASC req. cmd is not finished "
"recv. len=%d", countA);
msg_log(MSG);
return;
}
}
else if(ch == LF) // Code
{
inbuff_A[countA++]= (char)ch;
stepA= 20;
}
else
{
if( countA > (sizeof(inbuff_A) - 2) )
{
// buffer
sprintf(MSG, "Mod Slave ASCII Receive buffer over count=%d" ,countA);
msg_log(MSG);
countA= 0;
stepA= 5;
return;
}
inbuff_A[countA++]= (char)ch;
stepA= 10;
}
break;
case 20:
mod_request_ASCII();//ASCII Command
stepA= 5;
break;
}
return;
}
mod_request_ASCII() mod_request_RTU()
Meesage ASCII code itascxr()ascxti()

www.plcworld.cn

Modbus/TCP Slave
5.1
Demo7188 Demo7524 Modbus/TCP Slave
Driver Modbus ASCIIRTUTCP Slave Driver
7188E PC Based Controller Modbus
Server
Demo Modbus/TCP 32 Remote Modbus Client

7188XW Demo7188.exe

Ethernet IP Address 7188e> ip 192.168.127.253


Command 7188E Controller IP Address 192.168.127.253
IP Address Modbus/TCP Server
7188E Ethernet Name I7188EX Name
Remote Client IP Address
Library

DEMO7188.C
7188EL.LIBICP 7188E Library
TCPIPL.LIBICP 7188E TCP Library
(4-16)BC 3.0 Compiler

www.plcworld.cn

(4-17)Demo7188

Demo7188 Dem7524
TCP Remote Modbus Client Connect Disconnet

5.2 Demo7188Modbus/TCP Slave

Demo7188.prj
Demo7188 BC 3.0 Project file
Demo7188.c

7188e.h
7188E System API Head File
7188el.lib
7188E System API Library Large Model
TCPIP.h
7188E System API Head File for TCP/IP
TCPIPL.lib
7188E System API Library Large Model for
TCP/IP
7188sys.h
Modbus Common Varaible and constant define
head file
7188TCP.h
Modbus/TCP Common Varaible and constant
define head file
MBascDR.c
Modbus ASCII Slave driver
MBrtuDR.c
Modbus RTU Slave driver
MBtcpDR.c
Modbus TCP Slave driver
MOD_Sub.c
Modbus Common Subroutine
RS232XB.c
7188E or 7524 Common COM port Subroutine
TCP_SUB.c
7188E Common TCP/IP Subroutine

www.plcworld.cn

(4-18)Demo7188

MbascDR.cMbrtuDR.cMOD_SUB.cRS232XB.c Demo7524

TCP_SUB.c Subroutine
Subroutine
int tcp_main_initial()
int tcp_bind_initial(int port_no)
killsockets()

Open TCP
Bind one seocket Server socket
Remote Client connect
connect disconnet

(4-19)TCP_SUB

TCP/IP API Head File and Library


TCPIP.h and TCPIPL.lib
Demo7188.c Demo7524.c
TCP/IP
Head File and Subroutine while loop modbus_slave_TCP_init()
Open TCP while loop modbus_TCP_main()
Driverwhile loop killsocket() Close
main()
{
modbus_slave_TCP_init(); // TCP initial set
es= 1;
while(es)
{
// Modbus RTU and ASCII Slave Driver
modbus_TCP_main();

// Modbus/TCP Slave Driver

// Kbhit() ESC
} // while(1)
serclose(portA); // close COM3 port
TimerClose(); // close Timer table
killsockets(); // close all TCP/IP socket
Nterm();//close Ethernet

www.plcworld.cn

return;
}
MbtcpDR.cmodbus_TCP_main() Subroutine Modbus/TCP
Driver

driver

Selectsocket()
TCP message

for loop socket

connect
master

New Connect

remote client connect

Remote client send command


connect Remote
Client modbus
command message

for loop end

(4-20)Modbus/TCP

Accept new connect socket

www.plcworld.cn

modbus_TCP_main() Subroutine
int modbus_TCP_main()
{
int i, rc, err;
struct sockaddr_in ssin; /* client Internet endpoing address */
int sin_len;
/* length of sockaddr_in */
unsigned long set;
sin_len = sizeof( ssin );
for (i = 0; i < SOCKETS; i++)
{
if (SST[i].active)
{ /* re-join active sockets */
FD_SET( i, &RFDS );
}
}
SELTIME.tv_sec=0;
SELTIME.tv_usec=0;
/* Set NonBlock Mode for I/O*/
set = 1;
ioctlsocket(MASTER_SOCKET, FIONBIO, (unsigned long*) &set);
//------ check the socket come in -------rc = selectsocket( SOCKETS, &RFDS, NULL, NULL, &SELTIME );
if (rc < 0)
{
Print( "selectsocket error %d\n\r", rc );
return(-1);
}
if( !rc ) //no socket come in , continue waitting
return(0);
//some sockets come in, and scan all possible sockets
for (i = 0; i < SOCKETS; i++)
{ //------ scan all possible sockets
if (FD_ISSET(i, &RFDS))
{
if (i == MASTER_SOCKET)
{ /* master socket */
memset( &ssin, 0, sizeof(ssin) );
CLIENT_SOCKET = accept(MASTER_SOCKET, (struct sockaddr *)&ssin

www.plcworld.cn

, &sin_len );
err= CLIENT_SOCKET;
if (err < 0)
{
Print( "accept error %d\n\r", err );
return(-1);
}
//------ send connection message to client
FD_SET( CLIENT_SOCKET, &RFDS );//set the setting
SST[CLIENT_SOCKET].active = 1;//active
SST[CLIENT_SOCKET].init = 1;
memcpy( &SST[CLIENT_SOCKET].sin, &ssin, sin_len);
sprintf(MSG, "Client Sockect connect ID=%d", CLIENT_SOCKET);
msg_log(MSG);
}
else
{
/* slave socket */
// The client connection is accept and distribution to socket i
// So the user can read the Modbus Command message
// will cause one socket. So the maximun socket (connection) is 31.
// In the other word, This server can be connected by 31 client maximun.
modbus_request_TCP(i);

// do message command

}
} // if(FD_ISSET....)
} // for(i=0...)
return(0);
}

Modbus TCP Driver


z TCP bind socket accept() client
connect recv() remote client message
Windows Unix Multi-Thread/Process
MiniOS 7 Process client
connect message
selectsocket() socket
struct timeval SELTIME
ioctlsocket() NonBlock Mode
socket
socket FD_ISSET(i, &RFDS) socket

www.plcworld.cn

socket

z Client Connect Client send meesage socket


bind socket Remote Client accept()
socket socket
Modbus Command recv() Command
Response
z Modbus Command Command Message
6 bytes Modbus/TCP RTU Format
modbus_request_TCP() Command Response
RTU

Modbus Master
6.1
z Modbus RTU ASCII Master Type Driver
z MST7524R Modbus RTU Master/Slave
COM3 Port Modbus RTU Master driver COM4 Port
Modbus RTU Slave driver 9600 N 8 1
z MST7524A Modbus ASCII Master/Slave
COM3 Port Modbus ASCII Master driver COM4 Port
Modbus ASCII Slave driver 9600 O 7 1
z COM3 Port Master Driver
DIDOAIAO Common Variable COM4 Port Slave
Driver
z Master Driver
Unit

z 1024 Master and Slave


COM3 COM4 Common
Variable

www.plcworld.cn

(4-21)Modbus Master MST7524R

(4-22)Modbus Master MST7524A

www.plcworld.cn

6.2 MST7524RModbus RTU Master/Slave

MST7524R.prj
MST7524R BC 3.0 Project file
MST7524R.c

7188xb.h
7524 System API Head File
7188xbl.lib
7524 System API Library Large Model
MST7524R.h
Modbus Common Varaible and constant define
head file
MSrtuDR.c
Modbus RTU Master driver
MBrtuDR.c
Modbus RTU Slave driver
MOD_Sub.c
Modbus Common Subroutine
RS232XB.c
7524 Common COM port Subroutine
MSrtuDR.cModbus RTU Master Subroutine

stepD0

stepD

Open Port
stepD
5
stepD10

stepD20

stepD25

Query

stepD5

byte

byte

Response

Unit

stepD 30

Query Message

bytestepD

bytewhile

20

loop

byte

byte

stepD30

millscond

0.1

stepD 5

stepD 99

stepD 25
stepD99
3
stepD 5

CPU
(4-23)Modbus RTU Master

www.plcworld.cn

modbus_master_RTU_main() Subroutine
{
int i, ch, len, addr, case_no, val;
unsigned char *cptr;
unsigned int crc;
float fl;
if(portD < 0) return;

// port not define, it is empty port

switch(stepD)
{
case 0:
ch= seropen(portD, RSCOMM_D.rs.baud, RSCOMM_D.rs.parity,
RSCOMM_D.rs.stop_bit, RSCOMM_D.rs.data_bit, 0);
stepD= 5;
serflush(portD);
sprintf(MSG, "Open COM%d port= %ld %c %d %d "
"Master RTU rtc=%d ",
portD, RSCOMM_D.rs.baud, RSCOMM_D.rs.parity,
RSCOMM_D.rs.data_bit, RSCOMM_D.rs.stop_bit, ch);
msg_log(MSG);
c_caseD= -1;
break;
case 5:
c_caseD++; // unit index
// index case unit unit
if(c_caseD >= MODBUS_MASTER_UNIT_MAX) c_caseD= 0;
if(RTU_UNIT[c_caseD].station == -1) c_caseD= 0;
// prepare request command
if(RTU_UNIT[c_caseD].station == -1)
{ stepD= 5; return; }
memset(outbuff_D, 0, sizeof(outbuff_D));
outbuff_D[0]= RTU_UNIT[c_caseD].station;
outbuff_D[1]= RTU_UNIT[c_caseD].fun;
cptr=(unsigned char *)&RTU_UNIT[c_caseD].req_addr;
outbuff_D[3]=*(cptr);
outbuff_D[2]=*(cptr+1);
cptr=(unsigned char *)&RTU_UNIT[c_caseD].words;
outbuff_D[5]= *(cptr);
outbuff_D[4]=*(cptr+1);
len= 6;
CRC_check(outbuff_D, len, &outbuff_D[len]);

www.plcworld.cn

len= len+2;
serwrite(portD, outbuff_D, len); // Query Messsage
stepD= 10;
old_timeD= MINUTE * 60 + SECOND;
countD= 0;
timeoutD= 3; // 3 second
break;
case 10: // start code check
ch = serrecv(portD);
if( ch == -1)
{
if( time_out_check(old_timeD, timeoutD)==0 )
{ return; } // during comm.
else
{ // timeout error
stepD= 99; //
old_timeD= MINUTE * 60 + SECOND;
timeoutD= 3; // 3 second timeout
sprintf(MSG, "Mod RTU MASTER send command error "
"stn=%d unit=%d"
, RTU_UNIT[c_caseD].station, c_caseD );
msg_log(MSG);
return;
}
}
else
{
stepD= 20; // byte
memset(inbuff_D, 0, sizeof(inbuff_D));
countD= 0;
inbuff_D[countD++]= (char)ch;
old_nsecD= SECOND * 100 + NSEC;
}
break;
case 20: // end code check
while(1)
{
ch= serrecv(portD);
if(ch == -1)
{
if( nsec_out_check(old_nsecD, timeoutDD)==0 )
{ return; } // during comm.
else
{ // receive data finish

www.plcworld.cn

stepD= 25; return;


}
}
else
{
if( countD > (sizeof(inbuff_D) - 2) )
{
sprintf(MSG, "Mod Master RTU Receive buffer over count=%d"
,countD);
msg_log(MSG);
countD= 0;
stepD= 99;
//
old_timeD= MINUTE * 60 + SECOND;
timeoutD= 3; // 3 second timeout
return;
}
inbuff_D[countD++]= (char)ch;
stepD= 20;
old_nsecD= SECOND * 100 + NSEC;
}
}
//

break;
case 25: // Query Message Response Message
mod_save_RTU();
old_nsecD= SECOND * 100 + NSEC;
stepD= 30;
break;
case 30: // 0.1 unit
if( nsec_out_check(old_nsecD, 10)==0 )
{ return; } // during comm.
else
stepD= 5; // goto next polling
break;
case 99: // waiting 3 second for next polling
if( time_out_check(old_timeD, timeoutD)==0 )
{ return; } // still waiting
else
stepD= 5; // goto next polling
break;
} // switch(stepD)
return;

www.plcworld.cn

6.3 MST7524AModbus ASCII Master/Slave

MST7524A.prj
MST7524R BC 3.0 Project file
MST7524A.c

7188xb.h
7524 System API Head File
7188xbl.lib
7524 System API Library Large Model
MST7524A.h
Modbus Common Varaible and constant define
head file
MSascDR.c
Modbus ASCII Master driver
MBascDR.c
Modbus ASCII Slave driver
MOD_Sub.c
Modbus Common Subroutine
RS232XB.c
7524 Common COM port Subroutine
MSascDR.cModbus ASCII Master Subroutine
stepC0

stepA

Open Port
stepC
5

stepC5
Unit
Query Message

stepC10

stepD20

stepC25

Query

Code :

Code <LF>

Response

while loop

stepC 30

stepC 20

stepD 25

Code

stepC 99

stepD 99

stepC30
0.1
stepC 5

stepC99
3
stepC 5

CPU

(4-24)Modbus ASCII Master

www.plcworld.cn

modbus_master_ASCII_main() Subroutine
{
int i, ch, len, val, addr, case_no;
float fl;
unsigned char bf[10], change[6];

if(portC < 0) return;

// port not define, it is empty port

switch(stepC)
{
case 0:
ch= seropen(portC, RSCOMM_C.rs.baud, RSCOMM_C.rs.parity,
RSCOMM_C.rs.stop_bit, RSCOMM_C.rs.data_bit, 0);
stepC= 5;
sprintf(MSG, "Open COM%d port= %ld %c %d %d "
"Master ASCII rtc=%d ",
portC, RSCOMM_C.rs.baud, RSCOMM_C.rs.parity,
RSCOMM_C.rs.data_bit, RSCOMM_C.rs.stop_bit, ch);
msg_log(MSG);
c_caseC= -1;
break;
case 5:
c_caseC++; // unit index
// index case unit unit
if(c_caseC >= MODBUS_MASTER_UNIT_MAX) c_caseC= 0;
if(ASC_UNIT[c_caseC].station == -1) c_caseC= 0;
// prepare request command
if(ASC_UNIT[c_caseC].station == -1)
{ stepC= 5; return; }
memset(outbuff_C, 0, sizeof(outbuff_C));
outbuff_C[0]= ':';
sprintf(&outbuff_C[1], "%02X", ASC_UNIT[c_caseC].station);
sprintf(&outbuff_C[3], "%02X", ASC_UNIT[c_caseC].fun);
sprintf(&outbuff_C[5], "%04X", ASC_UNIT[c_caseC].req_addr);
sprintf(&outbuff_C[9], "%04X", ASC_UNIT[c_caseC].words);
len= strlen(outbuff_C);
LRC_check(&outbuff_C[1], len-1, &outbuff_C[len]);
len= len+2;
outbuff_C[len]= CR;
outbuff_C[len+1]= LF;
len= len+2;
serwrite(portC, outbuff_C, strlen(outbuff_C)); // Query Message

www.plcworld.cn

//

stepC= 10;
old_timeC= MINUTE * 60 + SECOND;
countC= 0;
timeoutC= 3; // 3 second
break;
case 10:
// response message
ch = serrecv(portC);
if( ch == -1)
{
if( time_out_check(old_timeC, timeoutC)==0 )
{ return; } // during comm.
else
{ // timeout error
stepC= 99; //
old_timeC= MINUTE * 60 + SECOND;
timeoutC= 3; // 3 second timeout
sprintf(MSG, "MODBUS ASCII MASTER send command error "
"stn=%d unit=%d"
, ASC_UNIT[c_caseC].station, c_caseC );
msg_log(MSG);
return;
}
}
else if( ch== ':' ) // Start code
{
stepC= 20;
memset(inbuff_C, 0, sizeof(inbuff_C));
countC= 0;
inbuff_C[countC++]= (char)ch;
}
else
{
Print("%04X ", ch);
}
break;
case 20: // end code <LF>
ch= serrecv(portC);
if(ch == -1)
{
if( time_out_check(old_timeC, timeoutC)==0 )
{ return; } // during comm.
else
{ // timeout error
stepC= 99; // waiting 3 second

www.plcworld.cn

old_timeC= MINUTE * 60 + SECOND;


timeoutC= 3; // 3 second timeout
sprintf(MSG, "MODBUS ASCII MASTER send command error "
"stn=%d unit=%d"
, ASC_UNIT[c_caseC].station, c_caseC );
msg_log(MSG);
return;
}
}
else if(ch == LF) // end code
{
inbuff_C[countC++]= (char)ch;
stepC= 25;
}
else
{
if( countC > (sizeof(inbuff_C) - 2) )
{
sprintf(MSG, "Mod Master ASCII Receive buffer over count=%d"
,countC);
msg_log(MSG);
countC= 0;
stepC= 99; //
old_timeC= MINUTE * 60 + SECOND;
timeoutC= 3; // 3 second timeout
return;
}
inbuff_C[countC++]= (char)ch;
stepC= 20;
}
break;
case 25: // Query Message Response Message
mod_save_ASCII();
old_nsecC= SECOND * 100 + NSEC;
stepC= 30;
break;
case 30: // 0.1 unit
if( nsec_out_check(old_nsecC, 10)==0 )
{ return; } // during comm.
else
{ // receive data finish
stepC= 5; // goto next polling
}
break;

www.plcworld.cn

case 99: // waiting 3 second for next polling


if( time_out_check(old_timeC, timeoutC)==0 )
{ return; } // still waiting
else
{
stepC= 5; // goto next polling
}
break;
} // switch(stepC)
return;
}
Unit
z Master Driver
Modbus Message 256 bytes Unit

z Unit struct Demo 100 case Unit


Modbus Device AddressFunction Code
Relay/Register Address
#define MODBUS_MASTER_UNIT_MAX
100

struct MODBUS_UNIT // for modbus master driver


{
char station;
// slave station ID No.
char fun ;
// function code
int words;
// no. of request words/bits
int req_addr;
// request start addr.
};
Unit Query Message Unit
Demo unit_init_set()
Master Driver Source RTU
ASCII Unit Case
Master ASCII unit_init_set()
unit_init_set()
{
int i, j, m, n, cnt;
#define
#define

DD_MAX_POLL
ED_MAX_POLL

960 // relay
60 // register

// initial Unit
memset((char *)ASC_UNIT, 0, sizeof(ASC_UNIT));
for(i=0; i<MODBUS_MASTER_UNIT_MAX; i++)

www.plcworld.cn

{ // 1 Unit
ASC_UNIT[i].station= -1;
// default to set no used unit
}
// Unit Unit
// Max. communication bits of Relay: (240 bytes/2) * 8 = 960 points
// Max. communication words of Register: 240 bytes / 4= 60 points
// create polling unit for Reading Output Coil
m= DD_BIT_MAX / DD_MAX_POLL;
n= DD_BIT_MAX % DD_MAX_POLL;
cnt= -1;
for(i=0; i<m; i++)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 1;
// Read Output Coil
ASC_UNIT[cnt].words= DD_MAX_POLL; // 960 points
ASC_UNIT[cnt].req_addr= i*DD_MAX_POLL; // relay start address
}
if( n>0)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 1;
// Read Output Coil
ASC_UNIT[cnt].words= n;
// residue of points
ASC_UNIT[cnt].req_addr= m*DD_MAX_POLL; // relay start
address
}
// create polling unit for Reading Input Status
m= DD_BIT_MAX / DD_MAX_POLL;
n= DD_BIT_MAX % DD_MAX_POLL;
for(i=0; i<m; i++)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 2;
// Read Input Status
ASC_UNIT[cnt].words= DD_MAX_POLL; // 960 points
ASC_UNIT[cnt].req_addr= i*DD_MAX_POLL; // relay start address
}
if( n>0)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address

www.plcworld.cn

ASC_UNIT[cnt].fun= 2;
// Read Input Status
ASC_UNIT[cnt].words= n;
// residue of points
ASC_UNIT[cnt].req_addr= m*DD_MAX_POLL; // relay start
address
}
// create polling unit for Reading Holding Register
m= ED_MAX / ED_MAX_POLL;
n= ED_MAX % ED_MAX_POLL;
for(i=0; i<m; i++)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 3;
// Read Input Status
ASC_UNIT[cnt].words= ED_MAX_POLL; // 60 points
ASC_UNIT[cnt].req_addr= i * ED_MAX_POLL; // register start
address
}
if(n >0)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 3;
// Read Input Status
ASC_UNIT[cnt].words= n;
// residue of points
ASC_UNIT[cnt].req_addr= m * ED_MAX_POLL; // register start
address
}
// create polling unit for Reading Input Register
m= ED_MAX / ED_MAX_POLL;
n= ED_MAX % ED_MAX_POLL;
for(i=0; i<m; i++)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address
ASC_UNIT[cnt].fun= 4;
// Read Input Status
ASC_UNIT[cnt].words= ED_MAX_POLL; // 60 points
ASC_UNIT[cnt].req_addr= i * ED_MAX_POLL; // register start
address
}
if(n >0)
{
cnt++;
ASC_UNIT[cnt].station= 1; // Modbus Device Address

www.plcworld.cn

ASC_UNIT[cnt].fun= 4;
// Read Input Status
ASC_UNIT[cnt].words= n;
// residue of points
ASC_UNIT[cnt].req_addr= m * ED_MAX_POLL; // register start
address
}
sprintf(MSG, "Initial Set Master Unit %d case", cnt+1);
msg_log(MSG);
return(0);
}

Modbus RTUASCII Master Driver


z Open Port Unit
index Unit Case No.
z Query Message
Byte 3 byte
byt buffer

z RTU code byte

z ASCII Line Feed 0x0A code Query


Message code

z byte
buffer
z Response Message DIDOAIAO
Common Variable Slave COM Port

z Unit Demo 0.1


Unit
Modbus

Interval
z 3
Unit

www.plcworld.cn

Modbus/TCP Master
7.1
z Modbus TCP Master Type Driver Remote connect
Modbus Device
z Modbus TCP Slave Type Driver

z DIDOAIAO Unit

z Modbus/TCP Slave

(4-25)Modbus/TCP Master

www.plcworld.cn

(4-26)Modbus/TCP Master ()

7.2 MST7188Modbus/TCP Master/Slave

MST7188.prj
MST7188 BC 3.0 Project file
MST7188.c

7188e.h
7188E System API Head File
7188el.lib
7188E System API Library Large Model
TCPIP.h
7188E System API Head File for TCP/IP
TCPIPL.lib
7188E System API Library Large Model for
TCP/IP
MST7188.h
Modbus Common Varaible and constant define
head file
7188TCP.h
Modbus/TCP Common Varaible and constant
define head file
MStcpDR.c
Modbus TCP Master driver
MBtcpDR.c
Modbus TCP Slave driver
MOD_Sub.c
Modbus Common Subroutine
RS232XB.c
7188E or 7524 Common COM port Subroutine
TCP_SUB.c
7188E Common TCP/IP Subroutine

www.plcworld.cn

MStcpDR.cmodbus_ master_TCP_main() Subroutine


driver

stepT 0: Remote
Server Connect

stepT 2, 4: 5
connect

stepT 5: unit
Query Message

stepT 10:
Response Message

stepT 25: Response


message
Common Variable

stepT 30: 0.1


Unit

stepT 99:
3 Remote
Server Connect

(4-27)Modbus/TCP Master

www.plcworld.cn

modbus_master_TCP_main()
{
int i, len, ch;
unsigned int crc, crc_r;
unsigned char *cptr, bf[10];
unsigned long set;
switch(stepT)
{
case 0:
// Set NonBlock Mode for I/O
set = 1;
ioctlsocket(OUT_SOCKET, FIONBIO, (unsigned long*) &set);
if(connect(OUT_SOCKET, (struct sockaddr *)&SST[OUT_SOCKET].sin,
sizeof(SST[OUT_SOCKET].sin)) == SOCKET_ERROR )
{
if(errno == EINPROGRESS)
{
FD_ZERO(&fd_write);
FD_SET(OUT_SOCKET,&fd_write);
selectsocket(OUT_SOCKET, 0, &fd_write, 0, &SELTIME);
if(FD_ISSET(OUT_SOCKET, &fd_write)) {}
stepT=2 ;
sprintf(MSG, "Remote modbus server connecting......");
msg_log(MSG);
}
else
{
sprintf(MSG, "Connect remote modbus server error-2 rtc=%d ", errno);
msg_log(MSG);
stepT= 99; // continue try to connect
old_nsecT= SECOND * 100 + NSEC;
}
}
else
{
stepT= 2;

www.plcworld.cn

sprintf(MSG, "Remote modbus server connecting............");


msg_log(MSG);
}
c_caseT= -1;
break;
case 2: // delay to make connect OK
old_nsecT= SECOND * 100 + NSEC;
stepT= 4;
break;
case 4: // delay 5 sec. to make connect OK
if( nsec_out_check(old_nsecT, 500)==0 )
{ return; } /* during comm. */
else
{

// wait 5 sec.

stepT= 5;
sprintf(MSG, "Remote modbus server Connect OK.........");
msg_log(MSG);
}
break;
case 5:
c_caseT++;
if(c_caseT >= MODBUS_MASTER_UNIT_MAX) c_caseT= 0;
if(TCP_UNIT[c_caseT].station == -1) c_caseT= 0;
// prepare request command
if(TCP_UNIT[c_caseT].station == -1)
{ stepT= 5; return; }
memset(outbuff_T, 0, sizeof(outbuff_T));
len= 6;
outbuff_T[len++]= TCP_UNIT[c_caseT].station;
outbuff_T[len++]= TCP_UNIT[c_caseT].fun;
cptr=(unsigned char *)&TCP_UNIT[c_caseT].req_addr;
outbuff_T[len++]=*(cptr+1);
outbuff_T[len++]=*(cptr);
cptr=(unsigned char *)&TCP_UNIT[c_caseT].words;
outbuff_T[len++]= *(cptr+1);
outbuff_T[len++]=*(cptr);

www.plcworld.cn

outbuff_T[5]= len -6;


outbuff_T[1]= c_caseT;
stepT= 10;
if(send(OUT_SOCKET, outbuff_T, len, 0) >0 )
{
stepT= 10;
old_nsecT= SECOND * 100 + NSEC;
countT= 0;
}
else
{
old_nsecT= SECOND * 100 + NSEC;
sprintf(MSG, "Send to remote modbus server error rtc=%d ", errno);
msg_log(MSG);
stepT= 99; // continue try to connect
}
break;
case 10: // receive response message
// Set NonBlock Mode for I/O
set = 1;
ioctlsocket(OUT_SOCKET, FIONBIO, (unsigned long*) &set);
countT= recv(OUT_SOCKET,inbuff_T,sizeof(inbuff_T),0 );
if(countT== 0 ) // it is disconnect
{
sprintf(MSG, "Remote modbus server close.... ");
msg_log(MSG);
stepT= 99; // continue try to connect
old_nsecT= SECOND * 100 + NSEC;
}
else if(countT == SOCKET_ERROR ) // has error
{
if(errno == EWOULDBLOCK) // continue to wait
{
if( nsec_out_check(old_nsecT, 500)==0 ) // wait 0.1 sec.
stepT= 10; // recv. again
else
{
stepT= 99; // continue try to connect

www.plcworld.cn

old_nsecT= SECOND * 100 + NSEC;


sprintf(MSG, "Recv from remote modbus server timeout");
msg_log(MSG);
}
}
else // it is error
{
sprintf(MSG, "Recv from remote modbus server error=%d ", errno);
msg_log(MSG);
stepT= 99; // continue try to connect
old_nsecT= SECOND * 100 + NSEC;
}
}
else

// it has data

{
stepT= 25;
}
break;
case 25: //
mod_save_TCP();
old_nsecT= SECOND * 100 + NSEC;
stepT= 30;
break;
case 30:
// waiting 0.1 sec and then polling next unit
if( nsec_out_check(old_nsecT, 10)==0 )
{ return; } // during comm.
else
{
// receive data finish
stepT= 5; // goto polling
}
break;
case 99: // waiting 3 second for next polling
if( nsec_out_check(old_nsecT, 300)==0 )
// wait 3 sec.
{ return; } // still waiting
else
{
stepT= 0; // goto connect again

www.plcworld.cn

reconnect();
}
break;
} // switch(stepD)
return;
}

Modbus TCP Master Driver


z Open TCP/IP Port Unit
index Unit Case No.

z Remote Modbus Slave Server


connect() API
ioctlsocket() Non-Block
Holding Driver
MiniOS7 Single Task Windows Multi-Task
Thread Event-Driven
z connect() 5
Ethernet Session

z recv() Response Message ioctlsocket()


Non-Block
z recv() bytes
disconnect connect()
z Response Message Common Variable
0.1 Unit
Interval
z connect() disconnectrecv()
3 sockect close sockect connect
connect()

z ICP7188E5 Real Time Clock


MiniOS7 GetDate() GetTime()
Real Time MinuteSecondMillsecond
system timer ticks
initial set
static unsigned long OLD_TIMER_MS;
static int TIMER_FLAG=0, TIMER_SECOND, NNSEC;

www.plcworld.cn

// 7188E does not support realtime clock


/*-------------------------------------------------------------------------*/
/* get system tick and set NSEC SECOND
*/
/*-------------------------------------------------------------------------*/
void get_nsec(void)
{
unsigned long ms, max;
unsigned char *cptr;
int delta;
ms= TimerReadValue();
if(ms >= OLD_TIMER_MS)

delta= (int)(ms - OLD_TIMER_MS);

else
{
cptr= (unsigned char *)&max;
*(cptr)= 0xFF;
*(cptr+1)= 0xFF;
*(cptr+2)= 0xFF;
*(cptr+3)= 0xFF;
delta= (int) ((max- OLD_TIMER_MS) + ms);
}
NNSEC= NNSEC + delta;
if(NNSEC >= 1000)
{
SECOND= SECOND + NNSEC/1000;
if(SECOND >=60)
{
SECOND= SECOND - 60;
MINUTE= MINUTE+1;
if(MINUTE >= 60) MINUTE= MINUTE - 60;
}
NNSEC= NNSEC % 1000;
}

www.plcworld.cn

NSEC= NNSEC/10;
OLD_TIMER_MS= ms;
//
Print("%d %d %d\n\r", MINUTE, SECOND, NSEC);
}
/*-------------------------------------------------------------------------*/
/* init NSEC SECOND
*/
/*-------------------------------------------------------------------------*/
void get_nsec_init(void)
{
if(TIMER_FLAG==0)
{
TimerOpen();
TIMER_FLAG= 1;
TimerResetValue();
OLD_TIMER_MS= TimerReadValue();
NSEC= 0;
SECOND= 0;
MINUTE= 0;
NNSEC= 0;
}
}

www.plcworld.cn

Demo
Demo
PC Based Controller
2.2.Utility

8.1
Demo7524 COM Port
ICP7524 Common Variable DIDOAIAO

COM1
ASCIIPC COM1
RTUPC COM2
7524 COM3
7524 COM4

PC-1Win-2000

ICP7524

PC-2Win-2000

Modbus_Tool

Demo7524

7188XW
Modbus_Tool

(4-28)Demo7524

1. PC-1Modbus_Tool Master ASCII [Port Define] Button


COM1 9600 O 7 1
2. PC-2Modbus_Tool Master RTU [Port Define] Button
COM2 9600 N 8 1
3. TXRXGND Pin TX RX GND

4. PC-2 COM1 ICP7524 COM1 7188XW


ICP7524 TXRX
GND ICP COM1 Port
5. Master ASCII [send command] Button
ICP7524 Common Variable AO
5.1 Function CodeHolding Register (Addr:4xxxxx)
5.2 Modbus Device Address1
5.3 Relay/Register Address100
5.4 Communication Words/Bits30
6. Master ASCII Mouse 40100

www.plcworld.cn

Decimal [Set Data Value] Button


123 Mouse 40105 Hex. Double
click Hex. ABC
Decimal 2748
7. PC7188XW AO
40100 40105
8. Master RTU Master ASCII [send
command] Button ICP7524 Common Variable AO
Master ASCII PC-1 ICP
PC-2 Master RTU
9. 5 8 Master RTU
Master ASCII 7188XW

(4-29)Demo7524
Demo7524
Holding Register

www.plcworld.cn

40105 2748
Query Message and Response
Message

(4-30)Modbus_Tool Master ASCII

MST7524A Modbus ASCII Master/Slave


Master ICP7524 Common Variable DI
DOAIAO Slave

COM1
ASCIIPC COM1
ASCIIPC COM2
7524 COM3
7524 COM4

PC-1Win-2000

ICP7524

PC-2Win-2000

Modbus_Tool

MST7524A

7188XW
Modbus_Tool

(4-31)Demo7524A

1. PC-1Modbus_Tool Slave ASCII [Port Define] Button


COM1 9600 O 7 1
2. PC-2Modbus_Tool Master ASCII [Port Define] Button

www.plcworld.cn

COM2 9600 O 7 1
3. TXRXGND Pin TX RX GND
4.

5.

6.
7.

8.

PC-2 COM1 ICP7524 COM1 7188XW


ICP7524 TXRX
GND ICP COM1 Port
PC-1Slave ASCII Open Server 7188XW
MST7524A 6
Modbus Slave
PC-1Slave ASCII [Open Server] Button
MST7524A
Slave ASCII
MST7524A Common Variable
7.1 Output Coil (DO)00001 ON00005 ON
7.2 Input Relay (DI)10011 ON10015 ON
7.3 Holding Register (AO)40021 12340025 456
7.4 Input Register (AI)30031 78930035 999
PC-2Master ASCII
[send command] Button ICP7524 Common Variable
Output Coil
8.1 Function CodeOutput Coil (Addr:0xxxxx)
8.2 Modbus Device Address1
8.3 Relay/Register Address1
8.4 Communication Words/Bits30

9. PC-1 ICP7524 RS232C 7188XW


MST7524A

10. 7 8
11. MST7524R

www.plcworld.cn

(4-32)MST7524A
MST7524A

Input Register

(4-33)Modbus_Tool Slave ASCII

www.plcworld.cn

Output Coil
00001 00005 On

(4-34)Modbus_Tool Master ASCII

www.plcworld.cn

8.2 Ethernet TCP/IP


Demo7188 COM Port Ethernet
ICP7188E5 Common Variable DIDOAIAO
Modbus/TCP Client

ASCIIPC COM1

COM1

7524 COM3

RTUPC COM2

TCPEthernet

7524 COM4

Ethernet
PC-1Win-2000

ICP7188E5

PC-2Win-2000

Modbus_Tool

Demo7188

7188XW
Modbus_Tool

(4-35)Demo7188

1. PC-1PC-2Master ASCIIMaster RTU Demo7524

2. PC-1PC-2ICP7188E5 IP Address
NetMask PC-1 192.168.127.2 PC-2
192.168.127.10 ICP7188E5 192.168.127.253
3. ICP7188E5 Modbus/TCP Slave
Client Connect PC-1PC-2 Master TCP
4. PC-2 COM1 ICP7188E5 COM1 7188XW
ICP7188E5 TXRX
GND ICP COM1 Port
5. PC-1Master TCP [send command] Button
ICP7188E5 Common Variable AO
5.1 Function CodeHolding Register(Addr:4xxxxx)
5.2 Modbus Device Address1
5.3 Relay/Register Address200
5.4 Communication Words/Bits50
6. PC-1Master TCP Mouse 40200
Decimal [Set Data Value] Button

www.plcworld.cn

456 Mouse 40211 Hex. Double


click Hex. CDE
Decimal 3294
7. PC7188XW AO
40200 40211
8. PC-2Master TCP PC-1Master TCP
[send command] Button ICP7188E5 Common Variable AO
PC-1Master TCP PC-1 ICP
PC-2Master TCP
9. 4 6 PC-2Master TCP
PC-1Master TCP 7188XW

10. PC Master ASCII Master RTU


PC-1Master TCPMaster ASCIIPC-2Master TCPMaster
RTU ICP7188E5
ICP7188E5 Common Variable

(4-36)Demo7188
Demo7188
client connect
Holding Register

www.plcworld.cn

(4-37)Modbus_Tool Master TCP

www.plcworld.cn

MST7188 Modbus TCP Master/Slave


Master ICP7188E5 Common Variable DI
DOAIAO Slave Client

COM1

Ethernet
PC-1Win-2000

ICP7188E5

PC-2Win-2000

Modbus_Tool

Demo7188

7188XW
Modbus_Tool

(4-38)MST7188

1. PC-1 Slave TCP Open Server Master


TCP
2. PC-2 Master TCP
3. PC-1PC-2ICP7188E5 IP Address
NetMask
4. PC-1 IP Address 129.168.127.2 MST7188
Connect Remote Server IP Address IP Address
5. PC-2 COM1 ICP7524 COM1 7188XW
ICP7524 TXRX
GND ICP COM1 Port
6. PC-1Slave TCP Open Server 7188XW MST7188
13 remote connect
Modbus Slave
7. PC-1Slave TCP [Open Server] Button
MST7188 7188XW
connect
8. Slave TCP MST7188
Common Variable
8.1 Output Coil (DO)00002 ON00006 ON
8.2 Input Relay (DI)10012 ON10016 ON
8.3 Holding Register (AO)40022 32140026 654
8.4 Input Register (AI)30032 98730036 888

www.plcworld.cn

9. PC-1Master TCP [send


command] Button ICP7188E5 Common Variable
Output Coil
9.1 Function CodeOutput Coil (Addr:0xxxxx)
9.2 Modbus Device Address1
9.3 Relay/Register Address1
9.4 Communication Words/Bits30
10. PC-2Master TCP 7188XW
Client
11. PC-1 Ethernet 7188XW Remote
Connect
MST7188
12. 7 8

(4-39)MST7188
MST7188
Connect Remote Server

www.plcworld.cn

(4-40)Modbus_Tool Slave TCP

(4-41)Modbus_Tool Master TCP

Master TCP Slave TCP

www.plcworld.cn

8.3 OPC
OPC OPC
Trial_Modbus Trial_ModbusTCP OPC Server OPC
Server 2 Trial Version OPC Server
OPC Client
Demo7524 Modbus OPC Server COM Port
Modbus OPC Server ICP7524 Common Variable
DIDOAIAO
COM1
OPCPC COM2
OPCPC COM1
7524 COM4
7524 COM3

PC-1Win-2000

ICP7524

PC-2Win-2000

OPCTrial_Modbus

Demo7524

7188XW

OPC Sample Client

OPCTrial_Modbus
OPC Sample Client

(4-42)Demo7524 OPC

1. PC Modbus OPC Server Trial Version


\OPC\Trial_Modbus\Disk1 setup.exe
Program Shortcut [SunWare OPC Server][Modbus OPC
Server Trial Version]
2. PC-1 Modbus OPC Server Menu [Edit][Ports] Port
Properties Dialog Box COM1 9600 O 7 1 None Flow control
PC COM1 ASCII ICP7524 COM3
3. PC-2 Modbus OPC Server Menu [Edit][Ports] Port
Properties Dialog Box COM2 9600 N 8 1 None Flow control
PC COM2 RTU ICP7524 COM4
4. TXRXGND Pin TX RX GND

5. PC-2 COM1 ICP7524 COM1 7188XW


ICP7524 TXRX
GND ICP COM1 Port
6. PC-1Menu [Add][NewDevices] Device Device

www.plcworld.cn

Properties
6.1 NameDevice1
6.2 Data TypeModbus
6.3 Comm PortCOM1
6.4 Address1 ( Modbus Device Address)
6.5 TimeoutWord SwapSimulation I/O
7. PC-1 Device1 Mouse
Menu [Add][New Group] Group
8. PC-1 Device1 Group Mouse
Menu [Add][New Tag] TAG Tag
Properties
8.1 Tag1Location 2Output RegisterData Type INT properties
8.2 Tag2Location 5Output CoilData Type BIT properties
8.3 Tag3Location 15Output RegisterData Type INT properties
8.4 Tag4Location 20Output CoilData Type BIT properties
9. PC-2 6 8 Device1 Properties Comm Port
COM2
10. PC-1PC-2 configure Menu [File][Save]
test.tdb
11. PC-1PC-2 Menu [View][Monitor]
Value Bad
12. PC-1 Program Shortcut [SunWare OPC Server][OPC Sample
Client] OPC Client Menu [OPC][Connect]
Select OPC Server Dialog Box OPC Server
NameSunWareCorp.Trial_Modbus Name
13. OPC Client Menu [OPC][Add Item] Add Item Dialog Box
OPC Server DeviceGroupTag TAG
Tag
14. Mouse Tag Menu [OPC][Write Value to Item]
Write Value to Item Dialog Box [OK] Button
ICP7524 TAG
Output Coil
0 Off 0 On
15. PC-2 OPC OPC
ICP7524
16. PC-2 OPC Sample Client
OPC
17. OPC Server Background OPC Server OPC
Sample Client OPC Sample Client 12 14

www.plcworld.cn

Connect OPC Server Add Item Tag


OPC Server Background

(4-43)Trial_Mobus OPC Server

(4-44)OPC Sample Client Select OPC Server

www.plcworld.cn

(4-45)OPC Sample Client Add Item

(4-46)OPC Sample Client ()

www.plcworld.cn

Demo7188 Modbus/TCP OPC Server


Modbus/TCP OPC Server ICP7188E5 ICP7188E5
Common Variable DIDOAI
AO VB OPC Client
OPC Server

COM1

Ethernet
PC-1Win-2000

ICP7188E5

PC-2Win-2000

OPCTrial_ModbusTCP

Demo7188

7188XW

VB6OPC Client

OPCTrial_ModbusTCP

VB6OPC Client
(4-47)Demo7188 OPC

1. PC ModbusTCP OPC Server Trial Version


\OPC\Trial_ModbusTCP\Disk1 setup.exe
Program Shortcut [SunWare OPC
Server][ModbusTCP OPC Server Trial Version]
2. PC-1PC-2 ModbusTCP OPC Server Menu [Edit][IP address
& Ports] Port Properties Dialog Box Port1 IP Address
192.168.127.253 Port No. 502 ICP7188E5
3. ICP7188E5 [ip] command IP Address 192.168.127.253
4. PC-2 COM1 ICP7524 COM1 7188XW
ICP7188E5 TXRX
GND ICP COM1 Port
5. PC-1Menu [Add][NewDevices] Device Device
Properties
5.1 NameDevice1
5.2
5.3
5.4
5.5

Data TypeModbus
Comm PortPort1
Address1 ( Modbus Device Address)
TimeoutWord SwapSimulation I/O

6. PC-1 Device1 Mouse


Menu [Add][New Group] Group
7. PC-1 Device1 Group Mouse

www.plcworld.cn

Menu [Add][New Tag] TAG Tag


Properties
7.1 Tag1Location 12Output RegisterData Type INT properties
7.2 Tag2Location 15Output CoilData Type BIT properties
7.3 Tag3Location 25Output RegisterData Type INT properties
7.4 Tag4Location 30Output CoilData Type BIT properties
8. PC-2 5 7
9. PC-1PC-2 configure Menu [File][Save]
test_TCP.tdb
10. PC-1PC-2 Menu [View][Monitor]
Value Bad
11. PC-1 VB6 OPCClient_Demo Search OPC IP Address
PC IP Address [Serach OPC] Button
PC OPC Server SunWareCorp.Trial_Modbus
SunWareCorp.Trial_ModbusTCP OPC Server Name
SunWareCorp.Trial_ModbusTCP [Connect] OPC
TAG Item Name OPC Server TAG Name
12. [Sync Read] Button Sync Value
0
13. Write Value [Write
Value] Button ICP7188E5
14. UnSync Value
OPC Server Connect OPC Client
15. PC-2 VB6OPCClient_Demo
16. OPC Server Background OPC Server VB6
OPCClient_Demo OPCClient_Demo 11
14 Connect OPC Server OPC Server Background

www.plcworld.cn

(4-48)Trial_MobusTCP OPC Server

(4-49)VB6: OPCClient_Demo

www.plcworld.cn

(4-50)VB6: OPCClient_Demo ()

www.plcworld.cn

Modbus
OPC Server Client
1.1 OPC
OPC OLE for Process Control
DCSPLC

Driver MIS

Fisher-RosemountRockwell SoftwareOpto32IntellutionIntuitive Technology


Microsoft 1996 OPC Foundation
client
MS Windows OLE
COMDCOMActiveX
OPC

1.2 OPC

z Plant Floor
command

z Process Floor DCSSCADA


MIS
z Business Floor
Database
SpreadsheetMES
OPC

(A)

(B)

OPC Client

OPC Client

Ethernet

OPC Server

OPC Server

OPC Server

Vendor A

Vendor B

Vendor C

(5-1)OPC

www.plcworld.cn

z
z
z
z

OPC Server

OPC Client OPC Server


OPC Client
MS COMDCOM OPC Server

OPC Client
Client Driver OPC Server

Driver Driver OPC


Server
OPC
OPC Server


OPC Server
VBDelphiPower Builder
OPC Server

OPC OPC
Server

OPC
PC Automation
VB

OPC Automation
Interface

Wrapper
Local or Remote
OPC Server

C++

(shared by memory client)


OPC Custom Interface
Sever Data Cache

Physical Device or
Database
(5-2)OPC

www.plcworld.cn

OPC Server
Server Client OPC COM
COM OPC client/server
Client
OPC Client Server
Client
C++
OPC Server
1.3 OPC
OPC
Online Data AccessAlarm and Event HandlingHistorical
Data Access SecuritybatchHistorical alarm and event data
access
OPC COM
OPC
custom COM Interface OLE Automation Interface VB
Excel DCOM Remote Client
z Online Data Access
DeviceGroupItem
Device
Group Group
Item

DI/O Boolean AI/O


OPC Client
Polling Rate OPC
Item ValueQuality Time Stamp Value VARIANT
Boolean
Quality Bad
Time Stamp
Alarm and Event Handling Interface Alarm
Event OPC Client OPC Client
Server
Alarm AI
DI Alarm Event OPC
client
IOPCEventServer Interface OPC Client

www.plcworld.cn

OPC Event Server Alarm Event


Alarm Event Server (Filter)
Event
Server Alarm Event
Server Alarm Event
Historical Data Access

Simple Trend data servers Online


Data Access server Time Value and Quality
Complex data compression and analysis servers

1.4 Modbus OPC Server Demo System


Modbus Modbus/TCP OPC Server Trial
Version OPC Data Access V1.0 and V2.0 2
Demo OPC Server
OPC Server VB OPC
Client

(5-3)OPC Server Device Properties Dialog

www.plcworld.cn

Menu [Add][New Device] Device Properties Dialog Box


Device
Dialog Box
z NameDevice Name
z Device Type Modicon PLC Type Modbus Device
z Comm Port Comm Port 8 Port
z AddressModbus Address Modbus Device ID No.
z Timeout
z SimulationOPC Server
Modbus
OPC Client
z Word Swap Modbus 16 bit integer Protocol
High Byte Low Byte Modbus

(5-4)OPC Server Group Define Dialog

Menu [Add][New Group] Group Dialog Box


Group Name

www.plcworld.cn

(5-5)OPC Server TAG Properties Define Dialog

Menu [Add][New Tag] Tag Properties Dialog Box


TAG
Dialog Box
z NameTAG Name Group Name
z Description TAG
z Loaction and Type TAG Modbus Type Input CoilOutput
CoilInput RegisterOutput Register Location TAG
z
z
z
z

Data Type TAG


Number of bytes Byte
Scaling Range
Simulation signal SinRampRandom

Scaling Range
z Raw Min Range Low
z Raw Max Range High
z Unit
z Min Range Low
z Max Range Low

www.plcworld.cn

Conversion LinearSquare Root

(5-6)

Menu [Edit][Port]
Modbus COM Port
Port COM1 COM8
Baud Rate
ParityNoneOddEven
FlowRTSCTS
Data Bits
Stop Bits

(5-7)COM Port Define

www.plcworld.cn

Menu [Edit][IP Address & Port]

Modbus/TCP TCP/IP
PortTCP/IP Port1 Port8
IP Address Remote Modbus
Device IP Address
TCP PortModbus 502

(5-8)IP Address & Port Define

(5-9)OPC Server

www.plcworld.cn

DeviceGroupTag
Status Bar Demo 120
Demo TAG Quality Flag Bad

(5-10)OPC Server Demo Time up

Menu [View][Monitor]

Menu [File][Save] Configuration File


tdb OPC Server
OPC Client connect OPC
Server OPC Server Background OPC
Server OPC Client TAG OPC Server
Configuration File 100 TAG OPC Client 10
OPC Server 10 TAG 100
OPC
Client 20 TAG
OPC Server 20 TAG
OPC Client
OPC Server
OPC TAG
Device1.Group.Tag1
.
Menu

www.plcworld.cn

[File][New] Configuration File


[File][Open] Configuration File
[File][Save] Configuration File
[File][Save As] Configuration File File Name
[File][Export CSV] Configuration File CSV Excel
CSV TAG NameLoaction

[File][Reexport CSV] Configuration File CSV

[File][Import CSV] CSV Configuration


File TAG CSV Excel
OPC Configuration File
[File][Reimport CSV] CSV Configuration File
[Add][New Device] Device
[Add][New Group] Group
[Add][New Tag] Tag
[Add][Multiply] Copy Tag TAG
[Edit][Cut] TAG Paste
[Edit][Copy] Paste
[Edit][Paste] TAG
[Edit][Delete]
[Edit][Ports] COM Port IP Address
[Edit][Properties] DeviceGroupTag Properties Dialog Box
[View][Monitor] Group Tag
[View][Status Bar] Status Bar
1.5 VB OPC Client Demo

PLCDCS
VB Driver
OPCClient_Demo VB OPC Data Access V1.0 and
V2.0 Server
VB 6.0
z Local or Remote Server OPC Server
z TAG Item SnychronizeUnsnychronize
TAG
z TAG Quality
z TAG OPC Server

www.plcworld.cn

(5-11)OPCClient_Demo

OPCClient_Demo Trial Version OPC Server


OPCClient_Demo
z Remote Server IP Address
IP Address Local ServerSearch OPC
Button Server OPC Server Name
OPC Server Name SunWareCorp.Trial_Modbus
SunWareCorp.Trial_ModbusTCP
z List Box OPC Server Name
z

TAG Item Full Name OPC Tag ConnectButton


Box Button
Demo TAG TAG Name

OPC Tag Unsync

www.plcworld.cn

ValueQualityUpdate Time OPC Server


OPC Client
Sync ReadButton OPC Client OPC Tag
Sync Value OPC Client

Tag Write Value Tag


Write Value-1Write Value-2Write Value-3 Button
Tag OPC Server OPC Server

Tag Read Only Tag


Modbus Output CoilOutput
Register Tag
connect Demo Server connectGroupItem
OPC Handle Disconnect
Button Demo Handle Remove
OPC Server OPC Client
OPC Client Disconnect OPC Server

www.plcworld.cn

(5-12)OPCClient_Demo

www.plcworld.cn

1.6 VB OPC Client


VB Project Menu [Project][References]
Dialog Box OPC Automation 2.0\winnt\system32
OPCDAAuto.dll

(5-13) OPC Automation 2.0

OPCAPIOPC Automation 2.0


OPC Foundation http://www.opcfoundation.orgOPC Data Access 2.0
opcda20_auto.doc
OPCClient_Demo OPC
OPC OPC Client
API
Demo
z OPC OPC ObjectOPC
OPC Server OPC Server
Group Group
Group Group Item OPC Tag
OPC object
propertiesmethodevent
opcda20_auto.doc

www.plcworld.cn

Option Explicit
Option Base 1
' OPC Interface object
Dim IconServer As OPCServer ' OPC server object Server
Dim RemoteServer As OPCServer ' OPC server object OPC Server list
Dim IconGroups As OPCGroups ' collection of groups Group
Private WithEvents IconGroup As OPCGroup ' individual group Group
Dim IconItems As OPCItems 'collection of items Group Item
Dim OneItem_A As OPCItem 'Single item Write TAG Item
Dim OneItem_B As OPCItem 'Single item
Dim OneItem_C As OPCItem 'Single item
'item object Item read/write
'Public OpcItem As IOPCItem
Dim ClientHandles(3) As Long
Dim ServerHandles() As Long
Dim Errors() As Long
Dim pQuality As Variant
Dim pTimestamp As Variant
Dim ItemIDs(3) As String
Dim AccessPaths(3) As String
Dim Active(3) As Boolean
Dim bServerStarted As Boolean
Dim bReadOn As Boolean
Dim ItemCount As Integer
Dim ReadValue() As Variant
z

OPC Server List Remote Server IP Address IP


Address Local Server [Search OPC] Button
RemoteServer OPC Server Object
GetOPCServers(Node) method OPC Server List
AllOPCServers Variant for loop
AllOPCServers List Box

Private Sub Command7_Click()

www.plcworld.cn

' get remote OPC


Dim AllOPCServers As Variant
Dim Node As Variant
Dim i As Integer
Set RemoteServer = New OPCServer
Node = Text2.Text
If Node = "" Then
AllOPCServers = RemoteServer.GetOPCServers ' it is local server
Else
AllOPCServers = RemoteServer.GetOPCServers(Node) ' it is remote server
End If
For i = LBound(AllOPCServers) To UBound(AllOPCServers)
List1.AddItem AllOPCServers(i)
Next i
End Sub
z

Connect Server IconServer connect method OPC


Server IconServer properies OPCGroups
Group Set IconGroup = IconGroups.Add("Group One")
GroupGroup One
IconGroup Item Item
Item ItemID OPC Tag device1.group.tag1
Item TAG Item

Private Sub Command1_Click()


Dim Node As String
' Create opc server object
Set IconServer = New OPCServer
' Establish connection to an OPC server
Node = Text2.Text
If Node = "" Then
IconServer.Connect Form1.Text1 'connect local OPC Server
Else
IconServer.Connect Form1.Text1, Node 'connect remote OPC server

www.plcworld.cn

End If
If TypeName(IconServer) = TypeName(Nothing) Then
MsgBox "Connect Error" ' OPC Server
Return
Else
MsgBox "Connect OK"
End If
' Server group
Set IconGroups = IconServer.OPCGroups
' group group
' Group Name
Set IconGroup = IconGroups.Add("Group One")
IconGroup.IsSubscribed = True

' group Items


Set IconItems = IconGroup.OPCItems
ItemCount = 3
' Items , item
' Item ClientHandle
ItemIDs(1) = Form1.ItemID(1).Text
ClientHandles(1) = 1
ItemIDs(2) = Form1.ItemID(2).Text
ClientHandles(2) = 2
ItemIDs(3) = Form1.ItemID(3).Text
ClientHandles(3) = 3
' Item "Group one"
IconItems.AddItems ItemCount, ItemIDs, ClientHandles, ServerHandles, Errors,
pQuality, pTimestamp
' AO or DO one item write data
Set OneItem_A = IconItems.GetOPCItem(ServerHandles(1))

www.plcworld.cn

Set OneItem_B = IconItems.GetOPCItem(ServerHandles(2))


Set OneItem_C = IconItems.GetOPCItem(ServerHandles(3))

' error code


If Errors(1) <> 0 Then
MsgBox "Add Item Error"
Return 'no server
Else
MsgBox "Add Item OK"
End If

Command1.Enabled = False ' connect button


Command2.Enabled = True
' disconnect button
Command3.Enabled = True
' Sync Read button
Command4.Enabled = True
' Write value-1 button
Command5.Enabled = True
' Write value-2 button
Command6.Enabled = True
' Write value-3 button
End Sub
z

Read Item Item value VB


IconGroup.SyncRead method OPC Server
TAG value
Event Subroutine OPC Server
Subroutine Private WithEvents
IconGroup As OPCGroup Group Read
Suboutine Private Sub
IconGroup_DataChange( )

Private Sub Command3_Click()


' Read data
IconGroup.SyncRead OPCCache, ItemCount, ServerHandles, ReadValue, Errors
If Errors(1) <> 0 Then
MsgBox "Read Data Error"
Return 'no server

www.plcworld.cn

Else
MsgBox "Read Data OK"
Form1.Value(14) = ReadValue(1)
Form1.Value(15) = ReadValue(2)
Form1.Value(16) = ReadValue(3)
End If
End Sub
' Data Change Event handler fired by group subscription callback
' OPC Server OPC Client ,
' call ,
Private Sub IconGroup_DataChange(ByVal TransactionID As Long, ByVal NumItems
As Long, ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long,
TimeStamps() As Date)
' MsgBox "CallBack Data OK"
Dim i, m, n As Integer

For i = 1 To NumItems
If ClientHandles(i) > 0 Then
Form1.Value(ClientHandles(i)) = ItemValues(i)
m = 3 + ClientHandles(i)
Form1.Value(m) = Qualities(i)
n = 6 + ClientHandles(i)
Form1.Value(n) = TimeStamps(i)
End If
Next i
End Sub
z

Write Item connect Item Write method


OPC Server Driver
Item Read/Write Enabled OPC
TAG OPC Server Read/Write TAG

www.plcworld.cn

OPC Server TAG


Private Sub Command4_Click()
' Write value-1
Dim Value As Variant
Value = SetValue(0)
OneItem_A.Write Value ' AO output
End Sub
z

Disconnect Server Remove


Item Group Server Disconnect
OPC Server
OPC Client
OPC Server
OPC Client OPC Server
OPC Server
OPC Client

Private Sub Command2_Click()


Dim Error() As Long
IconItems.Remove 3, ServerHandles, Error 'remove item first
IconGroups.RemoveAll
' and then remove Group
IconServer.Disconnect ' disconnect server final
Command1.Enabled = True ' connect button
Command2.Enabled = False ' disconnect button
Command3.Enabled = False ' Sync Read button
Command4.Enabled = False ' Write value-1 button
Command5.Enabled = False ' Write value-2 button
Command6.Enabled = False ' Write value-3 button
End Sub

www.plcworld.cn

2 Gateway
PLC
PLC
RS232RS422
RS485 115Kbps
PLC
RS232 RS485
Modbus(RTU, ASCII)
PLC
PLC PLC Modbus
PC PLC
PC PC-Base Controller

Size 7524
7188E

Multi-Gateway
2.1

Multi-Gateway (1) Modbus Protocol

Modbus

Multi-Gateway

PLC

(5-14)Multi-Gateway (1)

www.plcworld.cn

PLC
PLC
PLC Modbus
Multi-Gateway PLC

PLC baud rate


Modbus(RTU, ASCII) Multi-Gateway PC

2.2

Multi-Gateway (2)
CCTV

Multi-Gateway

A-type PLC
(5-15)Multi-Gateway (2)

PLC2
PLC
PLC Multi-Gateway
PLC
PLC
baud rates Multi-Gateway PC

www.plcworld.cn

2.3

Multi-Gateway (3)Modbus 232/TCP

RS232C

RS232C

Ethernet

(5-16)Multi-Gateway (3)

z Modbus
EthernetModbus ModbusTCP
Modbus Serial Modbus Gateway

z Modbus Gateway transparent mode

z
z Power ON

www.plcworld.cn

Modbus
1 Utility

Check List

1.
1.1

RS232422485

1.2 Baud Rate

12002400480096001920038400
57600115200

1.3 Parity

NoneOddEven

1.4 Data Bits

78
Modbus RTU Format
8 bits
ASCII Format 7
bits 8 bits

1.5 Stop Bits

12

1.6 RS232 Flow Co RTS/CTSXon/XoffModemNone


ntrol
Pin Assignment
Pin Assign
1.7 RS232 Pin Assign Pin Assignment
1.8 RS422 Pin Assign
1.9 RS485 Pin Assign

RS232 15

1.10 RS232
01

PC
1.11 RS485

2. Ethernet

CRC Check error

www.plcworld.cn

2.1 IP Address

Modbus IP Address
Modbus Slave IP
Address Modbus Master Driver
Remote IP Address

2.2 IP Address

IP Address

2.3 NetMask

NetMask

2.4 TCP Port No.

Modbus Default TCP Port No. 502

2.5 Ethernet Cable

Pin

2.6 Hub or Switch

2.7

2.8

Remote Modbus Slave

2.9

2.10 Ping check

Ping

3. Modbus
3.1 Modbus Address RS485 Modbus

AddressID No.
1 247

3.2 Modbus Address

3.3
Relay/Register Modbus Output CoilInput
Type
StatusInput RegisterHolding Register
Modbus Protocol Function Code1
234561516
3.4

Gerenal Reference Register


Relay/Register Type Modbus Protocol Function Code2021

3.5

Relay/Register

Address Modbus Master Driver

3.6

Relay/Register

AddressType Modbus Master


Modbus Slave

Holding Register

Modbus

www.plcworld.cn

3.7

Modbus Message 256 bytes


Format

ASCII FormatRelay 960 Register 60


RTU FormatRelay 1920 Register 120

3.8

Type
Address
Unit

3.9 Exception Code Modbus Slave Command message


Exception

Code code
3.10 ASCII LRC error Modbus Slave
LRC
3.11 RTU CRC error Modbus Slave
CRC
3.12 RTU Message Modbus RTU Message
3.5

Modbus Driver RTU char. Timeout

4.
4.1 COM Port COM Port
4.2 Cable

Pin

4.3

RS232/422/485

Ethernet Hub or Switch

4.4 Polling Time

Modbus Master
10 millsecond

www.plcworld.cn

Modbus Master Command


Modbus Slave Respnse
Slave

4.5 Timeout check

Modbus Slave Processor


Modbus Master
Timeout
Modbus

5. Utility Program
Check

(6-1)Modbus

1.1

Pin

RS232 Pin (1) RXTXGND Pin


Flow Control

Master

Slave

25 Pin

9 Pin

RX

RX

TX

TX

GND

GND

(6-2)RS232C Pin (1)

RS232 Pin (2) RXTXGND Pin


Flow Control
RTS CTS DTRDSRDCD
Pin Pin
Pin

www.plcworld.cn

Master

Slave

25 Pin

9 Pin

RX

RX

TX

TX

GND

GND

RTS

RTS

CTS

CTS

DCD

DCD

20

DTR

DTR

DSR

DSR

(6-3)RS232C Pin (2)

Master

Slave

25 Pin

9 Pin

RX

RX

TX

TX

GND

GND

RTS

RTS

CTS

CTS

DCD

DCD

20

DTR

DTR

DSR

DSR

(6-4)RS232C Pin (3)

RS485 Pin
Master

Slave

Data +

Data +

Data -

Data -

www.plcworld.cn

(6-5)RS485 Pin

RS422 Pin
Master

Slave

RXDA -

RXDA -

RXDB +

RXDB +

TXDA -

TXDA -

TXDB +

TXDB +

(6-6)RS422 Pin

1.2 Utility Modbus

Utility Modbus
Master Slave

Modbus Master Driver Modbus Relay/Register

Modbus Slave Driver Modbus Relay/Register

HubSwitch
Utility
Modbus Slave PLCPID
RS232
Ethernet

Modbus Master utility


Windows Utility

Modbus Slave

Program

RS232/485

www.plcworld.cn

(6-7)(1)

Modbus Master Modbus Driver


RS232
Ethernet

Modbus Slave utility

PC HMI/SCADA System

ICP 75247188

Modbus Master Driver

Demo7524Demo7188

(6-8)(2)

RS485 PID
Modbus RS485
RS485 CRC check
error RS232/485
Modbus Master RS232C Port
2 Modbus
z floatlong integer Modbus Protocol Register
16 bits integer 32767 ~ 32768
floatlong integer
PID 16 bits integer float
long integer 32 bits4 bytes
Register 4 bytes
Register Address
PID Controller Register Address Modbus Slave Type
Regsiter Address

Protocol Offset

Data Type

40001

float

Set Point (SV)

40003

float

Manipulator Value
(MV)

40005

float

Control Interval (TM)

40007

float

Process Value (PV)

etc.
(6-9)Data Type

www.plcworld.cn

Modbus Master Driver Register Address


4 Register 16 bytes 4 bytes Register
z word swap 16 bits integer Modbus Protocol
High Byte Low Byte
Processor integer Modbus
Master Driver word swap
Register 4 bytes floatlong integer
Byte swap
z BCD Code 16 bits integer 4 bits
4 bits 0 ~ 9999
BCD Code

(6-10)BCD Data Type

3 Modbus
Modbus Protocol
z Modbus Protocol

http://www.modbus.org.com/default.htm
z

Modbus Protocol Modicon PLC PLC

http://www.schneider-electric.com
z OPC OPC
http://www.opcfoundation.org

www.plcworld.cn

4 Sample Program
Demo Program
\Cbuilder50\Modbus_Tool\SRC

Modbus Utility sample program source

\Cbuilder50\Modbus_Tool\Install

Modbus Utility Intsall disk

\Cbuilder50\MB_SUB\SRC

MB_SUB.DLL program source

\ICP\Demo7524

ICP 7524 Modbus sample program source

\ICP\Demo7188

ICP 7188 Modbus sample program source

\ICP\MST7524A

ICP 7524 Modbus ASCII Master/Slave


sample program source

\ICP\MST7524R

ICP 7524 Modbus RTU Master/Slave


sample program source

\ICP\MST7188

ICP 7188 Modbus TCP Master/Slave


sample program source

\OPC\Trial_Modbus

Modbus OPC Trial Version install disk

\OPC\Trial_ModbusTCP

ModbusTCP OPC Trial Version install disk

\VB6\OPCClient_Demo

OPC Client sample program source

(6-11)Sample Program

You might also like