ModbusDataConvert.cs 9.5 KB
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.IO;
using log4net;
using System.Reflection;

namespace OnlineStore.Common
{
    public   class ModbusDataConvert
    {
        public static readonly ILog LOGGER = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        private string btn_sender = "";
        private const int read_num = 99;
        private const int read_num2 = 60;

        private Boolean received = false;

        private SerialPort mySerialPort;
        private System.Timers.Timer timer1;

        public ModbusDataConvert()
        {
            timer1 = new System.Timers.Timer();
            timer1.Interval = 100;
            timer1.AutoReset = true;
            timer1.Elapsed += timer1_Elapsed;
        }

        void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void btnOpen_Click(string myParity, string myStopBits, string portName, int baudRate,int dataBits)
        {
            mySerialPort = new SerialPort();
            //设置校验位
            switch (myParity)
            {
                case "None":
                    mySerialPort.Parity = Parity.None;
                    break;
                case "Even":
                    mySerialPort.Parity = Parity.Even;
                    break;
                case "Odd":
                    mySerialPort.Parity = Parity.Odd;
                    break;
                default:
                    mySerialPort.Parity = Parity.None;
                    break;
            }

            //设置数据位
            mySerialPort.DataBits = dataBits;

            //设置停止位
            switch (myStopBits)
            {
                case "1":
                    mySerialPort.StopBits = StopBits.One;
                    break;
                case "2":
                    mySerialPort.StopBits = StopBits.Two;
                    break;
                default:
                    mySerialPort.StopBits = StopBits.One;
                    break;

            }
            //采用ASCII编码方式
            mySerialPort.Encoding = Encoding.ASCII;
            //接收到一个字符就触发接收事件
            mySerialPort.ReceivedBytesThreshold = 1;

            //试图打开指定串口
            try
            {
                if (mySerialPort.IsOpen == false)
                {
                    mySerialPort.Open();        //打开串口 
                }
            }
            //打开异常,输出提示信息
            catch
            {
                LogUtil.error(LOGGER, "串口异常,无法打开" );
            }

        }

        private void btnClose_Click()
        {
            if (mySerialPort.IsOpen == true)
            {
                mySerialPort.Close();       //关闭串口 
                LogUtil.error(LOGGER, "串口已关闭"); 
            }
        }

        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] b = new byte[mySerialPort.BytesToRead];//定义byte数组,serialPort读取数据               

            mySerialPort.Read(b, 0, b.Length);

