VB编写的Modbus RTU协议通讯源程序

合集下载

用VB编写modbus源代码的过程

用VB编写modbus源代码的过程

用VB编写modbus源代码的过程今天是周六,现在刚从单位自愿加班回来。

为什么自愿加班呢?因为自己和老板夸下海口说:一个礼拜把modbus上位机程序写好(也就是这个礼拜拉)。

现在终于把这个程序写好拉。

感想很多啊!该如何说起呢?我语文不好,把自己想表达的意思说出来就行拉。

首先:还是那句话:一切得靠自己!上周一时,老板说让我做个modbus界面,我想:这个简单啊。

不就是串口收发么?于是我计划安排上写了1个礼拜搞定。

然后开始安装DELPHI(我在单位一直搞C编程,机子没有装这些),完后就打开我那曾经熟悉的界面。

恩?怎么看似熟悉的界面怎么这么陌生呢/于是上网找资料。

这个3天的期间我感慨好深啊:因为我大四学习的DELPHI,所以我感觉这个还熟悉点,可是当时做课程设计的时候也没有用过串口,这个串口编程咋得和MCU串口不一样呢?它就是不一样!晕晕。

上网找SPCOMM。

,学习了一天也不会用。

于是徒劳了3天也没有效果。

转眼就到了周四,我心里那个急呀。

唉!还是忍痛抛弃delphi吧!为什么呢?它没有自带串口控件,下载并安装了还是出错啊。

VB好象是我大二学的,具体时间我也忘了,反正就记得做课设的时候用它连个ACCESS实现了插入删除查询工作。

以后知道这个周四我也没有用过,甚至没有见到过它的界面。

我选择它一个因为我选择,我喜欢。

更重要的是它安装了自带串口控件,不用下载什么的了,用起来实打实的心里有底。

大家现在知道我的底子了吧?周四我借公司里的一本VB书看了一天的串口,然后心理有底了,周五动手一天,收获很大,今天早晨8点起床,心理还琢磨着程序的事情,由于家里没有实验仪器,于是打算去公司,一直做到现在,终于搞定拉。

这个礼拜上网找源代码的时候看着好多像我一样找源码的人发帖子要源程序,但是大多只是网页写了一大堆代码。

没有用!为什么呢?你怎么知道人家用什么控件,什么功能呢?还是老老实实的自己写吧。

没什么的,很简单的啊。

说实话,这个程序只要你把浮躁的心放下来写就可以了。

Modbus 通讯协议编程(VB源代码)

Modbus 通讯协议编程(VB源代码)

最近,本人为了实现电脑与Delta V FD-M变频器通讯,特意用VB6.0编了一个Modbus协议通讯软件。

这只是一个测试版,但Modbus的ASCII协议和RTU协议都已经实现。

现在将源程序上传,希望可以帮助到有需要的朋友,谢谢!另外,假如你觉得有更好的想法,欢迎指教。

如果对本程序有任何意见和建议,也可以一起讨论,共同进步。

大家多多支持俺啊。

