C# MODBUS 通信

背景

電廠有多組監控設備,需要在指定的設備上顯示某些數據(其他設備對接過來的)。通信協議是modbus主從結構。

源碼:

http://download.csdn.net/download/wolf12/8931267

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.Net.Sockets;
using System.Net;

namespace ModsDataCtl
{
    public partial class Form1 : Form
    {
        System.IO.Ports.SerialPort com;

        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Microsoft.VisualBasic.Devices.Computer pc = new Microsoft.VisualBasic.Devices.Computer();

            foreach (string s in pc.Ports.SerialPortNames)//遍歷本機所有串口
            {
                this.comboBox1.Items.Add(s);
            }

            com = new System.IO.Ports.SerialPort();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                com.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString();

                com.BaudRate = 9600;//波特率
                com.Parity = Parity.None;//無奇偶校驗位
                com.StopBits = StopBits.One;//兩個停止位
                //  com.Handshake = Handshake.RequestToSendXOnXOff;//控制協議
                com.ReadTimeout = 2000;
                com.WriteTimeout = 2000;
                //com.ReceivedBytesThreshold = 4;//設置 DataReceived 事件發生前內部輸入緩衝區中的字節數
                // com.NewLine = "/r/n";
                com.RtsEnable = true;
                com.Open(); //打開串口

                MessageBox.Show("串口打開成功");
            }
            catch
            {
                MessageBox.Show("串口已打開!");
            }
        }
        /// <summary>
        /// 監聽com端口接收的報文
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                StringBuilder strBuilder = new StringBuilder();
                while (com.BytesToRead > 0)
                {
                    char ch = (char)com.ReadByte();
                    strBuilder.Append(ch);
                }
                strBuilder = new StringBuilder();
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message.ToString());
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //發送指令
            byte[] sendbyte = new byte[8] { 01, 03, 0x0F, 0xA0, 00, 24, 46, 0xE7 };

            com.Write(sendbyte, 0, sendbyte.Length);
            MessageBox.Show("成功");
        }
        Thread thread;
        private void button3_Click(object sender, EventArgs e)
        {
            com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
    
            MessageBox.Show("發送成功");
        }

        private void button4_Click(object sender, EventArgs e)
        {

            com.Close(); //關閉串口
        }
        /// <summary>
        /// 測試
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            TcpClient tcp = new TcpClient();
            UdpClient udp = new UdpClient();
            udp.Connect("127.0.0.1", 7102);
            // tcp.Connect("192.168.1.101", 7101);
            // NetworkStream ns = ud
            byte[] sendbyte = new byte[8] { 01, 03, 0x0F, 0xA0, 0x00, 0x24, 0x46, 0xE7 };
            // byte[] sendbyte = new byte[8] { 01, 03, 10, 00, 00,02, 0xC0, 0xCB};
            // 01 0F 00 01 00 04 01 00 03 56
            // 01 06 00 01 00 17 98 04 
            //01 03 10 00 00 02 C0 CB
            // ns.Write(sendbyte, 0, sendbyte.Length);
            udp.Send(sendbyte, sendbyte.Length);
            //System.Net.IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7101);
            //var fff = udp.Receive(ref ip);
        }



        #region CRC


        /// <summary>
        /// 計算CRC-16
        /// </summary>
        /// <param name="data"></param>
        /// <returns>高位在前</returns>
        public byte[] CRC_16(string data)
        {
            if ((data.Length % 2) != 0) { throw new Exception("參數\"data\"長度不合法"); }
            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");
            byte[] retunBtye = new byte[8];
            tmp.CopyTo(retunBtye, 0);
            retunBtye[6] = StrToByte(strtmp.Substring(2, 2))[0];
            retunBtye[7] = StrToByte(strtmp.Substring(0, 2))[0];
            return retunBtye;
        }


        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;
        }

        #endregion

        private void timer1_Tick(object sender, EventArgs e)
        {
            //byte f = Convert.ToByte('\0');
            //string dd = "wefef\0";
            //byte[] fef = System.Text.Encoding.Default.GetBytes(dd);

            //  MessageBox.Show(com.BytesToRead.ToString());



            //01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59

            /*
             16:05:16.859 回覆(no=077): 01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59
   16:05:16.859 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正確
             * 
             * 16:07:09.406 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正確
             */


            /*
             從機
16:07:26.484 回覆(no=077): 01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59
16:07:26.484 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正確
             */
        }

        void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            this.Invoke(new Action(() =>
            {

                byte[] buffer = new byte[com.BytesToRead];

                com.Read(buffer, 0, com.BytesToRead);

                string instr = "";

                foreach (byte b in buffer)
                {
                    instr += b.ToString("X2");
                }
                if (instr != "")
                {
                    this.listBox1.Items.Add("收到:" + instr);
                }

               // byte[] sendbyte = new byte[] { 0x01, 0x03, 0x48, 0x01, 0xF4, 0x00, 0x00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xE3, 0x59 };
                byte[] sendbyte = new byte[] {  01,03,02,01,0xF4,0xB8,0x53};

               
                com.Write(sendbyte, 0, sendbyte.Length);

                string wri = "";

                foreach (byte b in sendbyte)
                {
                    wri += b.ToString("X2");
                }
                if (wri != "")
                {
                    this.listBox1.Items.Add("回覆:" + wri);
                }



            }));



        }


    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章