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;
        }
    
    }
}
原文地址:https://www.cnblogs.com/qq1151219115/p/10937022.html