附:VB6源程序Option ExplicitPrivate Text1text As StringPrivate RTUCRC As String'串口选择Private Sub Combo1_Click()mPort = Combo1.ListIndex + 1End Sub'数据位改变< span style="color: #008000;">Private Sub Combo2_Click()Call settingEnd Sub'波特率改变< span style="color: #008000;">Private Sub Combo3_Click()Call settingEnd Sub'奇偶校验改变< span style="color: #008000;">Private Sub Combo4_Click()Call settingEnd Sub'停止位改变< span style="color: #008000;">Private Sub Combo5_Click()Call settingPrivate Sub setting()MSComm1.Settings = CStr(Combo3.Text) & ","& CStr(Combo4.Text) & ","& CStr(C ombo2.Text) _& ","& CStr(Combo5.Text)End Sub'打开关闭串口< span style="color: #008000;">Private Sub Command1_Click()On Error Resume NextIf MSComm1.PortOpen = False ThenMSComm1.PortOpen = TrueElseMSComm1.PortOpen = FalseEnd IfIf MSComm1.PortOpen Then'打开关闭按钮显示文字及combo1使能Command1.Caption = "关闭串口"Combo1.Enabled = FalseElseCommand1.Caption = "打开串口"Combo1.Enabled = TrueEnd IfIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd Sub'10转16进制< span style="color: #008000;">Private Sub Command2_Click(Index As Integer)On Error Resume NextText4.Text = Hex(Text3.Text)If Err Then''则显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd If'16转10进制< span style="color: #008000;">Private Sub Command3_Click()Dim a As Longa = Val("&H"& CStr(Text4.Text))Text3.Text = aEnd Sub'手动串口发送< span style="color: #008000;">Private Sub Command4_Click()If MSComm1.PortOpen = False ThenMsgBox"请先打开串口< span style="color: #800000;">", , "错误信息" Exit SubEnd IfCall sentsubEnd Sub'清除接收窗< span style="color: #008000;">Private Sub Command5_Click()Text2.Text = ""End SubPrivate Sub Command6_Click()Unload MeEnd SubPrivate Sub Command7_Click()On Error Resume NextDim STP As StringSTP = CStr(Chr(2)) & "010001"& CStr(Chr(3)) & "25"MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = STPMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd SubPrivate Sub Command8_Click()On Error Resume NextDim FWD As StringFWD = CStr(Chr(2)) & "010101"& CStr(Chr(3)) & "26" MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = FWDMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd SubPrivate Sub Command9_Click()On Error Resume NextDim REV As StringREV = CStr(Chr(2)) & "010201"& CStr(Chr(3)) & "27" MSComm1.Settings = "9600,N,7,2"MSComm1.PortOpen = TrueMSComm1.Output = REVMSComm1.PortOpen = FalseIf Err Then'打开串口失败,则显示出错信息MsgBox Error$, 48, "错误信息"Exit SubEnd IfEnd Sub'窗口加载Private Sub Form_Load()Dim d%For d = 1To16Combo1.AddItem ("COM"& CStr(d))NextCombo1.ListIndex = 0Combo2.AddItem "6"Combo2.AddItem "7"Combo2.AddItem "8"Combo2.ListIndex = 2Combo3.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 = 5Combo4.AddItem "n" Combo4.AddItem "o" Combo4.AddItem "e" Combo4.ListIndex = 0Combo5.AddItem "1" Combo5.AddItem "2" Combo5.ListIndex = 0For d = 0To254Combo6.AddItem dNextCombo6.ListIndex = 1Text1.Text = "010*********" Text2.Text = ""Text3.Text = ""Text4.Text = ""Text5.Text = "1000"Text6.Text = "06"Text7.Text = "0"Text8.Text = "1"Option1.value = TrueOption3.value = TrueOption7.value = TrueOption9.value = TrueIf MSComm1.PortOpen = False ThenCommand1.Caption = "打开串口"ElseCommand1.Caption = "关闭串口"End IfEnd Sub'串口接收程序< span style="color: #008000;">Private Sub MSComm1_OnComm()Dim Hexchr As String, hexstring As String, i As Integer, j As Integer, hexdisp As Str ingIf Option8.value Thenhexstring = MSComm1.Input '十六进制显示< span style="color: #008000;">i = Len(hexstring)For j = 1To iHexchr = Mid(hexstring, j, 1)If Hex(Asc(Hexchr)) < 16ThenText2.Text = Text2.Text & "0"& Hex(Asc(Hexchr)) & " "ElseText2.Text = Text2.Text & Hex(Asc(Hexchr)) & " "End IfNext jText2.Text = Text2.Text & CStr(Chr(13)) & CStr(Chr(10))ElseText2.Text = Text2.Text & MSComm1.Input & CStr(Chr(13)) & CStr(Chr(10)) 'ASCII 码显示< span style="color: #008000;">End IfEnd Sub'手动发送选择< span style="color: #008000;">Private Sub Option1_Click()If Option1.value = True ThenTimer1.Enabled = FalseCommand4.Enabled = TrueElseTimer1.Enabled = TrueCommand4.Enabled = FalseEnd IfEnd Sub'Delta ASCII发送协议Private Sub Option10_Click()Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseOption11.value = TrueCombo2.ListIndex = 1Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = TrueEnd Sub'自动发送选择< span style="color: #008000;"> Private Sub Option2_Click()If Option2.value = True ThenTimer1.Enabled = TrueCommand4.Enabled = FalseElseTimer1.Enabled = FalseCommand4.Enabled = TrueEnd IfEnd SubPrivate Sub Option3_Click() 'Non选项< span style="color: #008000;"> Combo6.Enabled = FalseText6.Enabled = FalseText7.Enabled = FalseText8.Enabled = FalseLabel10.Enabled = FalseLabel11.Enabled = FalseLabel12.Enabled = FalseLabel13.Enabled = FalseOption6.Enabled = TrueOption7.Enabled = TrueCombo2.ListIndex = 2Combo5.ListIndex = 0Text1.Enabled = TrueLabel14.Enabled = TrueFrame7.Visible = FalseEnd SubPrivate Sub Option4_Click() 'ASCII选项< span style="color: #008000;"> Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseCombo2.ListIndex = 1Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = FalseEnd SubPrivate Sub Option5_Click() 'RTU选项< span style="color: #008000;"> Combo6.Enabled = TrueText6.Enabled = TrueText7.Enabled = TrueText8.Enabled = TrueLabel10.Enabled = TrueLabel11.Enabled = TrueLabel12.Enabled = TrueLabel13.Enabled = TrueOption6.Enabled = FalseOption7.Enabled = FalseCombo2.ListIndex = 2Combo5.ListIndex = 1Text1.Enabled = FalseLabel14.Enabled = FalseFrame7.Visible = FalseEnd Sub'发送时间间隔调整输入< span style="color: #008000;">Private Sub Text5_Change()Dim number As StringDim num As IntegerDim numcyc As Integernum = Len(Text5.Text)For numcyc = 1To numnumber = Mid(Text5.Text, numcyc, 1)Select Case InStr("0123456789", number)Case0MsgBox"输入时间间隔错误,请重新输入", , "错误信息"Exit SubEnd SelectNextTimer1.Interval = Text5.TextEnd Sub'自动发送定时器< span style="color: #008000;">Private Sub Timer1_Timer()If MSComm1.PortOpen ThenCall sentsubEnd IfEnd Sub'状态刷新定时器< span style="color: #008000;">Private Sub Timer2_Timer()StatusBar1.Panels(1).Text = "串口选择:< span style="color: #800000;">" & CStr(Comb o1.Text)StatusBar1.Panels(2).Text = "串口设置:< span style="color: #800000;">" & CStr(MSC omm1.Settings)StatusBar1.Panels(3).Text = "串口状态:< span style="color: #800000;">" & CStr(MSC omm1.PortOpen)End Sub'串口发送子程序Private Sub sentsub()Dim optioncase%If Option3.value Then optioncase = 1If Option4.value Then optioncase = 2If Option5.value Then optioncase = 3If Option10.value Then optioncase = 4Select Case optioncaseCase1If Option6.value ThenText1text = Text1.TextCall HexsentElseText1text = Text1.TextCall ASCIIsentEnd IfCase2Call incorporate '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call ASCIIcheckCall ASCIIsentCase3Call incorporate '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call RTUcheckCall HexsentCase4Call incorporate1 '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Call deltaASCIICall ASCIIsentEnd SelectEnd Sub'十六进制发送< span style="color: #008000;">Private Sub Hexsent()Dim hexchrlen%, Hexchr As String, hexcyc%, hexmid As Byte, hexmiddle As String Dim hexchrgroup() As Byte, i As Integerhexchrlen = Len(Text1text)For hexcyc = 1To hexchrlen '检查Text1文本框内数值是否合适Hexchr = Mid(Text1text, hexcyc, 1)If InStr("0123456789ABCDEFabcdef", Hexchr) = 0ThenMsgBox"无效的数值,请重新输入< span style="color: #800000;">", , "错误信息" Exit SubEnd IfNextReDim hexchrgroup(1To hexchrlen \ 2) As ByteFor hexcyc = 1To hexchrlen Step2'将文本框内数值分成两个、两个i = i + 1Hexchr = Mid(Text1text, hexcyc, 2)hexmid = Val("&H"& CStr(Hexchr))hexchrgroup(i) = hexmid'MSComm1.Output = CStr(hexmid)NextMSComm1.Output = hexchrgroupEnd Sub'ASC码发送< span style="color: #008000;">Private Sub ASCIIsent()MSComm1.Output = Text1textEnd Sub'ASC校验,此段程序计算出LRC校验值,并加上字头和字尾Private Sub ASCIIcheck()Dim a%, b%, chrnum%, Lrcbyte As StringDim checksum%, char%, AscLrc%, Lrc%chrnum = Len(Text1text)For a = 1To chrnum Step2char= Val("&H"& CStr(Mid(Text1text, a, 2))) '两个两个的取字符< span style="color: #008000;">checksum = checksum + char'全部加起来< span style="color: #008000;">NextAscLrc = checksum Mod&H100 '取255的余数< span style="color: #008000;">Lrc = (&HFF - AscLrc) + 1'取二次补If Lrc < 16Then'此段程序是判断Hex(lrc)是否是一位数,Lrcbyte = "0"+ CStr(Hex(Lrc)) '如果是的话,前面加0;否则不加零ElseLrcbyte = CStr(Hex(Lrc))End IfText1text = CStr(Chr(58)) & CStr(Text1text) & Lrcbyte & CStr(Chr(13)) & CStr(Chr(1 0))End Sub'DeltaASCII校验,此段程序计算出LRC校验值,并加上字头和字尾Private Sub deltaASCII()Dim a%, b%, chrnum%, Lrcbyte As StringDim checksum%, char%, Lrc%chrnum = Len(Text1text)For a = 1To chrnumchar= Asc(Mid(Text1text, a, 1)) '两个两个的取字符< span style="color: #008000;"> checksum = checksum + char'全部加起来< span style="color: #008000;">NextLrc = (checksum + &H3) Mod&H100 '取255的余数< span style="color: #008000;"> If Lrc < 16Then'此段程序是判断Hex(lrc)是否是一位数,Lrcbyte = "0"+ CStr(Hex(Lrc)) '如果是的话,前面加0;否则不加零ElseLrcbyte = CStr(Hex(Lrc))End IfText1text = CStr(Chr(2)) & CStr(Text1text) & CStr(Chr(3)) & LrcbyteEnd Sub'RTU校验< span style="color: #008000;">Private Sub RTUcheck()Dim CRC() As ByteDim d(5) As ByteDim string1 As StringDim j As Integer, chrlength As Integer, temp As Stringstring1 = Text1textchrlength = Len(string1)For j = 0To chrlength / 2- 1temp = Mid(string1, j * 2+ 1, 2)d(j) = Val("&H"& temp)NextRTUCRC = CRC16(d) '调用CRC16计算函数, CRC(0)为高位, CRC(1)为低位Text1text = Text1text & RTUCRCEnd SubPrivate Sub incorporate() '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Dim wholechar As String, wc%, wcyc%, wchar As StringDim SID As String, Cmd As String, InfoAdd As String, data As StringDim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%On Error Resume Nextwholechar = CStr(Combo6.Text) & CStr(Text6.Text) & CStr(Text7.Text) & CStr(Text8.T ext)wc = Len(wholechar)For wcyc = 1To wcwchar = Mid(wholechar, wcyc, 1)If InStr("0123456789", wchar) = 0ThenMsgBox"输入错误,请重新输入< span style="color: #800000;">", , "错误提示"Exit SubEnd IfNextSIDnum = Len(CStr(Hex(Combo6.Text)))Select Case SIDnumExit SubCase1SID = "0"& CStr(Hex(Combo6.Text)) Case2SID = CStr(Hex(Combo6.Text))End SelectCmdnum = Len(CStr(Hex(Text6.Text))) Select Case CmdnumCase0Exit SubCase1Cmd = "0"& CStr(Hex(Text6.Text)) Case1Cmd = CStr(Hex(Text6.Text))End SelectInfoAddNum = Len(CStr(Hex(Text7.Text))) Select Case InfoAddNumCase0Exit SubCase1InfoAdd = "000"& CStr(Hex(Text7.Text)) Case2InfoAdd = "00"& CStr(Hex(Text7.Text)) Case3InfoAdd = "0"& CStr(Hex(Text7.Text)) Case4InfoAdd = CStr(Hex(Text7.Text))End SelectDatanum = Len(CStr(Hex(Text8.Text))) Select Case DatanumCase0Exit Subdata = "000"& CStr(Hex(Text8.Text))Case2data = "00"& CStr(Hex(Text8.Text))Case3data = "0"& CStr(Hex(Text8.Text))Case4data = CStr(Hex(Text8.Text))End SelectIf Err Then'显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd IfText1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)End SubPrivate Sub incorporate1() '将输入的十进制从机地址、命令、资料地址和资料内容合并成字符串Dim wholechar As String, wc%, wcyc%, wchar As StringDim SID As String, Cmd As String, InfoAdd As String, data As StringDim SIDnum%, Cmdnum%, InfoAddNum%, Datanum%On Error Resume Nextwholechar = CStr(Combo6.Text) & CStr(Text7.Text) & CStr(Text8.Text)wc = Len(wholechar)For wcyc = 1To wcwchar = Mid(wholechar, wcyc, 1)If InStr("0123456789", wchar) = 0ThenMsgBox"输入错误,请重新输入< span style="color: #800000;">", , "错误提示"Exit SubEnd IfNextSIDnum = Len(CStr(Hex(Combo6.Text)))Select Case SIDnumCase0Case1SID = "0"& CStr(Hex(Combo6.Text)) Case2SID = 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 SelectInfoAddNum = Len(CStr(Hex(Text7.Text))) Select Case InfoAddNumCase0Exit SubCase1InfoAdd = "0"& CStr(Hex(Text7.Text)) Case2InfoAdd = CStr(Hex(Text7.Text))End SelectDatanum = Len(CStr(Hex(Text8.Text))) Select Case DatanumCase0Exit SubCase1data = "000"& CStr(Hex(Text8.Text)) Case2data = "00"& CStr(Hex(Text8.Text)) Case3data = "0"& CStr(Hex(Text8.Text))Case4data = CStr(Hex(Text8.Text))End SelectIf Err Then'显示出错信息< span style="color: #008000;">MsgBox Error$, 48, "错误信息"Exit SubEnd IfIf Option11.value ThenCmd = "08"Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd)ElseCmd = "07"Text1text = CStr(SID) & CStr(Cmd) & CStr(InfoAdd) & CStr(data)End IfEnd SubPrivate Function CRC16(data() As Byte) As StringDim CRC16Lo As Byte, CRC16Hi As Byte'CRC寄存器< span style="color: #00800 0;">Dim CL As Byte, CH As Byte'多项式码&HA001Dim CRCLo As String, CRCHi As StringDim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerCRC16Lo = &HFFCRC16Hi = &HFFCL = &H1CH = &HA0For i = 0To UBound(data)CRC16Lo = CRC16Lo Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0To7SaveHi = CRC16HiSaveLo = CRC16LoCRC16Hi = CRC16Hi \ 2'高位右移一位< span style="color: #008000;">CRC16Lo = CRC16Lo \ 2'低位右移一位< span style="color: #008000;">If((SaveHi And&H1) = &H1) Then'如果高位字节最后一位为1< span style="color: #008000;">CRC16Lo = CRC16Lo Or&H80 '则低位字节右移后前面补1< span style="color: #008 000;">End If'否则自动补0< span style="color: #008000;">If((SaveLo And&H1) = &H1) Then'如果LSB为1,则与多项式码进行异或CRC16Hi = CRC16Hi Xor CHCRC16Lo = CRC16Lo Xor CLEnd IfNext FlagNext iIf Len(Hex(CRC16Hi)) = 1ThenCRCHi = "0"+ Hex(CRC16Hi)ElseCRCHi = Hex(CRC16Hi)End IfIf Len(Hex(CRC16Lo)) = 1ThenCRCLo = "0"+ Hex(CRC16Lo)ElseCRCLo = Hex(CRC16Lo)End IfCRC16 = CRCLo + CRCHiEnd Function。

