三、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