zoukankan      html  css  js  c++  java
  • 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('');
                //string dd = "wefef";
                //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);
                    }
    
    
    
                }));
    
    
    
            }
    
    
        }
    }
    
    
  • 相关阅读:
    bash变量作用域问题
    grep sed awk find用法
    vim compare 比对
    python的位数问题
    mysql使用
    lua 学习
    iptables的使用
    地铁换乘
    NOJ 1063 生活的烦恼
    猴子的下落
  • 原文地址:https://www.cnblogs.com/wolf12/p/7919796.html
Copyright © 2011-2022 走看看