PLC论坛-全力打造可编程控制器专业技术论坛

 找回密码
 注册哦

QQ登录

只需一步,快速开始

微信扫码登录

查看: 4885|回复: 7

Modbus 通讯协议编程

[复制链接]
发表于 2006-6-12 01:49:00 | 显示全部楼层 |阅读模式
Modbus 通讯协议编程
本人最近为了实现电脑与Delta VFD-M变频器通讯,特意用VB6.0编了一个Modbus协议通讯软件,不过这只是一个测试版,但Modbus的ASCii协议和RTU协议都已经实现。现在将源程序上贴,希望可以帮助到有需要的朋友,谢谢!(我发现图片贴不上去)
另外,假如你觉得有更好的想法,欢迎E-mail指教。
附:VB6源程序

Option Explicit
Private Text1text As String
Private RTUCRC As String
'串口选择
Private Sub Combo1_Click()
MSComm1.CommPort = Combo1.ListIndex + 1
End Sub
'数据位改变
Private Sub Combo2_Click()
Call setting
End Sub
'波特率改变
Private Sub Combo3_Click()
Call setting
End Sub
'奇偶校验改变
Private Sub Combo4_Click()
Call setting
End Sub
'停止位改变
Private Sub Combo5_Click()
Call setting
End Sub
Private Sub setting()
MSComm1.Settings = CStr(Combo3.Text) & "," & CStr(Combo4.Text) & "," & CStr(Combo2.Text) _
& "," & CStr(Combo5.Text)
End Sub
'打开关闭串口
Private Sub Command1_Click()
On Error Resume Next
If MSComm1.PortOpen = False Then
MSComm1.PortOpen = True
Else
MSComm1.PortOpen = False
End If

If MSComm1.PortOpen Then '打开关闭按钮显示文字及combo1使能
Command1.Caption = "关闭串口"
Combo1.Enabled = False
Else
Command1.Caption = "打开串口"
Combo1.Enabled = True
End If

If Err Then '打开串口失败,则显示出错信息
MsgBox Error$, 48, "错误信息"
Exit Sub
End If
End Sub
'10转16进制
Private Sub Command2_Click(Index As Integer)
On Error Resume Next
Text4.Text = Hex(Text3.Text)
If Err Then ''则显示出错信息
MsgBox Error$, 48, "错误信息"
Exit Sub
End If
End Sub
'16转10进制
Private Sub Command3_Click()
Dim a As Long
a = Val("&H" & CStr(Text4.Text))
Text3.Text = a
End Sub
'手动串口发送
Private Sub Command4_Click()
If MSComm1.PortOpen = False Then
MsgBox "请先打开串口", , "错误信息"
Exit Sub
End If
Call sentsub
End Sub
'清除接收窗
Private Sub Command5_Click()
Text2.Text = ""
End Sub
Private Sub Command6_Click()
Unload Me
End Sub
Private Sub Command7_Click()
On Error Resume Next
Dim STP As String
STP = CStr(Chr(2)) & "010001" & CStr(Chr(3)) & "25"
MSComm1.Settings = "9600,N,7,2"
MSComm1.PortOpen = True
MSComm1.Output = STP
MSComm1.PortOpen = False
If Err Then '打开串口失败,则显示出错信息
MsgBox Error$, 48, "错误信息"
Exit Sub
End If
End Sub
Private Sub Command8_Click()
On Error Resume Next
Dim FWD As String
FWD = CStr(Chr(2)) & "010101" & CStr(Chr(3)) & "26"
MSComm1.Settings = "9600,N,7,2"
MSComm1.PortOpen = True
MSComm1.Output = FWD
MSComm1.PortOpen = False
If Err Then '打开串口失败,则显示出错信息
MsgBox Error$, 48, "错误信息"
Exit Sub
End If
End Sub
Private Sub Command9_Click()
On Error Resume Next
Dim REV As String
REV = CStr(Chr(2)) & "010201" & CStr(Chr(3)) & "27"
MSComm1.Settings = "9600,N,7,2"
MSComm1.PortOpen = True
MSComm1.Output = REV
MSComm1.PortOpen = False
If Err Then '打开串口失败,则显示出错信息
MsgBox Error$, 48, "错误信息"
Exit Sub
End If
End Sub
'窗口加载
Private Sub Form_Load()
Dim d%
For d = 1 To 16
Combo1.AddItem ("COM" & CStr(d))
Next
Combo1.ListIndex = 0

