MODBUS的CRC校验和程序
更新时间:2023-12-06 15:00:01 阅读量: 教育文库 文档下载
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 ,发送命令
起始位地址 0000 DO寄存器数据(16进制) 02 备 注 DO2输出状态为“1”,DO1输出状态为“0” 主机发送的报文格式: 主机发送 从机地址 功能码 起始BIT位 读数据长度 CRC码 从机(PDM)响应返回的报文格式: 从机响应 从机地址 功能码 数据长度 DO状态数据 CRC码 字节数 1 1 1 1 2 返回的信息 01 01 01 02 D049 备 注 来自从机01 读开关量输出状态 1个字节(8个BIT位) DO寄存器内容 由从机计算得到CRC码 字节数 1 1 2 2 2 发送的信息 01 01 0000 0002 BDCB 备 注 发送至地址为01的从机 读开关量输出状态 起始BIT位地址为0000 读取2路继电器输出状态位 由主机计算得到CRC码 2.3 功能码“03”:读多路寄存器输入 例如:主机要读取地址为01,起始地址为0116的3个从机寄存器数据。 从机(PDM)数据寄存器的地址和数据为: 寄存器地址 0116 0117 0118 主机发送的报文格式: 寄存器数据(16进制) 1784 1780 178A 对应PDM电量 UA UB UC 主机发送 从机地址 功能码 起始地址 数据长度 CRC码 从机(PDM)响应返回的报文格式: 从机响应 从机地址 功能码 读取字 寄存器数据1 寄存器数据2 寄存器数据3 CRC码 2.4 功能码“05”:写1路开关量输出(“遥控”) 例1:开关量输出点DO1,其当前状态为“分”,主机要控制该路继电器“合”。 控制命令为: “FF00”为控制继电器“合”; “0000”为控制继电器“分”; 主机发送的报文格式: 主机发送 字节数 发送的信息 备 注 字节数 1 1 1 2 2 2 2 返回的信息 01 03 06 1784 1780 178A 5847 备 注 来自从机01 读取寄存器 3个寄存器共6个字节 地址为0116内存的内容 地址为0117内存的内容 地址为0118内存的内容 由从机计算得到CRC码 字节数 1 1 2 3 2 发送的信息 01 03 0116 0003 E5F3 备 注 发送至地址为01的从机 读取寄存器 起始地址为0116 读取3个寄存器(共6个字节) 由主机计算得到CRC码 从机地址 功能码 输出BIT位 控制命令 CRC码 1 1 2 2 2 01 05 0000 FF00 8C3A 发送至地址为01的从机 写开关量输出状态 对应输出继电器BIT位(DO1) 控制该路继电器输出为“合”状态位 由主机计算得到CRC码 从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。 例2:开关量输出点DO2,其当前状态为“合”,主机要控制该路继电器“分”。 主机发送的报文格式: 主机发送 从机地址 功能码 输出BIT位 控制命令 CRC码 从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。 2.5 功能码“06”:写单路寄存器 例如:主机要把数据07D0,保存到地址为002C的从机寄存器中去(从机地址码为01)。通讯数据保存结束后,地址为002C的PDM表原存储信息为: 地址 002C 原来存储数据(16进制) 04B0 字节数 1 1 2 2 2 发送的信息 01 05 0001 0000 9C0A 备 注 发送至地址为01的从机 写开关量输出状态 对应输出继电器BIT位(DO2) 控制该路继电器输出为“合”状态位 由主机计算得到CRC码 主机发送的报文格式: 主机发送 从机地址 功能码 起始地址 写入数据 CRC码 从机(PDM)响应返回的报文格式: 与主机发送的报文格式及数据内容完全相同。 2.6功能码“10”:写多路寄存器 主机利用这个功能码把多个数据保存到PDM表的数据存储器中去。Modbus通讯规约中的寄存器指的是16位(即2字节),并且高位在前。这样PDM的存储器都是二个字节。由于Modbus通讯规约允许每次最多保存60个寄存器,因此PDM一次也最多允许保存60个数据寄存器。 例如:主机要把0064,0010保存到地址为002C,002D的从机寄存器中去(从机地址码为01)。通讯数据保存结束后,地址为002C/002D的PDM表内存储信息为: 地址 002C 002D 主机发送的报文格式: 主机发送 从机地址 功能码 起始地址 保存数据字长度 字节数 1 1 2 2 发送信息 01 10 002C 0002 举例 发送至从机01 写多路寄存器 要写入的寄存器的起始地址 保存数据的字长度(共2字) 原来存储数据(16进制) 04B0 1388 字节数 1 1 2 2 2 发送的信息 01 06 002C 07D0 4BAF 举例 发送至地址为01的从机 写单路寄存器 要写入的寄存器地址 对应的新数据 由主机计算得到的CRC码 保存数据字节长 保存数据1 保存数据2 CRC码 1 2 2 2 04 04B0 1388 FC63 保存数据的字节长度(共4字节) 数据地址002C 数据地址002D 由主机计算得到的CRC码 从机(PDM)响应返回的报文格式: 从机响应 从机地址 功能码 起始地址 保存数据字长度 CRC码 三、错误校验码(CRC校验): 主机或从机可用校验码进行判别接收信息是否正确。由于电子噪声或一些其它干扰,信息在传输过程中有时会发生错误,错误校验码(CRC)可以检验主机或从机在通讯数据传送过程中的信息是否有误,错误的数据可以放弃(无论是发送还是接收),这样增加了系统的安全和效率。 MODBUS通讯协议的CRC(冗余循环码)包含2个字节,即16位二进制数。CRC码由发送设备(主机)计算,放置于发送信息帧的尾部。接收信息的设备(从机)再重新计算接收到信息的CRC,比较计算得到的CRC是否与接收到的相符,如果两者不相符,则表明出错。 在进行CRC计算时只用8个数据位,起始位及停止位,如有奇偶校验位也包括奇偶校验位,都不参与CRC计算。 ● CRC码的计算方法是: 1.预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器; 2.把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器; 3.把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位; 4.如果移出位为0:重复第3步(再次右移一位); 如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或; 字节数 1 1 2 2 2 字节数 01 10 002C 0002 8001 举例 来自从机01 写多路寄存器 起始地址为002C 保存2个字长度的数据 由从机计算得到的CRC码
正在阅读:
MODBUS的CRC校验和程序12-06
上海交大、复旦、同济大学保送生数学试题07-25
最新部编人教版小学三年级语文上册《快乐读书吧 - 在那奇妙的王国里》优质教学设计10-05
公开课教案:恐龙研学 112906-05
二年级日记100字大全10篇03-27
长期股权投资的成本法与权益法核算03-14
阿穆尔-黑河边境油品储运与炼化综合体项目环境影响报告书简本08-17
广州大学操作系统实验指导书(2006年第一期)(标题化04-12
成都地铁2号线站点介绍05-25
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 校验
- 程序
- MODBUS
- CRC
- 太原市2017-2018学年第一学期高三年级阶段性测评数学试题
- 链家地产实习报告
- 物理实验 误差分析与数据处理
- 化工原理实验思考题及答案
- 人教版小学语文六年级下册《口语交际·习作二 习作》公开课教学设计 - 2
- 人教版七年级下册语文 人教版七年级下册语文 27 斑羚飞渡 学习要点 精品
- 注塑机PID温度调整设置原理
- 《高分子化学》习题答案
- 浅谈初中英语阅读教学中的评价策略-最新资料
- 少儿培训学校攻单话术
- 精选八年级物理全册第10章机械与人第6节合理利用机械能第1课时动能和势能教案新版沪科版
- v2.1.2新签全产品协议(阶梯)
- 创意6 有效学习三十六计
- 语文苏教版选修系列《唐诗宋词选读》配套文档:专题四+客 至+Word版含答案 docx
- 高职城市轨道交通类专业试行现代学徒制的探索
- 2017年郑州市惠济区招教考试真题及答
- 系统解剖学复习--名词解释和问答题
- 《C语言程序设计》试题库及答案
- 2017年下半年儿童发展心理学-作业
- 特点、难点、风险点分析及监理对策-老旧小区、重点大街的市政公用和综合治理工程