转自:http://www.cnblogs.com/luomingui/archive/2013/06/14/Modbus.html

什么是Modbus?

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协议通讯的一个调试工具

最新文章

  1. 积极主动敲代码,使用Junit学习Java程序设计
  2. Java——布局管理器
  3. 通过GPS数据反向地理信息编码, 得到当前位置信息
  4. 即学即会 Java 程序设计基础视频教程(100课整)无水印版
  5. JRE和JDK的区别
  6. SqlServer 如何以脚本形式导出数据
  7. C#语法需要注意的地方
  8. 适用于cocos2dx的编辑器:Texture,Tilemap,Particle,Action,Level etc
  9. Yaroslav and Divisors
  10. underscorejs-reduceRight学习
  11. AngularJs学习html转义
  12. (原)下载pubFig的python代码
  13. 查找MobileSafari WebKit revision number的方法
  14. 在MFC中对Excel的一些操作
  15. linux内核里的字符串转换 ,链表操作常用函数(转)
  16. Linux 下面 PG 的 uuid-ossp 包安装办法
  17. 第41章:MongoDB-集群--Sharding(分片)
  18. Windows7 64下搭建Caffe+python接口环境
  19. VM虚拟机启动报错Reason Failed to lock the file怎么办
  20. 关于Virtual的英语含义

热门文章

  1. 关于proplists:get_value/2 与lists:keyfind/3 的效率比较
  2. 【React Native开发】React Native控件之RefreshControl组件具体解释(21)
  3. fzu 2039 Pets (简单二分图 + (最大流 || 二分图))
  4. python 基础 1.3 使用pycharm给python传递参数及pycharm调试模式
  5. Channel (digital image) 通道 色彩深度 Color_depth
  6. python多进程编程常用到的方法
  7. 你不得不知的几款常用的在线API管理工具
  8. Laravel的初始化安装
  9. 51Nod 机器人走方格 V3 —— 卡特兰数、Lucas定理
  10. Mac OS 配置Maven