标准modbusrtu协议程序

标准modbusrtu协议程序

标准modbusrtu协议程序今天咱们来唠唠这个标准Modbus RTU协议程序哈。

一、啥是Modbus RTU协议呢?这Modbus RTU协议啊,就像是一种特殊的语言,专门让不同的设备之间能够好好聊天的。

你想啊,在一个大的工业环境或者智能家居啥的场景里,有各种各样的设备,就像一群小伙伴,它们得互相沟通才能把事情办好呀。

这个协议呢,就规定了这些设备之间该怎么说话,用啥格式,按啥顺序来传递信息。

比如说,哪个设备想获取另外一个设备的某个数据,就像你想知道你朋友的身高一样,那得按照这个协议规定的方式去问,对方才能听得懂并且给出正确的回应。

二、协议程序的基本结构。

这个协议程序呢,它有自己的一套结构。

就好比盖房子,得有个框架一样。

它有地址部分,这就像是每个设备的名字或者身份证号。

每个设备在这个网络里都有自己独特的地址,这样其他设备要找它的时候就能准确找到啦。

然后呢,还有功能码部分。

这功能码就像是指令,告诉对方设备你想让它干啥。

是想读取数据呢,还是想让它做个什么操作之类的。

再接着就是数据部分啦。

如果是读取数据,这里面可能就包含了要读取数据的起始地址之类的信息;要是写数据呢,那这里面就是要写进去的数据内容了。