            string str = "";
            for (int i = 0; i < b.Length; i++)
            {
                str += string.Format("{0:X2} ", b[i]);
            }
            LogUtil.info(LOGGER, "收到串口反馈数据:" + str);
            str = null;
            received = true;
        }


        public static void formatstring(string strinput, int length, out string stroutput, out Boolean Valid)
        {
            stroutput = "";
            Valid = true;
            byte temp;

            if  ((strinput.Length <= length) & (strinput.Length > 0))
            {
                for (int i = 0; i < strinput.Length; i++)
                {
                    try
                    {
                        temp = Convert.ToByte(strinput[i].ToString(), 16);
                    }

                    catch
                    {
                        Valid = false;
                        stroutput = "";
                        break;
                    }

                    stroutput += strinput[i];
                }

                if (Valid & (strinput.Length < length))
                {
                    for (int j = 0; j < length - strinput.Length; j++)
                    {
                        stroutput = "0" + stroutput;
                    }
                }
            }

            else
            {
                Valid = false;
                stroutput = "";
            }
        }


        private void btnsend_Click(string deviceAdd, string add1,string writData)
        {
            //btn_sender = ((Button)sender).Text.ToString();
            byte[] defByte = new byte[6]; 

            //设备号
            string str1x = deviceAdd;
            string str1 = "";
            Boolean Macvalid1; 
            formatstring(str1x, 2, out str1, out Macvalid1); 
            if (!Macvalid1)
            {
                LogUtil.info(LOGGER,"设备地址数值不符合规范,最多输入2位十六进制数");
                return; 
            }

            byte[] numbyte1 = this.mysendb(str1);
            defByte[0] = numbyte1[0];

            //功能码 - 06
            string fun_str1 = "06";
            byte[] fun_numbyte1 = this.mysendb(fun_str1);
            defByte[1] = fun_numbyte1[0];

            //地址
            string str2x = add1.ToString();
            string str2 = "";
            Boolean addrvalid1;

            formatstring(str2x, 4, out str2, out addrvalid1);

            if (!addrvalid1)
            {
                LogUtil.info(LOGGER,"寄存器地址数值不符合规范,最多输入4位十六进制数");
                return;
            }

            // textBoxInformation.AppendText(str2);

            byte[] numbyte2 = this.mysendb(str2);
            defByte[2] = numbyte2[0];
            defByte[3] = numbyte2[1];

            //写入的数据
            string str3x = writData;
            string str3 = "";
            Boolean valuevalid1;

            formatstring(str3x, 4, out str3, out valuevalid1);

            if (!valuevalid1)
            {
                LogUtil.info(LOGGER, "输入数值不符合规范,最多输入4位十六进制数");
                return;
            }

            byte[] numbyte3 = this.mysendb(str3);
            defByte[4] = numbyte3[0];
            defByte[5] = numbyte3[1];

            //计算CRC
            byte crch = 0;
            byte crcl = 0;

            CalculateCRC(defByte, defByte.Length, out crch, out crcl);

            // MOVE给新的数组
            byte[] rebyte = new byte[defByte.Length + 2];

            for (int i = 0; i < defByte.Length; i++)
            {
                rebyte[i] = defByte[i];
            }

            rebyte[6] = crcl;
            rebyte[7] = crch;

            received = false; 
            this.mySerialPort.Write(rebyte, 0, rebyte.Length); // 发送 

            //起动计时器
            timer1.Enabled = true;
            string strSend = ""; 
            for (int i = 0; i < rebyte.Length; i++)
            {
                strSend += string.Format("{0:X2} ", rebyte[i]);
            }
            LogUtil.info(LOGGER, "发送【" + strSend + "】成功\r\n");
             
        }

        //打包方法,可以将字符串转成byte[] 
        public byte[] mysendb(string s)
        {
            string temps = delspace(s);

            if (temps.Length % 2 != 0)
            {
                temps = "0" + temps;
            }

            byte[] tempb = new byte[50];
            int j = 0;

            for (int i = 0; i < temps.Length; i = i + 2, j++)
            {
                tempb[j] = Convert.ToByte(temps.Substring(i, 2), 16);
            }

            byte[] send = new byte[j];
            Array.Copy(tempb, send, j);
            return send;
        }

        //除去空格
        public string delspace(string putin)
        {
            string putout = "";

            for (int i = 0; i < putin.Length; i++)
            {
                if (putin[i] != ' ')
                    putout += putin[i];
            }

            return putout;
        }

        public static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
        {
            int nBit;
            ushort nShiftedBit;
            pChecksum = 0xFFFF;

            for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
            {
                pChecksum ^= pByte[nByte];
                for (nBit = 0; nBit < 8; nBit++)
                {
                    if ((pChecksum & 0x1) == 1)
                    {
                        nShiftedBit = 1;
                    }
                    else
                    {
                        nShiftedBit = 0;
                    }
                    pChecksum >>= 1;
                    if (nShiftedBit != 0)
                    {
                        pChecksum ^= 0xA001;
                    }
                }
            }
        }

        public static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out byte hi, out byte lo)
        {
            ushort sum;
            CalculateCRC(pByte, nNumberOfBytes, out sum);
            lo = (byte)(sum & 0xFF);
            hi = (byte)((sum & 0xFF00) >> 8);
        }

       
    }
}