首页/文章列表/文章详情

Modbus ASCII 获取数据

编程知识1832024-08-27评论

根据银河高低温试验箱协议读取数据

1.协议内容

8.1:通讯协议介绍8.1.5 通讯设置本通讯协议使用异步串行通讯方式,1 个起始位、8 个数据位、2 个停止位、无奇偶校验数据通讯格式,其中数据位8 位,第1 位为最高位(MSB),第8位为最低位(LSB)。8.1.6 数据格式通讯采用直接存取S7-200 V 存储器数据的方式,所有的参数均放置于S7-200 V存储器中,S7-200 中的数据类型为BYTE(字节)、INT(有符号整数)、WORD(无符号整数)、DWORD(无符号长整)、LONG(有符号长整)、FLOAT(浮点数)等格式,位操作按字节方式操作,一个字节8 个位。其中BYTE 长度为1字节;INT 和WORD为2字节,先高后低;DWORD和LONG 为4字节,先高后低;浮点数为4字节。详细资料可参考西门子SIMATIC S7-200 可编程控制器系统手册。8.1.7 读参数命令命令格式:>MMVDUUUUr>:起始字符MM:机号(在编程时因该转换为16进制数据)VD:读命令UUUU:S7200 内部V 存储器地址(在编程时因该转换为16 进制数据)r:回车字符响应数据格式:<MMVDUUUUaabbccddee…r<MMVDUUUU:响应命令头aabbccddee:从指定的V单元开始的128字节,每2个字符代表一个字节。r:回车字符

8.1.8 PLC地址说明

参数名称V地址单元数据格式数据说明
运行状态904int0 停止 1 运行 2 暂停
温度测量值804float单位:℃
湿度测量值860float单位:RH%

2.使用串口助手调试

  1. 串口助手设置
串口参数参数值
波特率9600
数据位8
停止位2
校验位
流控
  1. 调试截图
    img
    命令说明 要在命令后面添加回车,否则PLC无法识别命令。
>00VD0388 :获取设备运行状态 返回结果: <00VD0388000000010000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000FA03B6000000FA0000FDDA0000>00VD0324 :获取温度测量值 返回结果:<00VD032441EA980041EABDD541F6580041FBE0000000000044864400447EBA00000000000000000000000000000000000000000041C80000000000000000000000000000>00VD035C :获取湿度测量值 返回结果:<00VD035C00000000000000000000000001000400000000000000000000000000000000000000000000000000000000000000000100000002000400000000000000000000

根据命令返回结果,解析数据,获取温度测量值和湿度测量值。

1.由于返回结果为16进制,需要将16进制进行状态。

2.温度测量值和湿度测量值在返回结果中的位置分别为:41EA9800和00000000,需要将这两个值转换为float类型。
3.运行状态在返回结果中的位置为:0000(截取命令后4位),转换为整数值为0。

4.温度测量值为41EA9800(截取命令后8位),转换为浮点数为:29.324219。

5.湿度测量值为00000000(截取命令后8位),转换为浮点数为:0。

3.C# 使用 SerialPort 发送命令接收数据

  1. 初始化串口信息并打开串口
 private void OpenCom() { // 创建SerialPort对象 serialPort = new SerialPort(txtPort.Text.Trim(), 9600, Parity.None, 8, StopBits.Two); serialPort.ReadTimeout = 1000; //串口读取超时时间 serialPort.WriteTimeout = 1000; //串口写入超时时间 // 打开串口 serialPort.Open(); }
  1. 发送命令并接收数据
重点:将字符串转换为ASCII码字节数组 byte[] asciiBytes = Encoding.ASCII.GetBytes(request);如果不通过ASCII码字节数组发送,则无法正确接收数据。

img

public string SendOrderToPLC(string request) { string txt = string.Empty; try { OpenCom(); // 将字符串转换为ASCII码字节数组 byte[] asciiBytes = Encoding.ASCII.GetBytes(request); // 发送字节数组 serialPort.Write(asciiBytes, 0, asciiBytes.Length); //等待数据接收完成 数据量小等待时间可小,数据量大等待时间长 Thread.Sleep(1000); ASCIIEncoding ascii = new ASCIIEncoding(); byte[] readBuffer = new byte[serialPort.BytesToRead]; serialPort.Read(readBuffer, 0, readBuffer.Length); if (readBuffer.Length > 14) { txt = ascii.GetString(readBuffer); // 关闭串口 serialPort.Close(); return txt; } else { this.Invoke(new Action(() => { this.labMes.Text ="No response received"; })); serialPort.Close(); return txt; } } catch (Exception ex) { txt = null; this.Invoke(new Action(() => { this.labMes.Text = ex.Message; })); return txt; } }
  1. 处理数据
 处理设备运行状态数据 //获取设备运行状态 ,取的是整数 所以16进制取4位;排除前面的<00VD0388命令  var stringSub = result.Substring(9, 4); var st = HexToDecimal(stringSub); 处理温度数据  var stringSub = result.Substring(9, 8); var st = HexToDecimal(stringSub);  var stringSub = result.Substring(9, 8); var st = HexToDecimal(stringSub);

4.数据转换方法

 /// <summary> /// 将16进制字符串转换为浮点数 /// </summary> /// <param name="hex"></param> /// <returns></returns> static double HexToDecimal(string hex) { uint intValue = Convert.ToUInt32(hex, 16); // 将整数值转换为单精度浮点数 float floatValue = BitConverter.ToSingle(BitConverter.GetBytes(intValue), 0); // 输出结果 Console.WriteLine("Hex:" + hex); Console.WriteLine("Float:" + floatValue); return floatValue; }

博客园

这个人很懒...

用户评论 (0)

发表评论

captcha