认识Modbus协议
1.什么是Modbus?
Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间,控制器经由网络(例如以太网)和其它设备之间可以通信。Modbus协议定义了一个控制器能认识使用的消息结构,而不管他们是经过何种网络进行通信的。它描述了一个控制器请求访问其他设备的过程,如果回应来自其他设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
Modbus是一个请求/应答协议。
以下是要分解的Modbus热图

Modbus消息帧
了解了它,会使你对串口有一个清晰的认识!

通用消息帧

ASCII消息帧(在消息中的每个8Bit字节都作为两个ASCII字符发送)
十六进制,ASCII字符0...9,A...F
消息中的每个ASCII字符都是一个十六进制字符组成
每个字节的位
1个起始位
n个数据位,最小的有效位先发送
1个奇偶校验位,无校验则无
1个停止位(有校验时),2个Bit(无校验时)
错误检测域
LRC(纵向冗长检测)


RTU消息帧
8位二进制,十六进制数0...9,A...F
消息中的每个8位域都是一个两个十六进制字符组成
每个字节的位
1个起始位
8个数据位,最小的有效位先发送
1个奇偶校验位,无校验则无
1个停止位(有校验时),2个Bit(无校验时)
错误检测域
CRC(循环冗长检测)


CRC校验(http://baike.baidu.com/view/1664507.htm)
public static string CRCCheck(string val)
{
val = val.TrimEnd(' ');
string[] spva = val.Split(' ');
byte[] bufData = new byte[spva.Length + 2];
bufData = ToBytesCRC(val);
ushort CRC = 0xffff;
ushort POLYNOMIAL = 0xa001;
for (int i = 0; i < bufData.Length - 2; i++)
{
CRC ^= bufData[i];
for (int j = 0; j < 8; j++)
{
if ((CRC & 0x0001) != 0)
{
CRC >>= 1;
CRC ^= POLYNOMIAL;
}
else
{
CRC >>= 1;
}
}
}
return Maticsoft.DBUtility.HLConvert.ToHex(System.BitConverter.GetBytes(CRC));
}
/// <summary>
/// 例如把如下字符串转换成字节数组
/// AA AA AA AA 0A 00 68 00 06 03 04 54 21 28 22 E5 F3 16 BB BB BB BB 转换为字节数组
/// </summary>
/// <param name="hex">十六进制字符串</param>
/// <returns></returns>
public static byte[] ToBytesCRC(string hex)
{
string[] temp = hex.Split(' ');
byte[] b = new byte[temp.Length + 2];
for (int i = 0; i < temp.Length; i++)
{
b[i] = Convert.ToByte(temp[i], 16);
}
return b;
}
/// <summary>
/// 将字节数据转换为十六进制字符串,中间用 “ ”分割 如:AA AA AA AA 0A 00 68 00 06 03 04 54 21 28 22 E5 F3 16 BB BB BB BB
/// </summary>
/// <param name="vars">要转换的字节数组</param>
/// <returns></returns>
public static String ToHex(byte[] vars)
{
return BitConverter.ToString(vars).Replace('-', ' ').Trim();
}
CS校验(累加和)
public static string CSCheck(string str)
{
if (str.Length == 0) return "";
else str = str.Trim();
byte[] sss = ToBytes(str);
int n = 0;
for (int i = 0; i < sss.Length; i++)
{
n += sss[i];
}
return ToHex(n);
}
/// <summary>
/// AB CD 12 3B 转换为字节数组
/// </summary>
/// <param name="hex">十六进制字符串</param>
/// <returns></returns>
public static byte[] ToBytes(string hex)
{
string[] temp = hex.Split(' ');
byte[] b = new byte[temp.Length];
for (int i = 0; i < temp.Length; i++)
{
if (temp[i].Length > 0)
b[i] = Convert.ToByte(temp[i], 16);
}
return b;
}
/// <summary>
/// 转换为符合本程序的十六进制格式
/// </summary>
/// <param name="var">1 2 3 等。</param>
/// <returns>返回十六进制字符串,如果是1-9的话,前面带零</returns>
/// <example>例如: 5 ="05" 12 ="0C" 无论何时,都是两位数。 </example>
public static string ToHex(int var)
{
int cs = var;
string tmp = "";
if (cs == 0) { tmp = "00"; }
while (cs > 0)
{
int ys;
cs = Math.DivRem(cs, 256, out ys);
tmp = tmp.Insert(0, string.Format(" {0}", Right("00" + Convert.ToString(ys, 16), 2).ToUpper()));
}
return tmp.Trim();
}
public static string Right(string str, int Length)
{
if ((Length <= 0) || (str == null))
{
return "";
}
int length = str.Length;
if (Length >= length)
{
return str;
}
return str.Substring(length - Length, Length);
}
LRC校验(LRC错误校验用于ASCII模式)
/// <summary>
/// 取模FF(255)
/// 取反+1
/// </summary>
/// <param name="writeUncheck"></param>
/// <returns></returns>
public static string LRCheck(string writeUncheck)
{
char[] hexArray = new char[writeUncheck.Length];
hexArray = writeUncheck.ToCharArray();
int decNum = 0, decNumMSB = 0, decNumLSB = 0;
int decByte, decByteTotal = 0;
bool msb = true;
for (int t = 0; t <= hexArray.GetUpperBound(0); t++)
{
if ((hexArray[t] >= 48) && (hexArray[t] <= 57))
decNum = (hexArray[t] - 48);
else if ((hexArray[t] >= 65) & (hexArray[t] <= 70))
decNum = 10 + (hexArray[t] - 65);
if (msb)
{
decNumMSB = decNum * 16;
msb = false;
}
else
{
decNumLSB = decNum;
msb = true;
}
if (msb)
{
decByte = decNumMSB + decNumLSB;
decByteTotal += decByte;
}
}
decByteTotal = (255 - decByteTotal) + 1;
decByteTotal = decByteTotal & 255;
int a, b = 0;
string hexByte = "", hexTotal = "";
double i;
for (i = 0; decByteTotal > 0; i++)
{
b = Convert.ToInt32(System.Math.Pow(16.0, i));
a = decByteTotal % 16;
decByteTotal /= 16;
if (a <= 9)
hexByte = a.ToString();
else
{
switch (a)
{
case 10:
hexByte = "A";
break;
case 11:
hexByte = "B";
break;
case 12:
hexByte = "C";
break;
case 13:
hexByte = "D";
break;
case 14:
hexByte = "E";
break;
case 15:
hexByte = "F";
break;
}
}
hexTotal = String.Concat(hexByte, hexTotal);
}
return hexTotal;
}
public void LRCheck(byte[] code)
{
int sum = 0;
foreach (byte b in code)
{
sum += b;
}
sum = sum % 255;//取模FF(255)
sum = ~sum + 1;//取反+1
string lrc = Convert.ToString(sum, 16);
return lrc;
}
自定义Modbus数据表
自定义Modbus数据表例子:
设备相关读取信息:

命令报文信息解析:

自定义Modbus数据表定义注意
串口调试工具
串口调试工具的使用

串口调试工具 + RS485就可以读取硬件上的数据,和向硬件请求了,如何使用请看“调试篇”会有详细的说明。


网络调试助手:
调试助手主要还是TCP协议通讯的一个调试工具

在远程通信和计算机科学中,串行通信(英语:Serial communication)是指在计算机总线或其他数据信道上,每次传输一个比特数据,并连续进行以上单次过程的通信方式。与之对应的是并行通信,它在串行端口上通过一次同时传输若干比特数据的方式进行通信。串行通信被用于长距离通信以及大多数计算机网络,在这些应用场合里,电缆和同步化使并行通信实际应用面临困难。凭借着其改善的信号完整性和传播速度,串行通信总线正在变得越来越普遍,甚至在短程距离的应用中,其优越性已经开始超越并行总线不需要串行化组件(serializer),并解决了诸如时钟偏移(Clock skew)、互联密度(interconnect density)等缺点。PCI到PCI Express的升级就一个例子。
认识Modbus协议的更多相关文章
- modbus协议讲义
Modbus 一个工业上常用的通讯协议.一种通讯约定.Modbus协议包括RTU.ASCII.TCP.其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现.虽然RTU比较简单,但是看 ...
- 模拟Modbus协议问题
问题: 在嵌入式系统开发中,Modbus协议是工业控制系统中广泛应用的一种协议.本题用来简单模拟Modbus协议,只需根据条件生成符合该协议的数据帧,并解析所获取的数据.假设设备使用的协议发送数据格式 ...
- 各种非标232,485协议,自定义协议转modbus协议模块定制开发,各种流量计协议转modbus,
工业现场经常会碰到通过485或者232采集各类仪表数据,但是很多早期的仪表和设备不支持标准modbus协议,而是采用自定义的协议,这些协议数据由plc或者dcs系统来实现采集,不仅费时麻烦,而且不方便 ...
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...
- 基于AVR128单纯Modbus协议实施
Modbus通信协议Modicon公司1979在发展中,适用于工业现场总线协议控制.Modbus通信系统包含芯片的节点,并与组合物可编程控制的公共传输线,它的目的是收集和监视多个节点的数据.Modbu ...
- MODBUS协议详解
MODBUS是一个工业上通信常用的通讯协议,一般在PLC上面用的比较多,主要是定义了一种数据传输的规范,比如数据发给谁,数据是干嘛的,数据错没错,接收到数据的从机告诉我数据有没有接受到等. 传输的方式 ...
- C# MODBUS协议 上位机(转)
源:C# MODBUS协议 上位机 C#写了一款上位机监控软件,基于MODBUS_RTU协议. 软件的基本结构: 采用定时器(Timer控件)为时间片. 串口采用serialPort1_DataRec ...
- 串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧
串口屏Modbus协议,串口屏的modbus协议资料,串口屏modbus通讯协议开发,串口屏之modbus协议使用技巧 本例程中用51单片机作为Modbus从机,从机的设备地址为2,从机有4个寄存器, ...
- 《ServerSuperIO Designer IDE使用教程》-3.Modbus协议,读取多个寄存器,实现多种数据类型解析。发布:v4.2.2版本
更新内容,v4.2.2版本:1.增加Modbus协议读取多个寄存器,并且按多种数据类型解析数据.2.Modbus Serial和Modbus TCP两个驱动合并成一个驱动.3.修改数据库结构,保存配置 ...
随机推荐
- 工作中遇到的一些linux常用命令总结
零.查看历史命令,linux中可按“↑” “↓”查找之前输入的命令,亦可用 history 命令查看之前的输入,linux中的亦有“Tab”键可联想输入 一.root权限: 1.su 之后输入root ...
- python学习笔记5_异常
python学习笔记5_异常 1.什么事异常 Python使用异常对象(exception object) 来表示异常情况.遇到错误会发生异常. 如果异常对象未被处理或被捕捉,程序就会用所谓的回溯(t ...
- node编写定时任务,for循环只执行一遍的解决办法
在用node编写定时任务时候,发现for循环只执行i=0这一次,就不接着循环执行了,下面贴上代码: exports.task = async function(ctx){ let { app } = ...
- [认证授权] 2.OAuth2授权(续) & JWT(JSON Web Token)
1 RFC6749还有哪些可以完善的? 1.1 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何获得 ...
- linux ps aux 各列内容说明
[root@zabbix3 ~]# ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot ...
- windows系统下的特殊目录导致的FileNotFoundException
环境:下面只有JDK(内含jre),没有外在的jre 读取的两个文件都是存在的,只是文件名不同 运行结果1 运行结果2 切换JDK 运行结果3: 运行结果4: 请留意:C:\windows\syste ...
- 将root 当成arraylist放入数据sturts2 入门笔记
刚启动idea 就报出错误 [-- ::,] Artifact -sturts2:war exploded: Error during artifact deployment. See server ...
- Vue组件开发
在学习vue的时候,发现有很多使用vue开发的ui组件.本着学习的目的,自己也仿照Element写一些组件. 使用VuePress编写组件文档. 单元测试:karma+mocha+chai+sinon ...
- 台达PLC实现远程下载程序
台达PLC实现远程下载程序 日期:2019-04-27 时间 08:33:57 让物联变得更简单 18-09-2411:25 明明在公司调试没问题的设备一到 ...
- 用Python将一个列表分割成小列表
用Python将一个列表分割成小列表 2018年01月15日 11:09:25 幸福丶如此 阅读数:16842 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...