Combo2.AddItem "6"
Combo2.AddItem "7"
Combo2.AddItem "8"
Combo2.ListIndex = 2

Combo3.AddItem "110"
Combo3.AddItem "330"
Combo3.AddItem "1200"
Combo3.AddItem "2400"
Combo3.AddItem "4800"
Combo3.AddItem "9600"
Combo3.AddItem "19200"
Combo3.AddItem "38400"
Combo3.AddItem "56000"
Combo3.AddItem "57600"
Combo3.AddItem "115200"
Combo3.ListIndex = 5

Combo4.AddItem "n"
Combo4.AddItem "o"
Combo4.AddItem "e"
Combo4.ListIndex = 0

Combo5.AddItem "1"
Combo5.AddItem "2"
Combo5.ListIndex = 0

For d = 0 To 254
Combo6.AddItem d
Next
Combo6.ListIndex = 1

Text1.Text = "010601001770"
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""
Text5.Text = "1000"
Text6.Text = "06"
Text7.Text = "0"
Text8.Text = "1"

Option1.value = True
Option3.value = True
Option7.value = True
Option9.value = True

If MSComm1.PortOpen = False Then
Command1.Caption = "打开串口"
Else
Command1.Caption = "关闭串口"
End If
End Sub
'串口接收程序
Private Sub MSComm1_OnComm()
Dim Hexchr As String, hexstring As String, i As Integer, j As Integer, hexdisp As String
If Option8.value Then
hexstring = MSComm1.Input '十六进制显示
i = Len(hexstring)
For j = 1 To i
Hexchr = Mid(hexstring, j, 1)
If Hex(Asc(Hexchr)) < 16 Then
Text2.Text = Text2.Text & "0" & Hex(Asc(Hexchr)) & " "
Else
Text2.Text = Text2.Text & Hex(Asc(Hexchr)) & " "
End If
Next j
Text2.Text = Text2.Text & CStr(Chr(13)) & CStr(Chr(10))
Else
Text2.Text = Text2.Text & MSComm1.Input & CStr(Chr(13)) & CStr(Chr(10)) 'ASCII码显示
End If
End Sub
'手动发送选择
Private Sub Option1_Click()
If Option1.value = True Then
Timer1.Enabled = False
Command4.Enabled = True
Else
Timer1.Enabled = True
Command4.Enabled = False
End If
End Sub
'Delta ASCII发送协议
Private Sub Option10_Click()
Combo6.Enabled = True
Text6.Enabled = True
Text7.Enabled = True
Text8.Enabled = True
Label10.Enabled = True
Label11.Enabled = True
Label12.Enabled = True
Label13.Enabled = True
Option6.Enabled = False
Option7.Enabled = False
Option11.value = True
Combo2.ListIndex = 1
Combo5.ListIndex = 1
Text1.Enabled = False
Label14.Enabled = False
Frame7.Visible = True
End Sub

'自动发送选择
Private Sub Option2_Click()
If Option2.value = True Then
Timer1.Enabled = True
Command4.Enabled = False
Else
Timer1.Enabled = False
Command4.Enabled = True
End If
End Sub
Private Sub Option3_Click() 'Non选项
Combo6.Enabled = False
Text6.Enabled = False
Text7.Enabled = False
Text8.Enabled = False
Label10.Enabled = False
Label11.Enabled = False
Label12.Enabled = False
Label13.Enabled = False
Option6.Enabled = True
Option7.Enabled = True
Combo2.ListIndex = 2
Combo5.ListIndex = 0
Text1.Enabled = True
Label14.Enabled = True
Frame7.Visible = False
End Sub
Private Sub Option4_Click() 'ASCII选项
Combo6.Enabled = True
Text6.Enabled = True
Text7.Enabled = True
Text8.Enabled = True
Label10.Enabled = True
Label11.Enabled = True
Label12.Enabled = True
Label13.Enabled = True
Option6.Enabled = False
Option7.Enabled = False
Combo2.ListIndex = 1
Combo5.ListIndex = 1
Text1.Enabled = False
Label14.Enabled = False
Frame7.Visible = False
End Sub
Private Sub Option5_Click() 'RTU选项
Combo6.Enabled = True
Text6.Enabled = True
Text7.Enabled = True
Text8.Enabled = True
Label10.Enabled = True
Label11.Enabled = True
Label12.Enabled = True
Label13.Enabled = True
Option6.Enabled = False
Option7.Enabled = False
Combo2.ListIndex = 2
Combo5.ListIndex = 1
Text1.Enabled = False
Label14.Enabled = False
Frame7.Visible = False
End Sub
'发送时间间隔调整输入
Private Sub Text5_Change()
Dim number As String
Dim num As Integer
Dim numcyc As Integer
num = Len(Text5.Text)
For numcyc = 1 To num
number = Mid(Text5.Text, numcyc, 1)
Select Case InStr("0123456789", number)
Case 0
MsgBox "输入时间间隔错误,请重新输入", , "错误信息"
Exit Sub
End Select
Next
Timer1.Interval = Text5.Text
End Sub
'自动发送定时器
Private Sub Timer1_Timer()
If MSComm1.PortOpen Then
Call sentsub
End If
End Sub
'状态刷新定时器
Private Sub Timer2_Timer()
StatusBar1.Panels(1).Text = "串口选择:" & CStr(Combo1.Text)
StatusBar1.Panels(2).Text = "串口设置:" & CStr(MSComm1.Settings)
StatusBar1.Panels(3).Text = "串口状态:" & CStr(MSComm1.PortOpen)
End Sub

