MODBUS的CRC校验和程序(VB编制)
modbus协议做为一种通用协议得到了广泛的应用,它有两种传输模式:ASCII和RTU。ASCII模式采用LRC校验,RTU模式采用CRC校验。
CRC方法错误检测域的内容是通过对消息内容进行循环冗长检测方法得出的。
使用RTU模式,消息包括了一基于CRC方法的错误检测域。CRC域检测了整个消息的内容。
CRC域是两个字节,包含一16位的二进制值。它由传输设备计算后加入到消息中。接收设备重新计算收到消息的CRC,并与接收到的CRC域中的值比较,如果两值不同,则有误。
CRC是先调入一值是全“1”的16位寄存器,然后调用一过程将消息中连续的8位字节各当前寄存器中的值进行处理。仅每个字符中的8Bit数据对CRC有效,起始位和停止位以及奇偶校验位均无效。
CRC产生过程中,每个8位字符都单独和寄存器内容相或(OR),结果向最低有效位方向移动,最高有效位以0填充。LSB被提取出来检测,如果LSB为1,寄存器单独和预置的值或一下,如果LSB为0,则不进行。整个过程要重复8次。在最后一位(第8位)完成后,下一个8位字节又单独和寄存器的当前值相或。最终寄存器中的值,是消息中所有的字节都执行之后的CRC值。
CRC域附加在消息的最后,添加时先是低字节然后是高字节。故CRC的高位字节是发送消息的最后一个字节。
下面是用VB实现的CRC校验和程序:
Function CRC16(data() As Byte) As String ’CRC计算函数 Dim CRC16Lo As Byte, CRC16Hi As Byte ’CRC寄存器 Dim CL As Byte, CH As Byte ’多项式码&HA001 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
Dim ReturnData(1) As Byte
ReturnData(0) = CRC16Hi ’CRC高位 ReturnData(1) = CRC16Lo ’CRC低位
asd = Right(\
End Function
多线程串行通讯VB源码
Option Explicit
Private WithEvents oTest1 As TestExe.clsTest Private WithEvents oTest2 As TestExe.clsTest
Private Declare Function GetTickCount Lib \ Dim mi, i As Integer
Public Sub timedelay(ByVal t As Long) Dim tt As Double tt = GetTickCount() Do
DoEvents
Loop Until GetTickCount() - tt > t End Sub
Private Sub Command1_Click()
Set oTest1 = New TestExe.clsTest oTest1.lMillisecs = 100 oTest1.StartSub (1000)
Set oTest2 = New TestExe.clsTest oTest2.lMillisecs = 100 oTest2.StartSub (1000)
Command1.Enabled = False Command2.Enabled = True End Sub
Private Sub Command2_Click() oTest1.StopSub oTest2.StopSub
Command1.Enabled = True Command2.Enabled = False End Sub
Private Sub Command3_Click() oTest1.StopSub oTest2.StopSub
Set oTest1 = Nothing Set oTest2 = Nothing End Sub
Private Sub Form_Unload(Cancel As Integer) oTest1.StopSub oTest2.StopSub
Set oTest1 = Nothing Set oTest2 = Nothing End Sub
Private Sub oTest1_Progress(ByVal lProgress As Long) List1.AddItem lProgress
List1.ListIndex = List1.ListCount - 1 End Sub
Private Sub oTest2_Progress(ByVal lProgress As Long) recieve_message
List2.AddItem lProgress
List2.ListIndex = List2.ListCount - 1 End Sub
Private Sub send_message()
If MSComm1.PortOpen = False Then '置位 MSComm1.CommPort = 1 MSComm1.PortOpen = True End If
MSComm1.Settings = \ MSComm1.InputLen = 0
MSComm1.InputMode = comInputModeText MSComm1.Output = Text1.Text Do
timedelay 100 DoEvents
Loop While MSComm1.InBufferCount <= 2 Label1.Caption = MSComm1.Input If Label1.Caption = \
MsgBox \通讯错误,请确认线路是否连接\错误\ Else
'Label1.Caption = \开始运行\ End If
MSComm1.InputLen = 0 MSComm1.PortOpen = False End Sub
Private Sub recieve_message() '接收应答信息,初始化MSComm Dim str As String
If MSComm1.PortOpen = False Then '置位 MSComm1.CommPort = 1
MSComm1.PortOpen = True End If
MSComm1.Settings = \ MSComm1.InputLen = 0
MSComm1.InputMode = comInputModeText 'MSComm1.InputMode = comInputModeBinary Do
timedelay 100 DoEvents
Loop While MSComm1.InBufferCount <= 2 str = MSComm1.Input Label1.Caption = str Debug.Print str End Sub
Private Sub sent_msg_Click() send_message End Sub
Private Sub show_msg_Click() recieve_message End Sub
如何用VB实现Modbus串行通讯
在一些应用中可能需要使用诸如VB来进行上位机监控程序的开发,而Modbus协议是这类应用中首选的通讯协议;Modbus协议以其简单易用,在工业领域里已广泛的为其他第三方设备所支持。这里对VB和Twido PLC间的通讯进行说明。
对于大部分应用,Twido PLC作为从站,它不需要编制通讯程序,只要把通讯口的参数设置好即可,例如下图表示此Twido通过编程口和上位机连接,其站号地址为2;波特率、数据位、校验、停止位和上位机设置保持一致。
VB程序通过利用MSComm控件很容易就能够实现。 1. 通讯口初始化:
MSComm1.Settings = \ MSComm1.CommPort = 1 MSComm1.SThreshold = 0
If Not MSComm1.PortOpen Then MSComm1.PortOpen = True
2. CRC校验码的计算方法,如以下函数,可以得到字节数组变量cmdstring指向的字符串的CRC校验码。 字串7
Function crc16_1(ByRef cmdstring() As Byte, ByVal j As Integer) Dim data As Integer Dim i As Integer
Addressreg_crc = &HFFFF For i = 0 To j
Addressreg_crc = Addressreg_crc Xor cmdstring(i) For j = 0 To 7
data = Addressreg_crc And &H1 If data Then
Addressreg_crc = Int(Addressreg_crc / 2) Addressreg_crc = Addressreg_crc And &H7FFF Addressreg_crc = Addressreg_crc Xor &HA001 Else
Addressreg_crc = Addressreg_crc / 2
Addressreg_crc = Addressreg_crc And &H7FFF End If Next j Next i
If Addressreg_crc < 0 Then
Addressreg_crc = Addressreg_crc - &HFFFF0000 End If
HiByte = Addressreg_crc And &HFF
LoByte = (Addressreg_crc And &HFF00) / &H100 End Function
3. 读多个字的命令(本例是从2号站读%MW10起始的4个字): 字串2 Dim SendStr(7) As Byte Dim RcvStr() As Byte SendStr(0) = 2 ,从站号是2
SendStr(1) = &H3 ,读多个字的命令代码 SendStr(2) = 0 ,起始地址高字节 SendStr(3) = 10,起始地址低字节 SendStr(4) = &H0,数据长度高字节 SendStr(5) = 4 ,数据长度低字节
Call crc16(SendStr(), 5) ,CRC计算 SendStr(6) = HiByte SendStr(7) = LoByte
,读命令发送后,当接收 5 + SendStr(5) * 2 个字节时产生中断 CmdLenth = 5 + SendStr(5) * 2 MSComm1.RThreshold = CmdLenth MSComm1.Output = SendStr ,发送命令