C# winform mudbus_rtu类封装

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    class my_Modbus
    {
        ToolStripStatusLabel label;
        SerialPort serialPort;
        byte[] send_bytes = new byte[500];
        UInt16[] array_reg_data = new UInt16[500];
        UInt16 length;
        UInt16 reg_index;
        UInt16 reg_read_num;
        //
        public my_Modbus(System.IO.Ports.SerialPort port, ToolStripStatusLabel _label)
        {
            serialPort = port;
            label = _label;

            length = 300;
            for (uint i = 0; i < 300; i++)
            {
                array_reg_data[i] = 0;
            }

        }
        UInt16 crc(ref byte[] T_buffer, UInt16 length)
        {
            int CRC = 0xffff;
            for (UInt16 n = 0; n < length - 2; n++)
            {
                byte i;
                CRC = CRC ^ T_buffer[n];
                for (i = 0; i < 8; i++)
                {
                    int TT;
                    TT = CRC & 1;
                    CRC = CRC >> 1;
                    CRC = CRC & 0x7fff;
                    if (TT == 1)
                    {
                        CRC = CRC ^ 0xa001;
                    }
                    CRC = CRC & 0xffff;
                }
            }
            T_buffer[length - 2] = Convert.ToByte(CRC & 0xff);
            T_buffer[length - 1] = Convert.ToByte(CRC >> 8 & 0xff);
            return Convert.ToUInt16(CRC);
        }
        //
        UInt16 crc(byte[] T_buffer, UInt16 length)
        {
            int crc = 0xffff;
            for (UInt16 n = 0; n < length - 2; n++)
            {
                byte i;
                crc = crc ^ T_buffer[n];
                for (i = 0; i < 8; i++)
                {
                    int TT;
                    TT = crc & 1;
                    crc = crc >> 1;
                    crc = crc & 0x7fff;
                    if (TT == 1)
                    {
                        crc = crc ^ 0xa001;
                    }
                    crc = crc & 0xffff;
                }
            }
            return Convert.ToUInt16(crc);
        }
        /// <summary>
        /// 0:功能码 1:寄存地址 2:寄存器数量/写入值
        /// </summary>
        /// <param name="send">0:功能码 1:寄存地址 2:寄存器数量/写入值</param>
        public void output_send(UInt16[] send)
        {
            {
                send_bytes[0] = 0xfa;
                send_bytes[1] = (byte)send[0];
                //
                send_bytes[2] = (byte)(send[1] >> 8 & 0xff);
                send_bytes[3] = (byte)(send[1] >> 0 & 0xff);
                //
                send_bytes[4] = (byte)(send[2] >> 8 & 0xff);
                send_bytes[5] = (byte)(send[2] >> 0 & 0xff);
            }
            if (send[0] == 0x03)//只读功能码
            {
                reg_index = send[1];
                reg_read_num = send[2];
            }
            //
            crc(ref send_bytes, 8);
            if (serialPort.IsOpen)
            {
                serialPort.Write(send_bytes, 0, 8);
            }

            label.Text = "发送ing";

        }

        public void output_send(byte device_address, UInt16[] send)
        {
            {
                send_bytes[0] = device_address;
                send_bytes[1] = (byte)send[0];
                //
                send_bytes[2] = (byte)(send[1] >> 8 & 0xff);
                send_bytes[3] = (byte)(send[1] >> 0 & 0xff);
                //
                send_bytes[4] = (byte)(send[2] >> 8 & 0xff);
                send_bytes[5] = (byte)(send[2] >> 0 & 0xff);
            }
            if (send[0] == 0x03)//只读功能码
            {
                reg_index = send[1];
                reg_read_num = send[2];
            }
            //
            crc(ref send_bytes, 8);
            if (serialPort.IsOpen)
            {
                serialPort.Write(send_bytes, 0, 8);
            }

            label.Text = "发送ing";
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="length"></param>
        public byte in_data(byte[] bytes, UInt16 length)
        {
            byte func_code = 0x00;
            if (length < 2)
                return func_code;
            //
            UInt16 crc0, crc1;
            byte command = bytes[1];
            crc0 = crc(bytes, length);
            crc1 = (UInt16)(bytes[length - 1] << 8 | bytes[length - 2] << 0);
            //
            if (crc0 == crc1 && (command == 0x03 || command == 0x06 || command == 0x16))
            {
                switch (command)
                {
                    case 0x03:
                        {
                            byte offset = 3;
                            byte count = bytes[2];
                            //接收数量与实际需求相符
                            if (count / 2 != reg_read_num)
                            {
                                return func_code;
                            }
                            //
                            for (byte i = 0; i < count / 2; i++)
                            {
                                array_reg_data[i + reg_index] = (UInt16)(bytes[offset + i * 2] << 8 | bytes[offset + i * 2 + 1] << 0);
                            }
                            label.Text = "接收完成";
                            func_code = 0x03;
                        }
                        break;
                    case 0x06:
                        {
                            label.Text = "发送完成";
                            func_code = 0x06;
                        }
                        break;
                    case 0x16:
                        {
                            label.Text = "发送完成";
                            func_code = 0x06;
                        }
                        break;
                }
            }

            return func_code;

        }
        /// <summary>
        /// 
        /// </summary>
        public void get_reg(ref UInt16[] _array_u16, ref UInt16 _length)
        {
            _length = 300;
            for (uint i = 0; i < 300; i++)
            {
                _array_u16[i] = array_reg_data[i];
            }
        }

        public void get_reg(ref UInt16[] _array_u16, ref UInt16 _length, ref UInt16 offset_index, ref UInt16 count)
        {
            length = 300;
            for (uint i = 0; i < 300; i++)
            {
                _array_u16[i] = array_reg_data[i];
            }

            offset_index = reg_index;
            count = reg_read_num;

        }
    }

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
* * MODBUS协议 * * * 介绍: * 此modbus上位机 协议 具有较强的通用性 * 本协议最主要的思想是 把所有向下位机发送的指令 先存放在缓冲区中(命名为管道) * 再将管道中的指令逐个发送出去。 * 管道遵守FIFO的模式。管道中所存放指令的个数 在全局变量中定义。 * 管道内主要分为两部分:1,定时循环发送指令。2,一次性发送指令。 * 定时循环发送指令:周期性间隔时间发送指令,一般针对“输入寄存器”或“输入线圈”等实时更新的变量。 * 这两部分的长度由用户所添加指令个数决定(所以自由性强)。 * 指令的最大发送次数,及管道中最大存放指令的个数在常量定义中 可进行设定。 * * 使用说明: * 1,首先对所定义的寄存器或线圈进行分组定义,并定义首地址。 * 2,在MBDataTable数组中添加寄存器或线圈所对应的地址。 注意 寄存器:ob = new UInt16()。线圈:ob = new byte()。 * 3,对所定义的地址 用属性进行定义 以方便在外进行访问及了解所对应地址的含义。 * 4,GetAddressValueLength函数中 对使用说明的"第一步"分组 的元素个数进行指定。 * 5,在主程序中调用MBConfig进行协议初始化(初始化内容参考函数)。 * 6,在串口中断函数中调用MBDataReceive()。 * 7,定时器调用MBRefresh()。(10ms以下) * 指令发送间隔时间等于实时器乘以10。 例:定时器5ms调用一次 指令发送间隔为50ms。 * 8,在主程序初始化中添加固定实时发送的指令操作 用MBAddRepeatCmd函数。 * 9,在主程序运行过程中 根据需要添加 单个的指令操作(非固定重复发送的指令)用MBAddCmd函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值