最后还有校验部分,这就像是一个小保镖,检查一下前面这些信息在传输过程中有没有出错,如果出错了就赶紧提醒,这样就能保证信息的准确性啦。

三、编写协议程序要注意啥?宝子们,在写这个标准Modbus RTU协议程序的时候啊,有好多要小心的地方呢。

一个是波特率的设置。

波特率就像是设备之间说话的速度。

如果两个设备设置的波特率不一样,那就好比一个人说中文特别快,另一个人说中文特别慢,根本就没法好好交流嘛。

所以要确保所有相关设备的波特率都是一致的。

还有就是数据格式的一致性。

数据在不同设备里的表示方式可能会有点差别,就像不同地方的人计数方式可能有点不同。

有的设备可能用十六进制表示数据,有的可能用十进制,这时候就得统一好,不然就会乱套啦。

基于MODBUS协议的串行通讯例程(VB)

基于MODBUS协议的串行通讯例程(VB)

基于MODBUS协议的串行通讯例程(VB)'可通过MODBUS协议获取:主电压、电流、运行状态、DIP开关设置、硬接线状态、统计数据等;'并可通过MODBUS协议控制:启动、急停、软停、双重参数调节、慢速正/反转、节能等;'本例程为通过通讯获取软启动器当前运行状态'编制:董斌 dbboss@Private Const Read_Coil_Status = &H1Private Const Read_Input_Status = &H2Private Const Read_Holding_Registers = &H3Private Const Read_Input_Registers = &H4Private Const Force_Single_Coil = &H5Private Const Single_Registers = &H6Private Const Diagnostics = &H8Private Const Force_Multiple_Coil = &HFPrivate Const Force_Multiple_Register = &H10Public Function CRC16(data() As Byte) As tCRCDim CRC16Hi As ByteDim CRC16Lo As ByteDim Result As tCRCCRC16Hi = &HFFCRC16Lo = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To UBound(data)iIndex = CRC16Lo Xor data(i)CRC16Lo = CRC16Hi Xor GetCRCLo(iIndex) '低位处理CRC16Hi = GetCRCHi(iIndex) '高位处理Next iWith Result.bytLow = CRC16Lo 'CRC低位.bytHigh = CRC16Hi 'CRC高位End WithCRC16 = ResultEnd Function'CRC低位字节值表Private Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81 , &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &H C1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40)End Function'CRC高位字节值表Private Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HC D, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1 F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD0, &H10, &HF0, &H30, &H3 1, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3 A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE 4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _&H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &H AA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H 7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H 59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H 87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40) End FunctionPublic Function Get_Logic_Status(objRS485_Comm As MSComm, nSerialLink As Byte, _tTimeOut As Double) As tLogic_Status'取软启动器逻辑状态Dim CRC As tCRC, blnTimeOut As BooleanDim outByte() As Byte, T As Double, inByte() As Long, i As Long, r As IntegerDim inChr As String, wStatus As Long, Result As tLogic_StatusReDim outByte(0 To 5) As ByteoutByte(0) = nSerialLink '从设备号outByte(1) = Read_Input_Registers '功能调用号outByte(2) = &H0 '数据所在开始地址(高字节)outByte(3) = &H0 '数据所在开始地址(低字节)outByte(4) = &H0 '读取数据个数(高字节)outByte(5) = &H1 '读取数据个数(低字节)CRC = CRC16(outByte()) '计算CRCReDim Preserve outByte(0 To 7) As ByteWith CRCoutByte(6) = .bytLowoutByte(7) = .bytHighEnd WithobjRS485_Comm.InBufferCount = 0 '清通讯口输入缓存区objRS485_Comm.Output = outByte '输出DoDoEventsLoop Until objRS485_Comm.OutBufferCount = 0 '输出直至完毕T = TimerDoIf Timer - T > tTimeOut Then '超时?blnTimeOut = TrueEnd IfLoop Until (objRS485_Comm.InBufferCount >= 7) Or blnTimeOut '超时或接收数据长度〉7时结束接收If objRS485_Comm.InBufferCount > 0 Then '处理接收数据objRS485_Comm.InputLen = 1i = 0DoinChr = objRS485_Comm.InputReDim Preserve inByte(0 To i) As LonginByte(i) = AscB(inChr)i = i + 1Loop Until objRS485_Comm.InBufferCount = 0wStatus = CLng(inByte(3) * 256) + inByte(4)With Result.blnInsulation = wStatus And &H40& '绝缘报警.blnMotorRunningSlowSpeedReverse = wStatus And &H80& '慢速反转.blnMotorRunningSlowSpeedForward = wStatus And &H100& '慢速正转.blnMotorRunningEnergySaveON = wStatus And &H200& '节能.blnDualAdjON = wStatus And &H400& '双重参数调节.blnMotorRunning = wStatus And &H800& '电机运行.blnMotorStartProcess = wStatus And &H1000& '电机起动过程中.blnMotorSoftStopProcess = wStatus And &H2000& ’电机软停过程中.blnMotorStopped = wStatus And &H4000& ‘电机停止.blnTripped = wStatus And &H8000& ‘跳闸End WithGet_Logic_Status = ResultEnd IfobjRS485_Comm.InBufferCount = 0End Function‘本程序在Windows9x/2k/xp vb6.0 下调试通过。

