C# 遵守Modbus协议实现数据的发送-采用Nmodbus类库

所有的代码都贴出来了,有需要的朋友可以自行选择性的看一下。

一、运用到知识
初步了解简单的modbus协议、会查询Nmodbus类库、不懂英文的会使用有道词典阅读部分英文文档、会简单的C#语言、了解SerialPort类库。
二、项目环境
Win10系统、8G运行内存、i7处理器、VisualStudio2015
三、项目搭建
1、新建一个命名为“MyConsoleDemo”窗体的项目
2、右击引用进入NuGet,安装NModbus4
四、代码实现
1、页面布局
在这里插入图片描述

using Modbus.Device;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

// 使用命名空间
namespace MyConsoleDemo
{
    public partial class Form1 : Form
    {
       
        // 成员变量
        private SerialPort sp;
        private string protName;
        private int baudRate;
        private int deteBites;
        private StopBits stopBits;
        private Parity parity;
        
        
        //构造方法
        public Form1()
        {
            InitializeComponent();
            SerialPortSet();
        }
        // 串口设置方法
        private void SerialPortSet()
        {
            //  sp = new SerialPort();
            string [] PortNames = SerialPort.GetPortNames();
            // IEnumerable<String> query = PortNames.OrderBy(x => x);
             Array.Sort(PortNames);  // 在出现字符“com1 , com2, com10”,会排序出错!  ---- 未解决
            // 获取所有串口号
            foreach (String item in PortNames)  // 无法使用实例引用来调用 sp.GetPortNames()报错
            {
                this.CB_SerialPort.Items.Add(item);
            }
            // 下拉框默认值设定
            this.CB_SerialPort.SelectedIndex = 0;
            this.CB_BaudRate.SelectedIndex = 0;
            this.CB_ParityBit.SelectedIndex = 0;
            this.CB_DateBits.SelectedIndex = 0;
            this.CB_StopBits.SelectedIndex = 0;
            this.CB_BufferSize.SelectedIndex = 0;
            // this.CB_SerialPort.Text = "COM1"; 另一种设置下拉框默认值方式

        }
        // 打开串口
        private void OpenSerialPortClick(object sender, EventArgs e)
        {
            // 实例化SerialPort对象
            sp = new SerialPort();

            //赋值
            protName = this.CB_SerialPort.Text;  // 设置串口号
            // Console.WriteLine(sp.PortName);
            baudRate = int.Parse(this.CB_BaudRate.Text); // 设置波特率
            deteBites = int.Parse(this.CB_DateBits.Text); // 设置数据位
            stopBits = (StopBits)Enum.Parse(typeof(StopBits), this.CB_StopBits.Text); //设置停止位
            parity = (Parity)Enum.Parse(typeof(Parity), this.CB_ParityBit.Text); //设置校验位
            // 串口设置
            /*
             *  NONE
                ODD
                EVEN
                MARK
                SPACE
             */
            sp.PortName = protName;
            sp.BaudRate = baudRate;
            sp.DataBits = deteBites;
            sp.StopBits = stopBits;
            sp.Parity = parity;
            sp.Open();
        }
        // 关闭串口
        private void CloseSerialPortClick(object sender, EventArgs e)
        {
            sp = new SerialPort();

            //赋值
            protName = this.CB_SerialPort.Text;  // 设置串口号
            // Console.WriteLine(sp.PortName);
            baudRate = int.Parse(this.CB_BaudRate.Text); // 设置波特率
            deteBites = int.Parse(this.CB_DateBits.Text); // 设置数据位
            stopBits = (StopBits)Enum.Parse(typeof(StopBits), this.CB_StopBits.Text); //设置停止位
            parity = (Parity)Enum.Parse(typeof(Parity), this.CB_ParityBit.Text); //设置校验位
            sp.BaudRate = baudRate;
            sp.DataBits = deteBites;
            sp.StopBits = stopBits;
            sp.Parity = parity;
            sp.Close();
            // 清空文本域的信息
            RTB_OpenText.Text = "";
        }
        // 发送信号
        private void SendSignalClick(object sender, EventArgs e)
        {

            // 获取文本域的值
            //RichTextBox rb = new RichTextBox();
            //this.RTB_OpenText.Text = "2324"; 设置文本域的值
            string [] GetOpenText = RTB_OpenText.Lines;
           
            //string OpenText = null;
            ushort[] registers = (from  x in GetOpenText select ushort.Parse(x)).ToArray();
            foreach(ushort item in registers)
            {
                Console.WriteLine(item);
            }

            // 获取选择框的值
           // if (CK_OpenSexadecimal.Checked)  // 判断十六进制是否被中
            //{
                //OpenText = GetHexFromChs(OpenText); // 用户选中十六进制,发送信号文本域内容转化为十六进制
           // }
          //  if (CK_OpenString.Checked) // 判断字符是否被选中
           // {
                //OpenText = GetChsFromHex(OpenText); // 用户选中字符,发送信号文本域内容转化为字符型
           // }
            // 发送信号逻辑 
            try
            {
                // 判断串口是否开启
                if (sp.IsOpen)
                {
                    // RTU
                   IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(sp);
                    // 
                    byte slaveID = 1;
                    // 地址域
                    ushort startAddress = 100;
                    master.WriteMultipleRegisters(slaveID, startAddress, registers);
                    // 串口已经开启就将文本域的值传输过去
                    //sp.Write(OpenText);
                }
                else
                {
                    MessageBox.Show("串口未打开!");
                }
            }
            catch(Exception ex)
            {
              // 捕获到异常
               sp = new SerialPort();
                // 刷新COM选项
                CB_SerialPort.Items.Clear(); // 清空集合中的元素
                /*
                 * AddRange:添加数据到集合
                 * -- 将ICollection接口的一个集合的所有元素到指定集合的末尾
                 * 将SerialPort.GetPortNames()集合的所有元素添加到CB_SerialPort.Items集合中
                 */
                CB_SerialPort.Items.AddRange(SerialPort.GetPortNames());
               ///  System.Media.SystemSounds.Beep.Play(); 开启背景音乐,提示音
                MessageBox.Show(ex.Message);
            }
        }
        
        // 字符串转16进制--由于使用的是Modbus协议暂时没有使用到数据类型转换
        private string GetHexFromChs(string toSendHex)
        {
            if((toSendHex.Length % 2) != 0)
            {
                toSendHex += ""; //空格
            }
            Encoding chs = Encoding.GetEncoding("gb2312");
            byte[] bytes = chs.GetBytes(toSendHex);
            string str = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);
            }
            return str;
        }
        // 十六进制转化为字符串---由于使用的是Modbus协议暂时没有使用到数据类型转换
        private string GetChsFromHex(string toSendChs)
        {
            // 判断文本内容是否为空
            if (toSendChs == null)
            {
                
            }

            if (toSendChs.Length % 2 != 0)
            {
                toSendChs += "20";//空格
            }

            // 需要将 hex 转换成 byte 数组。
            byte[] bytes = new byte[toSendChs.Length / 2];

            for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。
                    bytes[i] = byte.Parse(toSendChs.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message.
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }

            // 获得 GB2312,Chinese Simplified。
            Encoding chs = Encoding.GetEncoding("GB2312");

            return chs.GetString(bytes);
        }

        private void ReceiptSignaClick(object sender, EventArgs e)
        {
            RTB_ReceiptText.Text = "";
            IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(sp);
            byte slaveID = 1;
            ushort startAddress = 100;
            //master.ReadWriteMultipleRegisters(slaveID, startAddress);
            // 串口已经开启就将文本域的值传输过去
            //sp.Write(OpenText);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/My_CODEart/article/details/106361140