1.Mymath
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace BIZHexagonalDevice{ class MyMath { ////// 字符串转BYTE数组 /// /// ///高位在前 static public byte[] StrToByte(string data) { byte[] bt = new byte[data.Length / 2]; for (int i = 0; i < data.Length / 2; i++) { bt[i] = Convert.ToByte(data.Substring(i * 2, 2), 16); } return bt; } ////// byte数组转STRING /// /// ///static public string BytetoStr(byte[] Bytes) { string str = string.Empty; str = BitConverter.ToString(Bytes, 0).Replace("-", string.Empty).ToLower(); return str; } /// /// 计算CRC-16 /// /// ///高位在前 static public string CRC_16(string data) { if ((data.Length % 2) != 0) { throw new Exception("Parameter\"data\"length error"); } byte[] tmp = StrToByte(data); /* 1、预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器; 2、把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器; 3、把寄存器的内容右移一位(朝低位),用0填补最高位,检查最低位; 4、如果最低位为0:重复第3步(再次移位); 如果最低位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或; 5、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; 6、重复步骤2到步骤5,进行下一个8位数据的处理; 7、最后得到的CRC寄存器即为CRC码。 */ UInt16 CRCREG = (UInt16)0xffff; for (int i = 0; i < tmp.Length; i++) { CRCREG = (UInt16)(CRCREG ^ (UInt16)tmp[i]);//<< 8; for (int j = 0; j < 8; j++) { UInt16 CRCtmp = (UInt16)(CRCREG & (UInt16)0x0001); CRCREG = (UInt16)(CRCREG >> (UInt16)1); if (CRCtmp == (UInt16)1) { CRCREG = (UInt16)(CRCREG ^ (UInt16)0xA001); } } } string strtmp = CRCREG.ToString("X4"); return strtmp.Substring(2, 2) + strtmp.Substring(0, 2); //return strtmp; } }}
2.modbus rtu通讯协议
using System;using System.Collections.Generic;using System.Text;//using WFDLL;namespace WfpRTU{ public class Modbus { protected string _PortName; public string PortName { get { return _PortName; } set { _PortName = value; SP.PortName = _PortName; } } protected int _PortBaud; public int PortBaud { get { return _PortBaud; } set { _PortBaud = value; SP.PortBaud = _PortBaud; } } protected int _Timeout; public int Timeout { get { return _Timeout; } set { _Timeout = value; SP.Timeout = _Timeout; } } protected System.IO.Ports.Parity _parity; public System.IO.Ports.Parity Parity { get { return _parity; } set { _parity = value; SP.Parity = _parity; } } protected MySerialPort SP = new MySerialPort(); public Modbus() { } public Modbus(string PName, int PBaud, System.IO.Ports.Parity parity, int timeout) { _PortName = PName; _PortBaud = PBaud; _Timeout = timeout; _parity = parity; SP.PortName = _PortName; SP.PortBaud = _PortBaud; SP.Timeout = timeout; SP.Parity = parity; } ////// 读取设备识别码(F0x2B) /// /// 通讯地址 /// ReadDevId /// 对象ID /// 数据 ///public MODBUSRESULT ReadDeviceRegister(string CommAddr, UInt16 ReadDevId, UInt16 ObjectId, out string data) { if ((CommAddr.Length % 2) != 0) { throw new Exception("CommAddr data length error"); } StringBuilder cmd = new StringBuilder(); cmd.Append(CommAddr); //通讯地址 cmd.Append("2B"); //功能码 cmd.Append("0E"); //MEI类型 cmd.Append(ReadDevId.ToString("X2")); //01 cmd.Append(ObjectId.ToString("X2")); //00 cmd.Append(MyMath.CRC_16(cmd.ToString())); return SP.SendAndReceive(cmd.ToString(),7, out data); } /// /// 读取多个线圈 /// /// 通讯地址 /// 功能码 /// 起始地址 /// 线圈数 /// 数据 ///public MODBUSRESULT ReadMultiCoil(string CommAddr, byte FunCode, UInt16 StartAddr, UInt16 RegCount, out string data) { if ((CommAddr.Length % 2) != 0) { throw new Exception("CommAddr data length error"); } StringBuilder cmd = new StringBuilder(); cmd.Append(CommAddr); //通讯地址 cmd.Append(FunCode.ToString("X2")); cmd.Append(StartAddr.ToString("X4")); //起始地址 cmd.Append(RegCount.ToString("X4")); //线圈数 cmd.Append(MyMath.CRC_16(cmd.ToString())); double cnt=RegCount / 8; return SP.SendAndReceive(cmd.ToString(), Convert.ToUInt16(Math.Ceiling(cnt)) + 4 + CommAddr.Length / 2, out data); } /// /// 写多个线圈 /// /// /// /// /// ///public MODBUSRESULT WriteMultiCoil(string CommAddr, byte FunCode, UInt16 StartAddr, string data) { if ((data.Length % 2) != 0) { throw new Exception("Data length error"); } StringBuilder cmd = new StringBuilder(); cmd.Append(CommAddr); //通讯地址 cmd.Append(FunCode.ToString("X2")); cmd.Append(StartAddr.ToString("X4")); //起始地址 //int RegCount = data.Length / 4; int bytecnt = data.Length / 2; int RegCount = bytecnt * 8;//--------------------------------------tgw------------------- cmd.Append(RegCount.ToString("X4")); //寄存器数 //int bytecnt = RegCount * 2; cmd.Append(bytecnt.ToString("X2")); //字节计数 cmd.Append(data); cmd.Append(MyMath.CRC_16(cmd.ToString())); return SP.SendAndReceive(cmd.ToString(), 7 + CommAddr.Length / 2, out data); } / / 读取输入寄存器(F0x04) / / 通讯地址 / 起始地址 / 寄存器数 / 数据 ///public MODBUSRESULT ReadInputRegister(string CommAddr, UInt16 StartAddr, UInt16 RegCount, out string data) //{ // if ((CommAddr.Length % 2) != 0) { throw new Exception("CommAddr数据长度错误"); } // StringBuilder cmd = new StringBuilder(); // cmd.Append(CommAddr); //通讯地址 // cmd.Append("04"); // cmd.Append(StartAddr.ToString("X4")); //起始地址 // cmd.Append(RegCount.ToString("X4")); //寄存器数 // cmd.Append(MyMath.CRC_16(cmd.ToString())); // return SP.SendAndReceive(cmd.ToString(), RegCount * 2 + 4 + CommAddr.Length / 2, out data); //} / / 读取保持寄存器(F0x03) / / 通讯地址 / 起始地址 / 寄存器数 / 数据 ///public MODBUSRESULT ReadHoldingRegister(string CommAddr, UInt16 StartAddr, UInt16 RegCount, out string data) //{ // if ((CommAddr.Length % 2) != 0) { throw new Exception("CommAddr数据长度错误"); } // StringBuilder cmd = new StringBuilder(); // cmd.Append(CommAddr); //通讯地址 // cmd.Append("03"); // cmd.Append(StartAddr.ToString("X4")); //起始地址 // cmd.Append(RegCount.ToString("X4")); //寄存器数 // cmd.Append(MyMath.CRC_16(cmd.ToString())); // return SP.SendAndReceive(cmd.ToString(), RegCount * 2 + 4 + CommAddr.Length / 2, out data); //} /// /// 读取多个寄存器 /// /// 通讯地址 /// 功能码 /// 起始地址 /// 寄存器数 /// 数据 ///public MODBUSRESULT ReadMultiRegister(string CommAddr, byte FunCode,UInt16 StartAddr, UInt16 RegCount, out string data) { if ((CommAddr.Length % 2) != 0) { throw new Exception("CommAddr data length error"); } StringBuilder cmd = new StringBuilder(); cmd.Append(CommAddr); //通讯地址 cmd.Append(FunCode.ToString("X2")); cmd.Append(StartAddr.ToString("X4")); //起始地址 string str = RegCount.ToString("X4"); cmd.Append(str); //寄存器数 cmd.Append(MyMath.CRC_16(cmd.ToString())); return SP.SendAndReceive(cmd.ToString(), RegCount * 2 + 4 + CommAddr.Length / 2, out data); } /// /// 写多个寄存器 /// /// /// /// /// ///public MODBUSRESULT WriteMultiRegister(string CommAddr, byte FunCode, UInt16 StartAddr, string data) { if ((data.Length % 4) != 0) { throw new Exception("Data length error"); } StringBuilder cmd = new StringBuilder(); cmd.Append(CommAddr); //通讯地址 cmd.Append(FunCode.ToString("X2")); cmd.Append(StartAddr.ToString("X4")); //起始地址 int RegCount = data.Length / 4; cmd.Append(RegCount.ToString("X4")); //寄存器数 int bytecnt = RegCount * 2; cmd.Append(bytecnt.ToString("X2")); //字节计数 cmd.Append(data); cmd.Append(MyMath.CRC_16(cmd.ToString())); return SP.SendAndReceive(cmd.ToString(), 7 + CommAddr.Length / 2, out data); } public static string GetResultMsg(MODBUSRESULT ret) { string msg = ""; switch (ret) { case MODBUSRESULT.DataAddrInvalid: msg = "Data address invalid"; break; case MODBUSRESULT.DataCheckFall: msg = "Data validation failure"; break; case MODBUSRESULT.DataFormatError: msg = "Data format error"; break; case MODBUSRESULT.DataValueInvalid: msg = "Data value invalid"; break; case MODBUSRESULT.OK: msg = "Correct"; break; case MODBUSRESULT.PortOpenFall: msg = "Open port failure"; break; case MODBUSRESULT.Timeout: msg = "Communication timeout"; break; case MODBUSRESULT.UnknownError: msg = "Unknown error"; break; case MODBUSRESULT.UnknownFunCode: msg = "Unsupported function code"; break; default: msg = "Unknown error"; break; } return msg; } public static string GetRegValue(string data,int StartReg,int RegNum)//按字符 { int offset = 6; int startpoint = offset + StartReg * 4; int len = RegNum * 4; return data.Substring(startpoint, len).ToUpper(); } public static string GetByteValue(string data, int StartReg, int RegNum)//按字符 { int offset = 6; int startpoint = offset + StartReg * 2; int len = RegNum * 2; return data.Substring(startpoint, len).ToUpper(); } }}
3.csv文件读写
/* * Created by SharpDevelop. * User: sz * Date: 2007/12/10 * Time: 18:09 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */using System;using System.Collections.Generic;using System.IO;using System.Text;namespace WfpRTU{ ////// CSVUtil is a helper class handling csv files. /// public class CSVUtil { private CSVUtil() { } //write a new file, existed file will be overwritten public static void WriteCSV(string filePathName,Listls) { WriteCSV(filePathName,false,ls); } //write a file, existed file will be overwritten if append = false public static void WriteCSV(string filePathName,bool append, List ls) { StreamWriter fileWriter=new StreamWriter(filePathName,append,Encoding.Default); foreach(String[] strArr in ls) { fileWriter.WriteLine(String.Join(",",strArr)); } fileWriter.Flush(); fileWriter.Close(); } public static List ReadCSV(string filePathName) { List ls = new List (); StreamReader fileReader=new StreamReader(filePathName); string strLine=""; while (strLine != null) { strLine = fileReader.ReadLine(); if (strLine != null && strLine.Length>0) { ls.Add(strLine.Split(',')); //Debug.WriteLine(strLine); } } fileReader.Close(); return ls; } }}
4.串口接收触发事件
private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e) { Thread.Sleep(1000); if (Com.IsOpen) { try { byte[] ReDatas = new byte[Com.BytesToRead]; if (Com.BytesToRead <= 0) { txtData.Text = "没查询到数据,请检查设置"; } else { Com.Read(ReDatas, 0, ReDatas.Length); string temHex = BytesToHex(ReDatas); } catch (Exception ex) { MessageBox.Show(ex.Message, "出错提示!!!!!"); txtData.Text = ""; } } else { txtData.Clear(); txtData.Text = "请检查串口是否打开"; } }