VB控件Mscomm控件与PLC进行RS485(Modbus)通讯源码

VB控件Mscomm控件与PLC进行RS485(Modbus)通讯源码
'<<算法>>
Dim CRC_2() As Byte
Dim v As Integer
ReDim CRC_2(K)
For v = 0 To K
CRC_2(v) = Val("&H" & Text1(v).Text)
Next
'==================================================================================================
'
'Next
'Label35.Caption = Str(Val(Asc(Mid(tmp, 6, 1))) / 10)
'
'
' tmp = Mid$(tmp, 6, 4)
'
'
' Dim strHex As String
' Dim Hex2Dec As Long
' Dim strTmp As String
'a = 0
'tmp = 0
'
'
'
' Do While Len(tmp) < 8
'
' tmp = tmp + MSComm1.Input
' testNO.Caption = testNO.Caption + " " + Str(Hex(Asc(tmp)))
' a = a + 1
' If a >= 3000 Then

VB编写的Modbus RTU协议通讯源程序

VB编写的Modbus RTU协议通讯源程序

VB编写的Modbus RTU协议通讯源程序modbus rtu协议可以算是一种事实上的工业标准协议,为许多仪表、PLC等所支持。

以前有几个用户问如何使用VB编程来与我们的KND-K3系列PLC通讯,于是整了一个demo程序。

这次把这个demo共享,希望能给大家一点帮助。

1)模块文件:modCRC,其中包含了CRC校验的函数。

