三、DLL函数说明
modbus.DLL是王俊于2007年最新开发的基于施耐得modbus rtu 通讯协议的串口通讯链接库。modbus.DLL专业版实现了对保持寄存器40001~4XXXX区数据读写(FCN03:读、FCN16:写,FCN06写单个数据);对逻辑线圈00001~0XXXX的 读写(FCN01:读取一组线圈,FCN05:强置单线圈,FCN15强置多线圈);对输入状态10001~1XXXX的读(FCN02);对输入寄存器30001~3XXXX的读(FCN04)。
DLL中的主要函数:
ComOpen:打开串口
ComClose:关闭串口
FCN01:读取一组线圈(00001~0XXXX)
FCN02:取得一组开关输入状态数据(10001~1XXXX)
FCN03:读多个保持寄存器数据(40001~4XXXX)
FCN04:读多个输入寄存器数据(30001~3XXXX)
FCN05S:置位单线圈(00001~0XXXX)
FCN05R:复位单线圈(00001~0XXXX)
FCN06: 预置单保持寄存器数据(40001~4XXXX)
FCN15: 强置多线圈的通断数据(00001~0XXXX)
FCN16: 写多个保持寄存器数据(40001~4XXXX)
FCN16_xSet:单保持寄存器的0~15相应位的置位(40001.0-40001.15~4XXXX.0-4XXXX.15)
FCN16_xReset:单保持寄存器的0~15相应位的复位(40001.0-40001.15~4XXXX.0-4XXXX.15)
FCN16_xSetReset:单保持寄存器的0~15相应位的置复位(40001.0-40001.15~4XXXX.0-4XXXX.15),
指使相应的位短时间通断一次(约通60ms)
ComTrue:读取DLL中的串口是否备有效打开
CinBin: 字中相应的位的状态抽取
1、打开串口
Function ComOpen(nport,BaudRate,DataBits,Parity,StopBits:longint;User:Pchar):longint;stdcall;
参数:nport: 打开串口号,取值为1~8,代表COM1~COM8;
BaudRate:波特率,取值为:1200、2400、4800、9600、19200、38400;
DataBits:数据位,取值为5、6、7、8;
Parity: 校验位,取值1(代表Even)、取值2(代表Odd)、取值3(代表Mark)、取值4(代表Space)、取值5(代表None);
StopBits:停止位,取值1(代表1位停止位)、取值2(代表2位停止位)、取值3(代表1.5位停止位);
User:DLL授权用户名;
返回值:长整型,操作成功返回“1”或“2”;1表示注册授权用户,2表示用户未注册;
操作不成功返回为“0”时的原因:1)、串口不存在或被占用; 2)、DLL注册授权不正确。
注:本DLL用户不注册除了下面说明的功能限制外没有其他限制,未注册用户请使用特定用户名:wangjun。
注册用户功能上无任何限制,且将得到永久的软件使用和更新升级服务;
使用举例:
Delphi:ComOpen(1,9600,8,1,1,Pchar('wangjun')) , 打开COM1口。
VB:ComOpen(1,9600,8,1,1,"wangjun") , 打开COM1口。(注:下面的示例都以VB调用形式给出)
2、关闭串口
Function ComClose(nport:longint):longint;stdcall;
参数:nport: 串口号,取值为1~8,代表COM1~COM8;
返回值:长整型,操作成功返回“1”,否则返回“0”;
使用举例:
ComClose(1) ,关闭打开的COM1口。
3、modbus相应功能码所对应的读取功能函数。
1)、01功能码位元件的读取(读取一组线圈)
Function FCN01(nport,node,address,Count:longint):Pchar;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从00001~0XXXX地址区(逻辑线圈)值(你要读标准modbus的00001地址这个值为0000,依次类推)
Count: 读取的位元件个数,一次最多读取1000个但不能超出寻址范围;
返回值: 16进制字符串数据,字符串数据的终止符为"@";
使用举例:
FCN01(1,1,19,37),由COM1读取modbus 1号从站00020~00056(标准modbus地址)的位状态值,返回值为“CD6BB20E1B@”
则表示27~20:CD, 35~28:6B, 43~36:B2, 51~44:0E, 56~52:1B;
字节值与实际的位状态值对应参考(其他位功能函数的说明不再重复本内容):
位地址: | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 35 | 34 | 33 | 32 | 31 | 30 | 29 | 28 |
-----------------------------------------
各位赋值: | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 |
-----------------------------------------
16进制串: | C | D | 6 | B |
-----------------------------------------
不足8位的位组的状态值参考:
位地址: | 56 | 55 | 54 | 53 | 52 |
-------------
各位赋值: | 0 | 1 | 0 | 1 | 1 |
-------------
16进制串: | 1 | B |
-------------
在读取错误或不能读取的情况下返回“Error@”
注:没有注册的用户只能读取00001~00006范围的状态值;
2)、02功能码位元件的读取(取得一组开关输入状态数据)
Function FCN02(nport,node,address,Count:longint):Pchar;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从10001~1XXXX地址区(开关输入状态)值(你要读标准modbus的10001地址这个值为0000,依次类推)
Count: 读取的位元件个数,一次最多读取1000个但不能超出寻址范围;
返回值: 16进制字符串数据,字符串数据的终止符为"@";
使用举例:
FCN02(1,1,196,22),由COM1读取modbus 1号从站10197~10218(标准modbus地址)的位状态值,返回值为“ACDB35@”
则表示10204~10197:AC, 10212~10205:DB, 10218~10213:35;
在读取错误或不能读取的情况下返回“Error@”
注:没有注册的用户只能读取10001~10006范围的状态值;
3)、03功能码字元件的读取(读多个保持寄存器数据)
Function FCN03(nport,node,address,Count:longint):Pchar;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器数据)值(你要读标准modbus的40001地址这个值为0000,依次类推)
Count: 读取的位元件个数,一次最多读取60个但不能超出寻址范围;
返回值: 16进制字符串数据,字符串数据的终止符为"@";
使用举例:
FCN03(1,1,107,3),由COM1读取modbus 1号从站40108~40110(标准modbus地址)的字状态值,返回值为“022B00000064@”
则表示40108:022B, 40109:0000, 40110:0064;
在读取错误或不能读取的情况下返回“Error@”
注:没有注册的用户只能读取40001~40003范围的状态值;
4)、04功能码字元件的读取(读多个输入寄存器数据)
Function FCN04(nport,node,address,Count:longint):Pchar;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从30001~3XXXX地址区(输入寄存器数据)值(你要读标准modbus的30001地址这个值为0000,依次类推)
Count: 读取的位元件个数,一次最多读取60个但不能超出寻址范围;
返回值: 16进制字符串数据,字符串数据的终止符为"@";
使用举例:
FCN04(1,17,8,1),由COM1读取modbus 17号从站30009(标准modbus地址)的字状态值,返回值为“000A@”
则表示30009:000A;
在读取错误或不能读取的情况下返回“Error@”
注:没有注册的用户只能读取30001~30003范围的状态值;
4、modbus相应功能码所对应的写入功能函数
1)、05功能码线圈的置复位功能函数
1、线圈置位
Function FCN05S(nport,node,address:longint):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从00001~0XXXX地址区(逻辑线圈)值(你要写标准modbus的00001地址这个值为0000,依次类推)
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
使用举例:
FCN05S(1,12,15),由COM1将modbus 12号从站00013(标准modbus地址)的位状态值置1,返回值为1表示成功
注:没有注册的用户只能写入00001~00006范围的状态值;
2、线圈复位
Function FCN05R(nport,node,address:longint):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从00001~0XXXX地址区(逻辑线圈)值(你要写标准modbus的00001地址这个值为0000,依次类推)
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
使用举例:
FCN05R(1,12,15),由COM1将modbus 12号从站00013(标准modbus地址)的位状态值置0,返回值为1表示成功
注:没有注册的用户只能写入00001~00006范围的状态值;
2)、06功能码预置单保持寄存器数据功能函数
Function FCN06(nport,node,address:longint;Sendstr:pchar):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器)值(你要写标准modbus的40001地址这个值为0000,依次类推)
Sendstr: 写入字值,该值为4个一组的16进制字符串组成其取值为0000~FFFF(整数值为0~65535);
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
当要写入字值时依次排列即可。如给40001写值1000,先将1000转成16进制字符串03E8,则sendstr=03E8;
使用举例:
FCN06(1,2,2,"03E8"),由COM1给modbus 2号从站40003(标准modbus地址)的字单元写入1000(16进制03E8),返回值为1表示成功
注:没有注册的用户只能写入40001~40003范围的状态值;
(00001~0XXXX)
3)、15功能码强置多线圈的通断数据功能函数
Function FCN15(nport,node,address,Count:longint;Sendstr:pchar):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从00001~0XXXX地址区(逻辑线圈)值(你要写标准modbus的00001地址这个值为0000,依次类推)
Count: 写入位元件个数,一次最多1000个但不能超出寻址范围;
Sendstr: 给位元件写入的值按8个为一组和成字节值在写入,该值为2个一组的16进制字符串组其取值为00~FF(整数值为0~255);
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
---------- - ~ - ------
写字符串序列如: | 00 | FF | 10 | 64 | ~ | 08 | 04 |
---------- - ~ - ------
实际字符串与位地址的数值应如下表:
位地址: | 40 | 39 | 38 | 36 | 35 | 34 | 33 | 32 | 48 | 47 | 46 | 45 | 44 | 43 | 42 | 41 |
-----------------------------------------
各位赋值: | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
-----------------------------------------
16进制串: | 6 | 4 | 5 | 0 |
-----------------------------------------
使用举例:
FCN06(1,2,19,10,"CD01"),由COM1给modbus 2号从站00020~00029(标准modbus地址)10个位单元写如相应值,返回值为1表示成功
写入值的参考 27~20:CD; 29~28:01;
位地址: | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | -- | -- | -- | -- | -- | -- | 29 | 28 |
-----------------------------------------
各位赋值: | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
-----------------------------------------
16进制串: | C | D | 0 | 1 |
-----------------------------------------
注:没有注册的用户只能写入00001~00006范围的状态值;
4)、16功能码写多个保持寄存器数据功能函数
Function FCN16(nport,node,address,Count:longint;Sendstr:pchar):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器)值(你要写标准modbus的40001地址这个值为0000,依次类推)
Count: 写入字元件个数,一次最多60个但不能超出寻址范围;
Sendstr: 给字写入的值,该值为4个一组的16进制字符串组其取值为0000~FFFF(整数值为0~65535);
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
当要写入多个字值时依次排列即可。如给40001与40002写值100和1000,先将100转成16进制字符串0064、1000转成16进制字符串03E8,
则sendstr=006403E8;一次最多写64个字即字符串长应小于等于256;
---------- ---- ~ ---------
写字符串序列如: | 0064 | 03E8 | 0010 | 6004 | ~ | 0008 | 0400 |
---------- ---- ~ ---------
使用举例:
FCN16(1,2,1,"000A0102"),由COM1给modbus 2号从站40002(标准modbus地址)的字单元写入给10(16进制000A)、40003(标准modbus地址)
的字单元写入给258(16进制0102)返回值为1表示成功;
注:没有注册的用户只能写入40001~40003范围的状态值;
5)、modbus功能码16的扩展功能函数
1、单保持寄存器的0~15相应位的置位 (40001.0-40001.15~4XXXX.0-4XXXX.15)
Function FCN16_xSet(nport,node,address,Bit:longint):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器)值(你要写标准modbus的40001地址这个值为4000,依次类推)
Bit: 保持寄存器的位,取值0~15;
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
使用举例:
FCN16_xSet(1,12,2,0),由COM1将modbus 12号从站40003(标准modbus地址)的第0个位状态值置1,返回值为1表示成功
注:没有注册的用户不能使用本功能;
2、单保持寄存器的0~15相应位的复位 (40001.0-40001.15~4XXXX.0-4XXXX.15)
Function FCN16_xReset(nport,node,address,Bit:longint):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器)值(你要写标准modbus的40001地址这个值为4000,依次类推)
Bit: 保持寄存器的位,取值0~15;
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
使用举例:
FCN16_xReset(1,10,3,12),由COM1将modbus 10号从站40004(标准modbus地址)的第12个位状态值置0,返回值为1表示成功
注:没有注册的用户不能使用本功能;
3、单保持寄存器的0~15相应位的置复位 (40001.0-40001.15~4XXXX.0-4XXXX.15)指使相应的位短时间通断一次(接通约60ms)
Function FCN16_xSetReset(nport,node,address,Bit:longint):longint;stdcall;
参数:
nport: 串口号,取值为1~8,代表COM1~COM8;
node: modbus从站号,取值1~255;
address: 元件地址,取值范围从40001~4XXXX地址区(保持寄存器)值(你要写标准modbus的40001地址这个值为4000,依次类推)
Bit: 保持寄存器的位,取值0~15;
返回值: 长整数,操作成功返回1,不能写入或操作错误返回0;
使用举例:
FCN16_xSetReset(1,10,9,10),由COM1将modbus 10号从站40010(标准modbus地址)的第10个位状态值置1后约60ms再置0,返回值为1表示成功
注:没有注册的用户不能使用本功能;
四、DLL附加函数说明 (本段函数对未注册用户没有限制,完全可以使用。)
1、串口打开状态的读取
Function ComTrue(nport:longint):longint;stdcall;
参数:
noprt: 串口号,取值为1~8,代表COM1~COM8;
返回值:长整型,串口成功打开返回“1”,否则返回“0”;
这里读取是DLL有效取得了串口的控制权,如果其他程序占用(串口不存在)等原因仍返回“0”。
2、整数转换成16进制字符串 (为VC等非RAD开发环境所增设)
Function CIntToHex(Dcint,Digits:Longint):Pchar;stdcall;
参数:
Cint: 待转换整数,取值为(0~65535);
Digits: 转换的字符串位数,指定位数小于实际位数时按实际输出;
在参数错误等非法的情况下返回“Error@”
使用举例:
CIntToHex(200,2),则返回字符串“C8@”;
CIntToHex(200,4),则返回字符串“00C8@”;
CIntToHex(200,8),则返回字符串“000000C8@”;
CIntToHex(4500,4),则返回字符串“1194@”;
CIntToHex(4500,3),则返回字符串“1194@”,因为“194”不足以表示4500这个数所以按实际输出字符串“1194@”;
"@"为字符串数据的终止符。
3、16进制字符串转换成整数 (为VC等非RAD开发环境所增设)
Function CHexToInt(CHex:Pchar):Longint;stdcall;
参数:
CHex: 待转换字符串,取值为(0000~FFFF);
使用举例:
CHexToInt("03E8"),则返回整数1000;
注:在参数不正确等出错情况下返回值为“-1”。
4、抽取(0~65535)所示整数中(0~15)某个位的值
Function CinBin(CHex,Start:longint):longint;stdcall;
参数:
CHex: 待转换整数,取值为0~65535(0000~FFFF);
Start: 抽取的位,取值为(0~15);
使用举例:
CinBin(15,3),则返回值1;
CinBin(15,4),则返回值0;
CinBin(1000,6),则返回值1;
读取MB0组合成的字节值为“FC”(252)时,要读取M0.1的值时,则调用CinBin(252,1)返回值0表示M0.1的值为0。
注:在参数不正确等出错情况下返回值为“-1”。
5、返回字符串Text左边的Count个字符 (为VC等非RAD开发环境所增设)
Function CLeftStr(Text:Pchar;Count:longint):Pchar;stdcall;
参数:
Text: 字符串原型;
Count: 指定返回左侧字符串个数;
在参数错误等非法的情况下返回“Error@”
使用举例:
CleftStr("123456", 3) = "123@";
"@"为字符串数据的终止符。
6、返回字符串Text右边的Count个字符 (为VC等非RAD开发环境所增设)
Function CRightStr(Text:Pchar;Count:longint):Pchar;stdcall;
参数:
Text: 字符串原型;
Count: 指定返回右侧字符串个数
在参数错误等非法的情况下返回“Error@”
使用举例:
CRightStr("123456", 3) = "456@";
"@"为字符串数据的终止符。
7、返回字符串Text从Start开始的Count个字符 (为VC等非RAD开发环境所增设)
Function CMidStr(Text:Pchar;Start,Count:longint):Pchar;stdcall;
参数:
Text: 字符串原型;
Start: 指定返回字符串的起始位置;
Count: 指定返回字符串个数;
在参数错误等非法的情况下返回“Error@”
使用举例:
CMidStr("123456",2,3) = "234@";
"@"为字符串数据的终止符。
8、字符串Cstr开始于字符串Ostr的位置 (为VC等非RAD开发环境所增设)
Function Cinstr(Ostr,Ckstr:Pchar;Dcint:Longint):Longint;stdcall;
参数:
Ostr: 字符串原型;
Cstr: 查询的字符串;
Dcint: 设定查询字符串的起始位置,取值>=1,即最少从源字符串的第一个字符开始查询;
返回值:长整型;
使用举例:
CinStr("1Tfdg23456","2",2) = 6
注:在参数不正确等出错情况下返回值为“0”。
9、PC喇叭的报警过程函数;
Function MyBeep(SoundHz:longint):longint;stdcall;
参数:SoundHz:长整型;
返回值:长整型,操作成功返回“1”,否则返回“0”。
使用举例:
MyBeep(2000); 按2000的频率发出报警声。
DLL中关于传出字符串值的函数都以"@"为字符串函数值终止符,这是对多开发环境应用时方便用户正确读取返回字符串数据而设。
五、Delphi、VB、VC语言环境的开发使用说明
1、Delphi语言环境开发说明
在Delphi环境下将modbus.dll、serialmodbus.slip(许可文件)复制到应用程序目录下(即将上述文件与编译后的可执行文件方入同一文件内);
在工程文件的主程序窗体(pas)文件中声明:
Function ComOpen(nport,BaudRate,DataBits,Parity,StopBits:longint;User:Pchar):longint;stdcall;External'modbus.dll';
Function ComClose(nport:longint):longint;stdcall;External'modbus.dll';
Function FCN01(nport,node,address,Count:longint):Pchar;stdcall;External'modbus.dll';
Function FCN02(nport,node,address,Count:longint):Pchar;stdcall;External'modbus.dll';
Function FCN03(nport,node,address,Count:longint):Pchar;stdcall;External'modbus.dll';
Function FCN04(nport,node,address,Count:longint):Pchar;stdcall;External'modbus.dll';
Function FCN05S(nport,node,address:longint):longint;stdcall;External'modbus.dll';
Function FCN05R(nport,node,address:longint):longint;stdcall;External'modbus.dll';
Function FCN06(nport,node,address:longint;Sendstr:pchar):longint;stdcall;External'modbus.dll';
Function FCN15(nport,node,address,Count:longint;Sendstr:pchar):longint;stdcall;External'modbus.dll';
Function FCN16(nport,node,address,Count:longint;Sendstr:pchar):longint;stdcall;External'modbus.dll';
Function FCN16_xSet(nport,node,address,Bit:longint):longint;stdcall;External'modbus.dll';
Function FCN16_xReset(nport,node,address,Bit:longint):longint;stdcall;External'modbus.dll';
Function FCN16_xSetReset(nport,node,address,Bit:longint):longint;stdcall;External'modbus.dll';
Function ComTrue(nport:longint):longint;stdcall;External'modbus.dll';
Function MyBeep(SoundHz:longint):longint;stdcall;External'modbus.dll';
其它附加函数Delphi有实用函数,建议用Delphi自带函数,如需使用声明参照上例;
注:所有DLL的函数必须声明方能使用,建议本DLL的声明采用示例所示的静态声明方式。 声明后可以在程序中使用这些函数,附加函数
中除ComTrue、CinBin、MyBeep等Delphi系统自带有类似功能函数。通信时必须先使用ComOpen函数打开串口,在串口打开后可以有效操作
相关函数,为确保通信可在程序运行开始时打开串口,程序退出前关闭串口。应用程序退出之前请务必将关闭所有串口,如串口没有关闭
而退出程序将抛出异常错误。
确保应用程序在关闭释放前关闭打开的串口。解决方法,在form的OnDestroy事件中加入如下语句:
for i:=1 to 8 do
begin
if ComTrue(i)=1 then ComClose(i);
end;
在Delphi中给中给DLL中的函数传pchar值问题,建议string型转换到Pchar型采用strPCopy()函数,Pchar型转换到string型采用straps()函数,
不推荐使用直接转换法即string到Pchar类型采用Mpchar=Pchar(str),Pchar到string采用str:=Mpchar (str为string类型、Mpchar为Pchar
类型)。上述可以详细参照DEMO程序。
2、VB语言环境开发说明
在VB环境下将modbus.dll、serialmodbus.slip(许可文件)复制到应用程序目录下(即将上述文件与编译后的可执行文件方入同一文件夹内);
函数说明中给出的是Delphi的函数原型,在VB中声明时只要注意一下类型的对应即可Delphi中的longint类型对应VB中的Long类型、
Delphi中的Pchar对应VB中的String类型,下面给出主要函数的声明:
Private Declare Function ComOpen Lib "modbus.dll" (ByVal nport As Long, ByVal BaudRate As Long, ByVal DataBits As Long, ByVal Parity As Long, ByVal StopBits As Long, ByVal User As String) As Long
Private Declare Function ComClose Lib "modbus.dll" (ByVal nport As Long) As Long
Private Declare Function FCN01 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long) As String
Private Declare Function FCN02 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long) As String
Private Declare Function FCN03 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long) As String
Private Declare Function FCN04 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long) As String
Private Declare Function FCN05S Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long) As Long
Private Declare Function FCN05R Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long) As Long
Private Declare Function FCN06 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Sendstr As String) As Long
Private Declare Function FCN15 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long, ByVal Sendstr As String) As Long
Private Declare Function FCN16 Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Count As Long, ByVal Sendstr As String) As Long
Private Declare Function FCN16_xSet Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Bit As Long) As Long
Private Declare Function FCN16_xReset Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Bit As Long) As Long
Private Declare Function FCN16_xSetReset Lib "modbus.dll" (ByVal nport As Long, ByVal node As Long, ByVal address As Long, ByVal Bit As Long) As Long
Private Declare Function ComTrue Lib "modbus.dll" (ByVal nport As Long) As Long
Private Declare Function MyBeep Lib "modbus.dll" (ByVal SoundHz As Long) As Long
Private Declare Function CinBin Lib "modbus.dll" (ByVal CHex As Long, ByVal start As Long) As Long
其它附加函数VB有实用函数,建议用VB自带函数,如需使用声明参上面的例子给相应的函数声明;做完上述声明后,便可以在程序中使用
相关函数了。本DLL是串口通信库,通信时必须先使用ComOpen函数打开串口,在串口打开后可以有效操作相关函数,为保证通信可以在
程序运行开始时打开串口,程序退出前关闭串口。在应用程序关闭之前请务必将关闭所有串口,如您的程序串口没有关闭退出程序将抛
出异常。当出现这样的异常请更改您的程序,确保应用程序在关闭释放前关闭所打开的串口。
解决方法,在form的Unload事件中加入如下例:
If ComTrue(1)=1 then
ComClose(1)
End if
为确保Unload事件有效执行程序中不应使用“End”语句,而尽量使用“Unload”语句释放所有窗体,因使用“End”语句系统不会执行
正常的窗体释放等事件而直接退出程序,如程序中有form1,form2两个窗体,则使用下面语句:
Unload form1
Unload form2
VB会在所有窗体关闭后释放所有占用资源。上述可以详细参照DEMO程序。当然也可在使用“End”语句前将串口关闭也是可以释放串口的。
3、VC语言环境开发说明
在VC环境下将modbus.dll、serialmodbus.slip(许可文件)复制到应用程序目录下(即将上述文件与编译后的可执行文件方入同一文件夹内);
在VC中使用DLL一般都是采用动态声明的方式,函数说明中给出的是Delphi的函数原型,在VC中声明时只要注意一下类型的对应即可
Delphi中的longint类型对应VC中的Long类型、Delphi中的Pchar对应VC中的char* 类型,下面给出主要函数的声明:
在工程主文件cpp中声明一个句柄:
HINSTANCE m_handle;
用来标识导入的动态链接库。
1)、导入动态链接库,如例所示:
m_handle =:: LoadLibrary("modbus.dll");
2)、按下例说明声明相关各个函数:
typedef long (CALLBACK* pOpen)(long nport, long BaudRate, long DataBits, long Parity, long StopBits, char* User);
typedef long (CALLBACK* pClose)(long nport);
typedef char* (CALLBACK* pFCN01)(long nport, long node, long address, long Count);
typedef char* (CALLBACK* pFCN02)(long nport, long node, long address, long Count);
typedef char* (CALLBACK* pFCN03)(long nport, long node, long address, long Count);
typedef char* (CALLBACK* pFCN04)(long nport, long node, long address, long Count);
typedef long (CALLBACK* pFCN05S)(long nport, long node, long address);
typedef long (CALLBACK* pFCN05R)(long nport, long node, long address);
typedef long (CALLBACK* pFCN06)(long nport, long node, long address, char* Sendstr);
typedef long (CALLBACK* pFCN15)(long nport, long node, long address, long Count, char* Sendstr);
typedef long (CALLBACK* pFCN16)(long nport, long node, long address, long Count, char* Sendstr);
typedef long (CALLBACK* pFCN16_xSet)(long nport, long node, long address, long Bit);
typedef long (CALLBACK* pFCN16_xReset)(long nport, long node, long address, long Bit);
typedef long (CALLBACK* pFCN16_xSetReset)(long nport, long node, long address, long Bit);
typedef long (CALLBACK* pTrue)(long nport);
typedef char* (CALLBACK* pIntHex)(long Dcint,long Digits);
typedef long (CALLBACK* pHexInt)( char* CHex);
typedef long (CALLBACK* pBin)( long Chex, long Start);
typedef char* (CALLBACK* pLeft)( char* Text, long Count);
typedef char* (CALLBACK* pRight)( char* Text, long Count);
typedef char* (CALLBACK* pMid)( char* Text, long Start, long Count);
typedef long (CALLBACK* pinstr)( char* Ostr, char* Ckstr, Long Dcint);
typedef long (CALLBACK* pBeep)( long SoundHz);
3)、声明并建立动态链接库中的函数与新函数名的对应关系,如下:
pOpen Copen = (pOpen)GetProcAddress(m_handle,"ComOpen");
pClose Cclose = (pClose)GetProcAddress(m_handle,"ComClose");
pFCN01 CFCN01 = (pFCN01)GetProcAddress(m_handle,"FCN01");
pFCN02 CFCN02 = (pFCN02)GetProcAddress(m_handle,"FCN02");
pFCN03 CFCN03 = (pFCN03)GetProcAddress(m_handle,"FCN03");
pFCN04 CFCN04 = (pFCN04)GetProcAddress(m_handle,"FCN04");
pFCN05S CFCN05S = (pFCN05S)GetProcAddress(m_handle,"FCN05S");
pFCN05R CFCN05R = (pFCN05R)GetProcAddress(m_handle,"FCN05R");
pFCN15 CFCN15 = (pFCN15)GetProcAddress(m_handle,"FCN15");
pFCN16 CFCN16 = (pFCN16)GetProcAddress(m_handle,"FCN16");
pFCN16_xSet CFCN16_xSet = (pFCN16_xSet)GetProcAddress(m_handle,"FCN16_xSet");
pFCN16_xReset CFCN16_xReset = (pFCN16_xReset)GetProcAddress(m_handle,"FCN16_xReset");
pFCN16_xSetReset CFCN16_xSetReset = (pFCN16_xSetReset)GetProcAddress(m_handle,"FCN16_xSetReset");
pTrue Ctrue = (pTrue)GetProcAddress(m_handle," ComTrue");
pIntHex Cinthex = (pIntHex)GetProcAddress(m_handle," CIntToHex");
pHexInt Chexint = (pHexInt)GetProcAddress(m_handle," CHexToInt");
pBin Cbin = (pBin)GetProcAddress(m_handle," CinBin");
pLeft Cleft = (pLeft)GetProcAddress(m_handle," CLeftStr");
pRight Cright = (pRight)GetProcAddress(m_handle," CRightStr");
pMid Cmid= (pMid)GetProcAddress(m_handle," CMidStr");
pinstr Cinstr=(pinstr)GetProcAddress(m_handle," CinStr");
pTrue CBeep = (pBeep)GetProcAddress(m_handle," MyBeep");
注:双引号中为动态链接库中的函数名。
4)、接下来就可以自由使用动态链接库中的函数了,如:
Copen(参数略);
Cclose(参数略);
CFCN01(参数略);
CFCN02(参数略);
CFCN03(参数略);
CFCN04(参数略);
CFCN05S(参数略);
CFCN05R(参数略);
CFCN15(参数略);
CFCN16(参数略);
CFCN16_xSet(参数略);
CFCN16_xReset(参数略);
CFCN16_xSetReset(参数略);
Ctrue(参数略);
Cinthex(参数略);
Chexint(参数略);
Cbin(参数略);
Cleft(参数略);
Cright(参数略);
Cmid(参数略);
Cinstr(参数略);
CBeep(参数略);
注:函数中用到了char*型参数,这里介绍下char*与Cstring的相互转换的函数:
(1)char*->CString
char* sz;
CString str;
str.Format("%s",sz); //可以用此函数将读取的值转成字符串
(2) CString -> char*
CString str;
char* sz = str.GetBuffer(0);//可将字符串转成char*给函数赋值
5)、当不再需要使用DLL时记得关闭串口及释放动态链接库,如:
关闭串口
if cTrue(1)==1 then
{
cClose(1);
}
6)、释放DLL
FreeLibrary(m_handle);
六、详细的DLL使用请参DEMO程序,相关DEMO程序和说明所使用的开发环境VB指的是VB6.0,Delphi指的是Delphi6.0/Delphi7.0,
VC指的是VC6.0。如果使用了高版本开发环境请根据开发软件更新后所兼容的声明方式进行声明调用。VC的串口调用没DEMO程序
请参照本手册的说明进行调用(本说明的方法经过测试是可行有效的)。
DLl已经过使用和测试具有很好的稳定性(测试平台为Win2000/WinXP),目前还没有用户方面返回的缺陷报告,如果你在使用过程中发现
有什么缺陷也请和我联系,我将在最短时间内给你更新升级(更新升级只针对注册用户)。
作者: wjun7610
QQ: 157610979
淘宝店:
http://shop34821629.taobao.com