RS485转RS232
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO.Ports; namespace serial { public class ModBus { /// <summary> /// modbus状态 /// </summary> public static string modbusStatus; /// <summary> /// 定义SerialPort变量 /// </summary> public static SerialPort Port = new SerialPort(); /// <summary> /// 打开串口 /// </summary> /// <param name="m_Port">串口号</param> /// <param name="BaudRate">波特率</param> /// <param name="m_dataBits">数据位</param> /// <param name="m_Parity">奇偶校验</param> /// <param name="m_StopBits">停止位</param> /// <returns>返回BOOL型,True为成功,False为失败</returns> public static bool OpenPort(string m_Port, int BaudRate, int m_dataBits, Parity m_Parity, StopBits m_StopBits) { if (Port.IsOpen) { return true; } else { Port.PortName = m_Port; Port.BaudRate = BaudRate; Port.DataBits = m_dataBits; Port.Parity = m_Parity; Port.StopBits = m_StopBits; Port.Open(); if (Port.IsOpen) { return true; } else { return false; } } } /// <summary> /// 关闭串口 /// </summary> /// <returns>返回BOOL型,True为成功,False为失败</returns> public static bool PortClose() { if (Port.IsOpen) { Port.Close(); return true; } else { return false; } } public static void GetCRC(byte[] message, byte[] CRC) { //Function expects a modbus message of any length as well as a 2 byte CRC array in which to //return the CRC values: ushort CRCFull = 0xFFFF; byte CRCHigh = 0xFF, CRCLow = 0xFF; char CRCLSB; for (int i = 0; i < (message.Length) -2; i++) { CRCFull = (ushort)(CRCFull ^ message[i]); for (int j = 0; j < 8; j++) { CRCLSB = (char)(CRCFull & 0x0001); CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); if (CRCLSB == 1) CRCFull = (ushort)(CRCFull ^ 0xA001); } } CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF); CRC[0] = CRCLow = (byte)(CRCFull & 0xFF); } /// <summary> /// CRC16算法 /// </summary> /// <param name="te">原始数组</param> /// <param name="message">保存变量</param> public static void BuildMessage(byte[] te, ref byte[] message) { //Array to receive CRC bytes: byte[] CRC = new byte[2]; for (int i = 0; i < te.Length; i++) { message[i] = te[i]; } GetCRC(message, CRC); message[message.Length - 2] = CRC[0]; message[message.Length - 1] = CRC[1]; } /// <summary> /// 发送数据 /// </summary> /// <param name="m_date">需写入的数据</param> /// <param name="type">操作类型0为多输出口控制与open参数不共用,1为单控制口输出open为255时线圈闭合0时线圈释放</param> /// <param name="open">1为单控制口输出open为255时线圈闭合0时线圈释放</param> /// <returns>返回True或false</returns> public static bool SendMessage(byte m_date,int type,bool open=true) { if (!Port.IsOpen) { return false; } else { switch (type) { case 0://多个DO输出控制数据位{ 地址, 功能, 线圈起始地址前位, 线圈起始地址后位, 线圈结束地址前位, 线圈结束地址后位, 数据字节, 线圈状态 }; byte[] data = new byte[10]; byte[] dd = { 1, 15, 0, 0, 0, 8, 1, m_date }; ModBus.BuildMessage(dd, ref data); Port.Write(data, 0, data.Length); break; case 1://单个控制输出{ 地址, 功能, 线圈起始地址前位, 需控制的线圈地址, 开关状态255为开0为关, 线圈开关后位 }; byte[] data_one = new byte[8]; byte temp0; if (open) { temp0 = 255; } else { temp0 = 0; } byte[] dd1 = { 1, 5, 0, m_date, temp0, 0 }; ModBus.BuildMessage(dd1, ref data_one); Port.Write(data_one, 0, data_one.Length); break; case 2: byte[] getsig = new byte[8]; byte[] getsige = { 1, 2, 0, 0, 0, m_date }; ModBus.BuildMessage(getsige, ref getsig); Port.Write(getsig, 0, getsig.Length); break; case 3: break; } return true; } } #region Check Response private static bool CheckResponse(byte[] response) { //Perform a basic CRC check: byte[] CRC = new byte[2]; GetCRC(response, CRC); if (CRC[0] == response[response.Length - 2] && CRC[1] == response[response.Length - 1]) return true; else return false; } #endregion #region Get Response private static void GetResponse(ref byte[] response) { //There is a bug in .Net 2.0 DataReceived Event that prevents people from using this //event as an interrupt to handle data (it doesn't fire all of the time). Therefore //we have to use the ReadByte command for a fixed length as it's been shown to be reliable. for (int i = 0; i < response.Length; i++) { response[i] = (byte)(Port.ReadByte()); } } #endregion public static bool GetModbusData(ref byte[] values) { if (Port.IsOpen) { int count = Port.BytesToRead; if (count > 0) { byte[] readBuffer = new byte[count]; GetResponse(ref readBuffer); // CRC 验证 if (CheckResponse(readBuffer)) { //显示输入数据 values = readBuffer; Port.DiscardInBuffer(); return true; } else { Port.DiscardInBuffer(); return false; } } else return false; } else return false; } } }
posted on 2019-05-28 14:12 qq1151219115 阅读(491) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