'data 待校验的数组名称'no 数组中元素个数'btLoCRC 算出的CRC高字节'btHiCRC 算出的CRC低字节Public Function CalCRC16Fast(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim CL As Byte, CH As Byte '多项式码&HA001Dim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerbtHiCRC = &HFFbtLoCRC = &HFFCL = &H1CH = &HA0For i = 0 To (no - 1)btHiCRC = btHiCRC Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = btLoCRCSaveLo = btHiCRCbtLoCRC = btLoCRC \ 2 '高位右移一位btHiCRC = btHiCRC \ 2 '低位右移一位If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1btHiCRC = btHiCRC Or &H80 '则低位字节右移后前面补1End If '否则自动补0If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或btLoCRC = btLoCRC Xor CHbtHiCRC = btHiCRC Xor CLEnd IfNext FlagNext iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Fast = ReturnDataEnd FunctionPublic Function CalCRC16Tbl(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim btLoCRC As ByteDim btHiCRC As BytebtLoCRC = &HFFbtHiCRC = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To (no - 1)iIndex = btHiCRC Xor data(i)btHiCRC = btLoCRC Xor GetCRCLo(iIndex) '低位处理btLoCRC = GetCRCHi(iIndex) '高位处理Next iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Tbl = ReturnDataEnd Function'CRC低位字节值表Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40)End Function'CRC高位字节值表Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, _&H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _ &H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40)End Function2)窗体:FORM1,上面放置的控件如下:Begin VB.Form frmComCaption = "Form1"ClientHeight = 8235ClientLeft = 3885ClientTop = 2250ClientWidth = 6810LinkTopic = "Form1"ScaleHeight = 8235ScaleWidth = 6810Begin VB.TextBox txtReceive ‘注:放置接收上来的IB0数据Height = 495Left = 1200TabIndex = 2Top = 2280Width = 1335EndBegin mandButton Command1Caption = "读取IB0"Height = 495Left = 2760TabIndex = 1Top = 2280Width = 1695EndBegin mandButton cmdSDOCaption = "置位Q1.1"Height = 495Left = 2160TabIndex = 0Top = 3720Width = 1575EndBegin MSCommLib.MSComm ComK3Left = 480Top = 1080_ExtentX = 1005_ExtentY = 1005_V ersion = 393216DTREnable = -1 'TrueEnd①Form_Load事件,在此主要是实现了打开并初始化串口Private Sub Form_Load()With ComK3.CommPort = 1.Settings = "19200,N,8,1".InputMode = comInputModeBinary '二进制收发.InBufferSize = 512.OutBufferSize = 512If (Not .PortOpen) Then .PortOpen = True End WithEnd Sub②Form_UnLoad事件,在此主要是关闭串口Private Sub Form_Unload(Cancel As Integer)If (ComK3.PortOpen) ThenComK3.PortOpen = FalseEnd IfEnd Sub③“置位Q1.1”按钮单击事件'设置Q1.1为1Private Sub cmdSDO_Click()Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H5 '功能码btSend(2) = &H0 'Q1.1地址(0009)高字节btSend(3) = &H9 'Q1.1地址(0009)低字节btSend(4) = &HFF '强制值高字节btSend(5) = &H0 '强制值低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CV ar(btSend)End Sub④“读取IB0”按钮单击事件'查表知I0.0的modbus地址为0000,从I0.0开始读取连续8位Private Sub Command1_Click()'发请求Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H2 '功能码btSend(2) = &H0 'I0.0地址(0000)高字节btSend(3) = &H0 'i0.0地址(0000)低字节btSend(4) = &H0 '读取个数高字节btSend(5) = &H8 '读取个数低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CV ar(btSend)'注意下面编写的接收过程很简单,要编写实际应用的监控程序来说需要更完善Dim btReceive As V ariantWith ComK3DoDoEventsLoop Until .InBufferCount = 6.InputLen = 6btReceive = .InputIf btReceive(1) = &H2 Then '若正确,返回帧的第2个字节为功能码.实际上,此处应首先进行CRC校验txtReceive.Text = Hex$(btReceive(3))End IfEnd WithEnd Sub。

Modbusvb源程序(可以读写寄存器)

Modbusvb源程序(可以读写寄存器)

Modbusvb源程序(可以读写寄存器)modbus vb源程序可以读写寄存器自己的项目做完了,最近比较闲,就帮别人用VB写了一个很简单的modbus程序,可以实现实时数据采集显示,以及能对寄存器进行设置。

程序很简单,想用的可以完善,现在只能实时采集显示一个地址的数据,只要修改一下,就可以实时采集多个地址的数据。

现在也只能一次对一个寄存器进行设置,也可以更加完善。

想用的朋友就自己改改吧。

下面是运行界面,采集的模块的地址为75,是一个温湿度采集模块。

有3个寄存器,显示的数据上是温度,湿度,露点温度。

