基于Modbus协议的C#串口工具开发

(Tips:本人纯萌新小白一枚,文章只为记录自己的编程历史,温故而知新,能帮助到大家倍感荣幸,有错误的地方劳烦指点!)

不多废话直接进入主题!

本文旨在基于Modbus协议、C#开发语言进行串口工具的开发工作:

首先是界面的设计:

初次设计,界面略显花哨,各位按需进行颜色的设置。

用到的控件有:label(文本)、textBox(文本框)、comboBox(下拉框)、button(按键)、groupBox(组合框)、timer(时钟)、serialPort(串口) 。

由于是初次设计,所以内容较为单薄,且有未实现的功能(例如10H指令并未实现)

首先是Form(主函数)的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Modbus.Data;
using Modbus.Device;
using Modbus.Message;
using Modbus调试工具_demo_.Properties;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace Modbus调试工具_demo_
{
    public partial class Form1 : Form
    {
        #region 一些定义
        /// <summary>
        /// 私有串口实例
        /// </summary>
        private SerialPort serialPort = new SerialPort();   
        //定义接收字节数组
        byte[] Data = new byte[1024];
        byte ReceiveByte;
        int ReceiveByteCount = 0;
        //定义设备地址
        int CurrentAddr = 1;
        int Word;
        //定义返回报文
        string ReceiveData;
        #endregion

        public Form1()
        {
            InitializeComponent();

            Control.CheckForIllegalCrossThreadCalls = false;
        }

        #region 打开窗口触发事件(存在问题需要修改!!!)
        private void Form1_Load(object sender, EventArgs e)
        {
            //(待程序调整好后启用) MessageBox.Show("欢迎使用本软件!\r\n", "MB调试工具");
            this.MaximumSize = this.Size;
            this.MinimumSize = this.Size; //固定程序窗口大小;
            button1.Text = "打开串口";
            button1.BackColor = Color.Green;
            button9.BackColor = Color.Yellow;
            button3.Enabled = false;
            button4.Enabled = false;
            button5.Enabled = false;
            button6.Enabled = false;
            button7.Enabled = false;
            checkBox1.Enabled = false;
            timer3.Start();

            this.textBox3.Text = Settings.Default.One;
            this.textBox4.Text = Settings.Default.Two;
            this.textBox5.Text = Settings.Default.Three;
            this.textBox6.Text = Settings.Default.Four;
            this.textBox7.Text = Settings.Default.Five;
            this.textBox8.Text = Settings.Default.Six;
            this.textBox9.Text = Settings.Default.Seven;
            this.textBox10.Text = Settings.Default.Eight;
            this.textBox11.Text = Settings.Default.Nine;

            #region 保存输入数值代码段(存在错误)
            /*  string Data_Save = " ";
            string[] Data_Set = { " " };
            string Data_Path = Application.StartupPath + "\\config_data.ini";
            try
            {
                StreamReader streamReader = new StreamReader(Data_Path);
                Data_Save = streamReader.ReadToEnd();
                streamReader.Close();
                Data_Set = Regex.Split(Data_Save, "||");
            }
            catch { }

            //USART_Scan(serialPort1, comboBox1);
            if (Data_Set.Length > 12)
            {
                try
                {
                    if (Data_Set[0] == "1")
                    {
                        checkBox1.Checked = true;
                    }
                    else
                    {
                        checkBox1.Checked = false;
                    }
                    comboBox2.Text = Data_Set[1];
                    comboBox3.Text = Data_Set[2];
                    comboBox4.Text = Data_Set[3];
                    comboBox5.Text = Data_Set[4];
                    textBox3.Text = Data_Set[5];
                    textBox4.Text = Data_Set[6];
                    textBox5.Text = Data_Set[7];
                    textBox6.Text = Data_Set[8];
                    textBox7.Text = Data_Set[9];
                    textBox8.Text = Data_Set[10];
                    textBox9.Text = Data_Set[11];
                    textBox10.Text = Data_Set[12];
                    textBox11.Text = Data_Set[13];
                    //代码段暂时存在错误,无法使用;
                }
                catch
                {
                    checkBox1.Checked = false;
                    comboBox2.Text = "9600";
                    comboBox3.Text = "No Parity";
                    comboBox4.Text = "8";
                    comboBox5.Text = "1";
                    textBox3.Text = "";
                    textBox4.Text = "";
                    textBox5.Text = "";
                    textBox6.Text = "";
                    textBox7.Text = "";
                    textBox8.Text = "";
                    textBox9.Text = "";
                    textBox10.Text = "";
                    textBox11.Text = "";
                }
            }
            else
            {
                comboBox2.Text = "9600";
                comboBox3.Text = "No Parity";
                comboBox4.Text = "8";
                comboBox5.Text = "1";
            }          */
            #endregion

        }
        #endregion

        #region 开关串口
        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.Text == "打开串口")    //假设当前串口设备为关闭状态;
            {
                try
                {
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                    serialPort1.DataBits = Convert.ToInt32(comboBox4.Text);
                    serialPort1.Open();

                    button1.Text = "关闭串口";
                    comboBox1.Enabled = false;
                    comboBox2.Enabled = fal
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于Modbus协议串口通信代码示例: ```python import serial # Modbus协议相关常量 MODBUS_READ_COILS = 1 MODBUS_READ_DISCRETE_INPUTS = 2 MODBUS_READ_HOLDING_REGISTERS = 3 MODBUS_READ_INPUT_REGISTERS = 4 MODBUS_WRITE_SINGLE_COIL = 5 MODBUS_WRITE_SINGLE_REGISTER = 6 MODBUS_WRITE_MULTIPLE_COILS = 15 MODBUS_WRITE_MULTIPLE_REGISTERS = 16 # 串口通信相关常量 BAUDRATE = 9600 BYTESIZE = 8 PARITY = 'N' STOPBITS = 1 TIMEOUT = 1 class ModbusSerial(object): def __init__(self, port): self.ser = serial.Serial(port=port, baudrate=BAUDRATE, bytesize=BYTESIZE, parity=PARITY, stopbits=STOPBITS, timeout=TIMEOUT) def read_coils(self, address, count): request = self._build_request(MODBUS_READ_COILS, address, count) response = self._send_request(request) return self._parse_response(response) def read_discrete_inputs(self, address, count): request = self._build_request(MODBUS_READ_DISCRETE_INPUTS, address, count) response = self._send_request(request) return self._parse_response(response) def read_holding_registers(self, address, count): request = self._build_request(MODBUS_READ_HOLDING_REGISTERS, address, count) response = self._send_request(request) return self._parse_response(response) def read_input_registers(self, address, count): request = self._build_request(MODBUS_READ_INPUT_REGISTERS, address, count) response = self._send_request(request) return self._parse_response(response) def write_single_coil(self, address, value): request = self._build_request(MODBUS_WRITE_SINGLE_COIL, address, value) response = self._send_request(request) return self._parse_response(response) def write_single_register(self, address, value): request = self._build_request(MODBUS_WRITE_SINGLE_REGISTER, address, value) response = self._send_request(request) return self._parse_response(response) def write_multiple_coils(self, address, values): request = self._build_request(MODBUS_WRITE_MULTIPLE_COILS, address, values) response = self._send_request(request) return self._parse_response(response) def write_multiple_registers(self, address, values): request = self._build_request(MODBUS_WRITE_MULTIPLE_REGISTERS, address, values) response = self._send_request(request) return self._parse_response(response) def _build_request(self, function_code, address, data): # Modbus协议请求报文格式:[设备地址][功能码][数据] if function_code in (MODBUS_READ_COILS, MODBUS_READ_DISCRETE_INPUTS, MODBUS_READ_HOLDING_REGISTERS, MODBUS_READ_INPUT_REGISTERS): # 读请求数据格式:[起始地址高位][起始地址低位][数据长度高位][数据长度低位] request = bytearray([0x01, function_code, (address >> 8) & 0xff, address & 0xff, (data >> 8) & 0xff, data & 0xff]) elif function_code in (MODBUS_WRITE_SINGLE_COIL, MODBUS_WRITE_SINGLE_REGISTER): # 单个写请求数据格式:[起始地址高位][起始地址低位][数据高位][数据低位] request = bytearray([0x01, function_code, (address >> 8) & 0xff, address & 0xff, (data >> 8) & 0xff, data & 0xff]) elif function_code in (MODBUS_WRITE_MULTIPLE_COILS, MODBUS_WRITE_MULTIPLE_REGISTERS): # 多个写请求数据格式:[起始地址高位][起始地址低位][数据长度高位][数据长度低位][字节数][数据1][数据2]... num_bytes = (len(data) + 7) // 8 byte_string = ''.join(['1' if x else '0' for x in data]) byte_array = [int(byte_string[i:i+8], 2) for i in range(0, len(byte_string), 8)] request = bytearray([0x01, function_code, (address >> 8) & 0xff, address & 0xff, (len(data) >> 8) & 0xff, len(data) & 0xff, num_bytes] + byte_array) else: raise ValueError('Invalid Modbus function code: {}'.format(function_code)) return request def _send_request(self, request): self.ser.write(request) response = self.ser.read(1024) if not response: raise IOError('No response received from device') return response def _parse_response(self, response): # Modbus协议响应报文格式:[设备地址][功能码][数据长度][数据] if response[0] != 0x01: raise ValueError('Invalid Modbus response: {}'.format(response.hex())) if response[1] & 0x80: error_code = response[2] raise IOError('Modbus error code: {}'.format(error_code)) data_length = response[2] data = response[3:3+data_length] return data ``` 使用示例: ```python modbus = ModbusSerial('/dev/ttyUSB0') coils = modbus.read_coils(0x0000, 10) print(coils) ``` 在上面的示例中,我们创建了一个`ModbusSerial`对象,然后调用了`read_coils`方法读取了设备0x01的0x0000地址开始的10个线圈状态。注意,这里的`/dev/ttyUSB0`是Linux下的串口设备地址,Windows下可能会有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值