回复

使用道具 举报

 楼主| 发表于 2006-6-12 01:49:00 | 显示全部楼层
\'串口发送子程序
Private Sub sentsub()
Dim optioncase%
If Option3.value Then optioncase = 1
If Option4.value Then optioncase = 2
If Option5.value Then optioncase = 3
If Option10.value Then optioncase = 4
Select Case optioncase
Case 1
If Option6.value Then
Text1text = Text1.Text
Call Hexsent
Else
Text1text = Text1.Text
Call ASCIIsent
End If
Case 2
Call incorporate \'将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串
Call ASCIIcheck
Call ASCIIsent
Case 3
Call incorporate \'将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串
Call RTUcheck
Call Hexsent
Case 4
Call incorporate1 \'将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串
Call deltaASCII
Call ASCIIsent
End Select
End Sub
\'十六进制发送
Private Sub Hexsent()
Dim hexchrlen%, Hexchr As String, hexcyc%, hexmid As Byte, hexmiddle As String
Dim hexchrgroup() As Byte, i As Integer
hexchrlen = Len(Text1text)
For hexcyc = 1 To hexchrlen \'检查Text1文本框内数值是否合适
Hexchr = Mid(Text1text, hexcyc, 1)
If InStr(\"0123456789ABCDEFabcdef\", Hexchr) = 0 Then
MsgBox \"无效的数值,请重新输入\", , \"错误信息\"
Exit Sub
End If
Next
ReDim hexchrgroup(1 To hexchrlen \\ 2) As Byte
For hexcyc = 1 To hexchrlen Step 2 \'将文本框内数值分成两个、两个
i = i + 1
Hexchr = Mid(Text1text, hexcyc, 2)
hexmid = Val(\"&H\" & CStr(Hexchr))
hexchrgroup(i) = hexmid
\'MSComm1.Output = CStr(hexmid)
Next
MSComm1.Output = hexchrgroup
End Sub
\'ASC码发送
Private Sub ASCIIsent()
MSComm1.Output = Text1text
End Sub
\'ASC校验,此段程序计算出LRC校验值,并加上字头和字尾
Private Sub ASCIIcheck()
Dim a%, b%, chrnum%, Lrcbyte As String
Dim checksum%, char%, AscLrc%, Lrc%

chrnum = Len(Text1text)
For a = 1 To chrnum Step 2
char = Val(\"&H\" & CStr(Mid(Text1text, a, 2))) \'两个两个的取字符
checksum = checksum + char \'全部加起来
Next
AscLrc = checksum Mod &H100 \'取255的余数
Lrc = (&HFF - AscLrc) + 1 \'取二次补
If Lrc < 16 Then \'此段程序是判断Hex(lrc)是否是一位数,
Lrcbyte = \"0\" + CStr(Hex(Lrc)) \'如果是的话,前面加0;否则不加零
Else
Lrcbyte = CStr(Hex(Lrc))
End If
Text1text = CStr(Chr(58)) & CStr(Text1text) & Lrcbyte & CStr(Chr(13)) & CStr(Chr(10))
End Sub
\'DeltaASCII校验,此段程序计算出LRC校验值,并加上字头和字尾
Private Sub deltaASCII()
Dim a%, b%, chrnum%, Lrcbyte As String
Dim checksum%, char%, Lrc%

chrnum = Len(Text1text)
For a = 1 To chrnum
char = Asc(Mid(Text1text, a, 1)) \'两个两个的取字符
checksum = checksum + char \'全部加起来
Next
Lrc = (checksum + &H3) Mod &H100 \'取255的余数
If Lrc < 16 Then \'此段程序是判断Hex(lrc)是否是一位数,
Lrcbyte = \"0\" + CStr(Hex(Lrc)) \'如果是的话,前面加0;否则不加零
Else
Lrcbyte = CStr(Hex(Lrc))
End If
Text1text = CStr(Chr(2)) & CStr(Text1text) & CStr(Chr(3)) & Lrcbyte
End Sub

\'RTU校验
Private Sub RTUcheck()
Dim CRC() As Byte
Dim d(5) As Byte
Dim string1 As String
Dim j As Integer, chrlength As Integer, temp As String

string1 = Text1text
chrlength = Len(string1)
For j = 0 To chrlength / 2 - 1
temp = Mid(string1, j * 2 + 1, 2)
d(j) = Val(\"&H\" & temp)
Next
RTUCRC = CRC16(d) \'调用CRC16计算函数, CRC(0)为高位, CRC(1)为低位
Text1text = Text1text & RTUCRC
End Sub
Private Sub incorporate() \'将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串
Dim wholechar As String, wc%, wcyc%, wchar As String
Dim SID As String, Cmd As String, InfoAdd As String, data As String
Dim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%

On Error Resume Next
wholechar = CStr(Combo6.Text) & CStr(Text6.Text) & CStr(Text7.Text) & CStr(Text8.Text)
wc = Len(wholechar)
For wcyc = 1 To wc
wchar = Mid(wholechar, wcyc, 1)
If InStr(\"0123456789\", wchar) = 0 Then
MsgBox \"输入错误,请重新输入\", , \"错误提示\"
Exit Sub
End If
Next

SIDnum = Len(CStr(Hex(Combo6.Text)))
Select Case SIDnum
Case 0
Exit Sub
Case 1
SID = \"0\" & CStr(Hex(Combo6.Text))
Case 2
SID = CStr(Hex(Combo6.Text))
End Select

Cmdnum = Len(CStr(Hex(Text6.Text)))
Select Case Cmdnum
Case 0
Exit Sub
Case 1
Cmd = \"0\" & CStr(Hex(Text6.Text))
Case 1
Cmd = CStr(Hex(Text6.Text))
End Select

InfoAddNum = Len(CStr(Hex(Text7.Text)))
Select Case InfoAddNum
Case 0
Exit Sub
Case 1
InfoAdd = \"000\" & CStr(Hex(Text7.Text))
Case 2
InfoAdd = \"00\" & CStr(Hex(Text7.Text))
Case 3
InfoAdd = \"0\" & CStr(Hex(Text7.Text))
Case 4
InfoAdd = CStr(Hex(Text7.Text))
End Select

Datanum = Len(CStr(Hex(Text8.Text)))
Select Case Datanum
Case 0
Exit Sub
Case 1
data = \"000\" & CStr(Hex(Text8.Text))
Case 2
data = \"00\" & CStr(Hex(Text8.Text))
Case 3
data = \"0\" & CStr(Hex(Text8.Text))
Case 4
data = CStr(Hex(Text8.Text))
End Select

If Err Then \'显示出错信息
MsgBox Error$, 48, \"错误信息\"
Exit Sub
End If
Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)
End Sub
Private Sub incorporate1() \'将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串
Dim wholechar As String, wc%, wcyc%, wchar As String
Dim SID As String, Cmd As String, InfoAdd As String, data As String
Dim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%

On Error Resume Next
wholechar = CStr(Combo6.Text) & CStr(Text7.Text) & CStr(Text8.Text)
wc = Len(wholechar)
For wcyc = 1 To wc
wchar = Mid(wholechar, wcyc, 1)
If InStr(\"0123456789\", wchar) = 0 Then
MsgBox \"输入错误,请重新输入\", , \"错误提示\"
Exit Sub
End If
Next

SIDnum = Len(CStr(Hex(Combo6.Text)))
Select Case SIDnum
Case 0
Exit Sub
Case 1
SID = \"0\" & CStr(Hex(Combo6.Text))
Case 2
SID = CStr(Hex(Combo6.Text))
End Select

\'Cmdnum = Len(CStr(Hex(Text6.Text)))
\'Select Case Cmdnum
\'Case 0
\' Exit Sub
\'Case 1
\' Cmd = \"0\" & CStr(Hex(Text6.Text))
\'Case 1
\' Cmd = CStr(Hex(Text6.Text))
\'End Select

InfoAddNum = Len(CStr(Hex(Text7.Text)))
Select Case InfoAddNum
Case 0
Exit Sub
Case 1
InfoAdd = \"0\" & CStr(Hex(Text7.Text))
Case 2
InfoAdd = CStr(Hex(Text7.Text))
End Select

Datanum = Len(CStr(Hex(Text8.Text)))
Select Case Datanum
Case 0
Exit Sub
Case 1
data = \"000\" & CStr(Hex(Text8.Text))
Case 2
data = \"00\" & CStr(Hex(Text8.Text))
Case 3
data = \"0\" & CStr(Hex(Text8.Text))
Case 4
data = CStr(Hex(Text8.Text))
End Select

If Err Then \'显示出错信息
MsgBox Error$, 48, \"错误信息\"
Exit Sub
End If

If Option11.value Then
Cmd = \"08\"
Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd)
Else
Cmd = \"07\"
Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)
End If

End Sub
Private Function CRC16(data() As Byte) As String
Dim CRC16Lo As Byte, CRC16Hi As Byte \'CRC寄存器
Dim CL As Byte, CH As Byte \'多项式码&HA001
Dim CRCLo As String, CRCHi As String
Dim SaveHi As Byte, SaveLo As Byte
Dim i As Integer
Dim Flag As Integer
CRC16Lo = &HFF
CRC16Hi = &HFF
CL = &H1
CH = &HA0
For i = 0 To UBound(data)
CRC16Lo = CRC16Lo Xor data(i) \'每一个数据与CRC寄存器进行异或
For Flag = 0 To 7
SaveHi = CRC16Hi
SaveLo = CRC16Lo
CRC16Hi = CRC16Hi \\ 2 \'高位右移一位
CRC16Lo = CRC16Lo \\ 2 \'低位右移一位
If ((SaveHi And &H1) = &H1) Then \'如果高位字节最后一位为1
CRC16Lo = CRC16Lo Or &H80 \'则低位字节右移后前面补1
End If \'否则自动补0
If ((SaveLo And &H1) = &H1) Then \'如果LSB为1,则与多项式码进行异或
CRC16Hi = CRC16Hi Xor CH
CRC16Lo = CRC16Lo Xor CL
End If
Next Flag
Next i
If Len(Hex(CRC16Hi)) = 1 Then
CRCHi = \"0\" + Hex(CRC16Hi)
Else
CRCHi = Hex(CRC16Hi)
End If
If Len(Hex(CRC16Lo)) = 1 Then
CRCLo = \"0\" + Hex(CRC16Lo)
Else
CRCLo = Hex(CRC16Lo)
End If
CRC16 = CRCLo + CRCHi
End Function

回复 支持 反对

使用道具 举报

发表于 2007-5-16 20:13:00 | 显示全部楼层
有点难,学习中
回复 支持 反对

使用道具 举报

发表于 2008-5-16 22:00:00 | 显示全部楼层
有点难,有带注释的源程序下载吗?
回复 支持 反对

使用道具 举报

发表于 2009-6-1 15:59:00 | 显示全部楼层
直接把工程传上来吧
回复 支持 反对

使用道具 举报

发表于 2009-11-6 09:52:00 | 显示全部楼层

上传工程吧,楼主。谢谢了。

回复 支持 反对

使用道具 举报

发表于 2010-8-6 12:24:00 | 显示全部楼层
正在研究中
回复 支持 反对

使用道具 举报

发表于 2011-8-16 16:10:00 | 显示全部楼层
研究
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册哦

本版积分规则

QQ|小黑屋|手机版|Archiver|PLC技术网-PLC论坛 ( 粤ICP备17165530号 )|网站地图

GMT+8, 2024-4-19 02:07 , Processed in 0.053756 second(s), 26 queries .

快速回复 返回顶部 返回列表