modbusPrivate Sub Command1_Click() '设置按钮Dim bisend() As ByteDim crcDim btLoCRC As Byte, btHiCRC As ByteDim Data As IntegerIf MSComm1.PortOpen = True ThenIf Combo5.ListIndex = 0 ThenReDim bisend(7) '重新定义数组长度bisend(0) = "&h" + Hex(Val(Text1.Text)) '地址码bisend(1) = "&h" + Hex(3) '功能码读寄存器bisend(2) = "&h" + Hex(0) '起始地址高位bisend(3) = "&h" + Hex(0) '起始地址低位bisend(4) = "&h" + Hex(0) '寄存器个数高位bisend(5) = "&h" + Hex(Combo6.ListIndex + 1) '寄存器个数低位crc = CRC16(bisend, 6, btLoCRC, btHiCRC)bisend(6) = "&h" + Hex(btLoCRC) 'CRC高位bisend(7) = "&h" + Hex(btHiCRC) 'CRC低位'发送数据MSComm1.Output = bisendElseReDim bisend(10) '一次只能写一个寄存器bisend(0) = "&h" + Hex(Val(Text1.Text)) '地址码bisend(1) = "&h" + Hex(16) '功能码写寄存器bisend(2) = "&h" + Hex(0) '起始地址高位bisend(3) = "&h" + Hex(0) '起始地址低位bisend(4) = "&h" + Hex(0) '寄存器个数高位bisend(5) = "&h" + Hex(1) '寄存器个数低位bisend(6) = "&h" + Hex(2) '字节数Data = Val(Trim(Text3.Text))bisend(7) = "&h" + Hex(Data \ 256) '要写入寄存器的值的高字节bisend(8) = "&h" + Hex(Data Mod 256) '要写入寄存器的值的低字节crc = CRC16(bisend, 9, btLoCRC, btHiCRC)bisend(9) = "&h" + Hex(btLoCRC) 'CRC高位bisend(10) = "&h" + Hex(btHiCRC) 'CRC低位MSComm1.Output = bisendEnd IfElseMsgBox "串口没有打开"End IfEnd SubPrivate Sub Command2_Click() '实时采集按钮Timer1.Enabled = Not Timer1.Enabled '进行状态切换End SubPrivate Sub Command3_Click()'初始化,并打开串口With MSComm1If .PortOpen = False Then.CommPort = Combo7.ListIndex + 1 '打开串口1.Settings = Combo1.Text + "," + Combo2.Text + "," + Combo3.T ext + Combo4.Text.InputMode = 1.InputLen = 50 '一次性从接收缓冲区中读取所有数据(8个字节为一组!!).InBufferCount = 0 '清空接收缓冲区.OutBufferCount = 0 '清空发送缓冲区.RThreshold = 5 + (Combo6.ListIndex + 1) * 2.InBufferSize = 1024.OutBufferSize = 1024.PortOpen = TrueElseMsgBox "串口已经打开"End IfEnd WithEnd SubPrivate Sub Command4_Click() '关闭串口按钮If MSComm1.PortOpen = True Then MSComm1.PortOpen = False End IfEnd SubPrivate Sub Form_Load()Dim i As Integer'波特率设置Combo1.AddItem "4800", 0 Combo1.AddItem "9600", 1 Combo1.AddItem "115200", 2'校验位设置Combo2.AddItem "N", 0Combo2.AddItem "E", 1Combo2.AddItem "O", 2'数据位设置Combo3.AddItem "7", 0Combo3.AddItem "8", 1'停止位设置Combo4.AddItem "1", 0Combo4.AddItem "2", 1'功能码选择Combo5.AddItem "读寄存器03", 0 Combo5.AddItem "写寄存器16", 1 '寄存器个数设置Combo6.AddItem "1", 0Combo6.AddItem "2", 1Combo6.AddItem "3", 2Combo6.AddItem "4", 3Combo6.AddItem "5", 4 Combo6.AddItem "6", 5Combo6.AddItem "7", 6Combo6.AddItem "8", 7Combo6.AddItem "9", 8Combo6.AddItem "10", 9 Combo6.AddItem "11", 10 Combo6.AddItem "12", 11 Combo6.AddItem "13", 12 Combo6.AddItem "14", 13 Combo6.AddItem "15", 14 Combo6.AddItem "16", 15 Combo6.AddItem "17", 16 Combo6.AddItem "18", 17 Combo6.AddItem "19", 18Combo6.AddItem "20", 19Combo6.AddItem "21", 20Combo6.AddItem "22", 21'串口选择Combo7.AddItem "串口1", 0Combo7.AddItem "串口2", 1Combo7.AddItem "串口3", 2Combo7.AddItem "串口4", 3'初始赋值Combo1.ListIndex = 1Combo2.ListIndex = 1Combo3.ListIndex = 1Combo4.ListIndex = 0Combo5.ListIndex = 0Combo6.ListIndex = 2Combo7.ListIndex = 0'初始化串口End SubPrivate Sub Form_Unload(Cancel As Integer)If MSComm1.PortOpen = True ThenMSComm1.PortOpen = FalseEnd IfEnd SubPrivate Sub MSComm1_OnComm()Dim INByte() As ByteDim Buf As StringDim btLoCRC As Byte, btHiCRC As ByteDim Data As IntegerIf mEvent = comEvReceive Then '接收到数据以后INByte = MSComm1.InputIf INByte(1) = 3 Then '读寄存器'CRC校验crc = CRC16(INByte, UBound(INByte) - LBound(INByte) - 1, btLoCRC, btHiCRC)If INByte(UBound(INByte) - 1) = btLoCRC And INByte(UBound(INByte)) = btHiCRC Then '校验正确'////////////////////////////////////For i = 3 To UBound(INByte) - 2 Step 2Data = "&h" + Hex(INByte(i)) + Hex(INByte(i + 1))' Buf = Buf + Hex(INByte(i)) + Chr(32)Buf = Buf + Str(Data) '转换为十进制显示Next iList1.AddItem BufEnd IfEnd IfMSComm1.InBufferCount = 0 '请缓存End IfEnd SubPrivate Sub Timer1_Timer()'定时发送命令Dim tbisend(7) As ByteDim crc '定时1sDim btLoCRC As Byte, btHiCRC As ByteDim Buf As StringIf MSComm1.PortOpen = True Thentbisend(0) = "&h" + Hex(Val(Text1.Text)) '地址码tbisend(1) = "&h" + Hex(3) '功能码读寄存器tbisend(2) = "&h" + Hex(0) '起始地址高位tbisend(3) = "&h" + Hex(0) '起始地址低位tbisend(4) = "&h" + Hex(0) '寄存器个数高位tbisend(5) = "&h" + Hex(Combo6.ListIndex + 1) '寄存器个数低位crc = CRC16(tbisend, 6, btLoCRC, btHiCRC)tbisend(6) = "&h" + Hex(btLoCRC) 'CRC高位tbisend(7) = "&h" + Hex(btHiCRC) 'CRC低位'发送数据MSComm1.Output = tbisendEnd IfEnd Sub/////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////Function CRC16(Data() As Byte, no As Integer, CRC16Lo As Byte, CRC16Hi As Byte) As StringDim CL As Byte, CH As Byte '多项式码&HA001Dim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerCRC16Lo = &HFFCRC16Hi = &HFFCL = &H1CH = &HA0For i = 0 To no - 1CRC16Lo = CRC16Lo Xor Data(i) '每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = CRC16HiSaveLo = CRC16LoCRC16Hi = CRC16Hi \ 2 '高位右移一位CRC16Lo = CRC16Lo \ 2 '低位右移一位If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1 CRC16Lo = CRC16Lo Or &H80 '则低位字节右移后前面补1End If '否则自动补0If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或CRC16Hi = CRC16Hi Xor CHCRC16Lo = CRC16Lo Xor CLEnd IfNext FlagNext iDim ReturnData(1) As ByteReturnData(0) = CRC16Hi 'CRC高位ReturnData(1) = CRC16Lo 'CRC低位CRC16 = ReturnDataEnd Function'CRC低位字节值表Function GetCRCLo(ind As Long) As ByteGetCRCLo = Choose(ind + 1, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC1, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H81, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40)End Function'CRC高位字节值表Function GetCRCHi(ind As Long) As ByteGetCRCHi = Choose(ind + 1, &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, _&HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, _&H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, _&H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, _&HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, _&H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &O33, &HF3, _&HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, _&H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, _&H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, _&HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF,&H2D, &HED, _&HEC, &H2C, &HE4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, _&H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _&H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, _&HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, _&H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, _&H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, _&H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, _&H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, _&H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, _&H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, _&H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, _&H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, _&H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, _&H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, _&H43, &H83, &H41, &H81, &H80, &H40)End Function。

Modbus通讯RTU协议的源代码程序实例

Modbus通讯RTU协议的源代码程序实例
#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0;
#endif
eMBErrorCode ULONG
eStatus = MB_ENOERR; usTimerT35_50us;
( void )ucSlaveAddress; ENTER_CRITICAL_SECTION( );
/* ----------------------- System includes ----------------------------------*/ #include "stdlib.h" #include "string.h"
/* ----------------------- Platform includes --------------------------------*/ #include "port.h"
*
= 220000 / Baudrate
* The reload for t3.5 is 1.5 times this value and similary
* for t3.5.
*/
usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );
#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0;
#endif
ENTER_CRITICAL_SECTION( ); /* Initially the receiver is in the state STATE_RX_INIT. we start
* the timer and if no character is received within t3.5 we change * to STATE_RX_IDLE. This makes sure that we delay startup of the * modbus protocol stack until the bus is free. */ eRcvState = STATE_RX_INIT; eSndState = STATE_TX_IDLE; //2008.11.12 修改 vMBPortSerialEnable( TRUE, FALSE ); vMBPortTimersEnable( );
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

modbus rtu协议可以算是一种事实上的工业标准协议,为许多仪表、PLC等所支持。

以前有几个用户问如何使用VB编程来与我们的KND-K3系列PLC通讯,于是整了一个demo 程序。

这次把这个demo共享,希望能给大家一点帮助。

1)模块文件:modCRC,其中包含了CRC校验的函数。

'data 待校验的数组名称'no 数组中元素个数'btLoCRC 算出的CRC高字节'btHiCRC 算出的CRC低字节Public Function CalCRC16Fast(data() As Byte, no As Integer, btLoCRC As Byte, btHiCR C As Byte) As StringDim CL As Byte, CH As Byte '多项式码&HA001Dim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerbtHiCRC = &HFFbtLoCRC = &HFFCL = &H1CH = &HA0For i = 0 To (no - 1)btHiCRC = btHiCRC Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = btLoCRCSaveLo = btHiCRCbtLoCRC = btLoCRC \ 2 '高位右移一位btHiCRC = btHiCRC \ 2 '低位右移一位If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1btHiCRC = btHiCRC Or &H80 '则低位字节右移后前面补1End If '否则自动补0If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或btLoCRC = btLoCRC Xor CHbtHiCRC = btHiCRC Xor CLEnd IfNext FlagNext iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Fast = ReturnDataEnd FunctionPublic Function CalCRC16Tbl(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim btLoCRC As ByteDim btHiCRC As BytebtLoCRC = &HFFbtHiCRC = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To (no - 1)iIndex = btHiCRC Xor data(i)btHiCRC = btLoCRC Xor GetCRCLo(iIndex) '低位处理btLoCRC = GetCRCHi(iIndex) '高位处理Next iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Tbl = ReturnDataEnd Function'CRC低位字节值表Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &H C1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H8 1, &H40)End Function'CRC高位字节值表Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, _&H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7 , &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, & HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, & HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD 0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H 37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE 4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, & H21, &H20, &HE0, &HA0, &H60, _&H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &HAA, &H6A, & H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7 A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB 0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H 55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8 B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40)End Function2)窗体:FORM1,上面放置的控件如下:Begin VB.Form frmComCaption = "Form1"ClientHeight = 8235ClientLeft = 3885ClientTop = 2250ClientWidth = 6810LinkTopic = "Form1"ScaleHeight = 8235ScaleWidth = 6810Begin VB.TextBox txtReceive ‘注:放置接收上来的IB0数据Height = 495Left = 1200TabIndex = 2Top = 2280Width = 1335EndBegin mandButton Command1Caption = "读取IB0"Height = 495Left = 2760TabIndex = 1Top = 2280Width = 1695EndBegin mandButton cmdSDOCaption = "置位Q1.1"Height = 495Left = 2160TabIndex = 0Top = 3720Width = 1575EndBegin MSCommLib.MSComm ComK3Left = 480Top = 1080_ExtentX = 1005_ExtentY = 1005_Version = 393216DTREnable = -1 'TrueEndEnd① Form_Load事件,在此主要是实现了打开并初始化串口Private Sub Form_Load()With ComK3.CommPort = 1.Settings = "19200,N,8,1".InputMode = comInputModeBinary '二进制收发.InBufferSize = 512.OutBufferSize = 512If (Not .PortOpen) Then .PortOpen = TrueEnd WithEnd Sub② Form_UnLoad事件,在此主要是关闭串口Private Sub Form_Unload(Cancel As Integer)If (ComK3.PortOpen) ThenComK3.PortOpen = FalseEnd IfEnd Sub③“置位Q1.1”按钮单击事件'设置Q1.1为1Private Sub cmdSDO_Click()Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H5 '功能码btSend(2) = &H0 'Q1.1地址(0009)高字节btSend(3) = &H9 'Q1.1地址(0009)低字节btSend(4) = &HFF '强制值高字节btSend(5) = &H0 '强制值低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CVar(btSend)End Sub④“读取IB0”按钮单击事件'查表知I0.0的modbus地址为0000,从I0.0开始读取连续8位Private Sub Command1_Click()'发请求Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H2 '功能码btSend(2) = &H0 'I0.0地址(0000)高字节btSend(3) = &H0 'i0.0地址(0000)低字节btSend(4) = &H0 '读取个数高字节btSend(5) = &H8 '读取个数低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CVar(btSend)'注意下面编写的接收过程很简单,要编写实际应用的监控程序来说需要更完善 Dim btReceive As VariantWith ComK3DoDoEventsLoop Until .InBufferCount = 6.InputLen = 6btReceive = .InputIf btReceive(1) = &H2 Then '若正确,返回帧的第2个字节为功能码.实际上,此处应首先进行CRC校验txtReceive.Text = Hex$(btReceive(3))End IfEnd WithEnd Sub。

相关文档
最新文档