仿艾莫迅MODBUS调试工具写一个上位机

公司采购了一个夹具,项目负责人想要试探这个夹具的性能,于是想要我这边写一个烤机的程序,小编结合官网资料
https://wiki.amsamotion.com/?title=196&doc=222
在这里插入图片描述
查看其pdf说明文档和调试工具并按照其工具写一个烤机上位机
在这里插入图片描述
根据项目负责人的要求开发了一个小程序
在这里插入图片描述
在这里插入图片描述

using JY_MODBUS_IO8R_IS_Soft.BLL;
using JY_MODBUS_IO8R_IS_Soft.Business;
using JY_MODBUS_IO8R_IS_Soft.JY_MODBUS_IO8R_Controller;
using JY_MODBUS_IO8R_IS_Soft.Model;
using JY_MODBUS_IO8R_IS_Soft.userControl;
using LogManager;
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 JY_MODBUS_IO8R_IS_Soft
{
    public partial class frmMain : Form
    {
        ModbusController controller = new ModbusController();
        static readonly Modbus_helper Modbus_helper = new Modbus_helper(DeviceBll.Single.SerialPort);
        public frmMain()
        {
            InitializeComponent();
            //获取电脑上可用的串口号
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            if (ports.Length != 0)
            {
                cbb_Com.Items.AddRange(ports);
            }
            Modbus_helper.DelResult = DelWriteLog;
            Modbus_helper.DelTime = DelWriteLog;
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                LogNetManagment.LogNet.WriteDebug("连接串口");
                string errMsg = string.Empty;
                if (
                    !Modbus_helper.Connect(cbb_Com.Text.Trim(), Convert.ToInt32(cbb_ComRate.Text.Trim()), Convert.ToInt32(txtWriteReadTime.Text.Trim()), ref errMsg))
                {
                    MessageBox.Show(errMsg);
                }
                else
                {
                    UpdateConnectStatus(true);
                }
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException("连接通信", ex);
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 改变连接状态
        /// </summary>
        /// <param name="status"></param>
        public void UpdateConnectStatus(bool status)
        {
            if (status)
            {
                btnConnect.Enabled = false;
                btnBreak.Enabled = true;
            }
            else
            {
                btnConnect.Enabled = true;
                btnBreak.Enabled = false;
            }
        }

        private void btnBreak_Click(object sender, EventArgs e)
        {
            try
            {
                LogNetManagment.LogNet.WriteDebug("断开串口");
                string errMsg = string.Empty;
                if (!Modbus_helper.Close(ref errMsg))
                {
                    MessageBox.Show(errMsg);
                }
                else
                {
                    UpdateConnectStatus(false);
                }
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException("断开通讯", ex);
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnTest_Click(object sender, EventArgs e)
        {
            try
            {
                LogNetManagment.LogNet.WriteDebug("开始循环测试,循环次数为"+txtTestTime.ToString());
                this.btnTest.Enabled = false;
                int channel = cmbChannel.SelectedIndex;
                Task.Factory.StartNew(() =>
                {
                    string errMsg = string.Empty;
                    Modbus_helper.IsTestStatus = true;
                    if (!Modbus_helper.ContinueTest(channel, Convert.ToInt32(txtTestTime.Text),ref errMsg))
                    {
                        this.Invoke(new Action(() =>
                        {
                            MessageBox.Show(errMsg);
                        }));
                    }
                }).ContinueWith((task) => {
                    this.Invoke(new Action(() => {
                        this.btnTest.Enabled = true;
                    }));
                });
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException("开始循环测试", ex);
                MessageBox.Show(ex.ToString());
            }
        }

        private void DelWriteLog(int runtime)
        {
            this.BeginInvoke(new Action(() =>
            {
                DateTime date = DateTime.Now;
                txtLog.AppendText($"{date.ToString("yyyy-MM-dd HH:mm:ss.fff")} 当前正在执行{runtime}次"+ Environment.NewLine);
            }));
        }

        private void DelWriteLog(ResultModel result)
        {
            this.BeginInvoke(new Action(() =>
            {
                DateTime date = DateTime.Now;
                if (result.TestResult == (uint)Common.CommonEnum.TestResultType.Success)
                {
                    txtLog.AppendText(date.ToString("yyyy-MM-dd HH:mm:ss.fff") + " " + result.LabelTip + Environment.NewLine);
                }
                else if (result.TestResult == (uint)Common.CommonEnum.TestResultType.Fail)
                {
                    txtLog.AppendText(date.ToString("yyyy-MM-dd HH:mm:ss.fff") + " " + result.LabelTip + Environment.NewLine);
                }
                else
                {
                    txtLog.AppendText(date.ToString("yyyy-MM-dd HH:mm:ss.fff") + " " + result.LabelTip + Environment.NewLine);
                }
            }));
        }

        private void switchButtons1_Btn_Click(object sender, EventArgs e)
        {
            Button userCtl = sender as Button;
            string errMsg = string.Empty;
            if (switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor == SystemColors.Control)
            {
                if (!Modbus_helper.TestByChannel(Convert.ToInt32(userCtl.Tag), Common.CommonEnum.OrderType.Control, ref errMsg))
                {
                    switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor = SystemColors.Control;
                }
                else
                {
                    switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor = Color.Red;
                }
            }
            else if (switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor == Color.Red)
            {
                if (!Modbus_helper.TestByChannel(Convert.ToInt32(userCtl.Tag), Common.CommonEnum.OrderType.Clearance, ref errMsg))
                {
                    switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor = Color.Red;
                }
                else
                {
                    switchButtons1.Controls.Find($"btn{userCtl.Tag}", true)[0].BackColor = SystemColors.Control;
                }
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            LogNetManagment.LogNet.WriteDebug("点击停止");
            Modbus_helper.IsTestStatus = false;
            DateTime date = DateTime.Now;
            txtLog.AppendText(date.ToString("yyyy-MM-dd HH:mm:ss.fff") + " 点击停止"  + Environment.NewLine);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JY_MODBUS_IO8R_IS_Soft.Common
{
    public class CommonEnum
    {
        /// <summary>
        /// 指令类型
        /// </summary>
        public enum OrderType : uint
        {
            /// <summary>
            /// 控制
            /// </summary>
            Control = 0,
            /// <summary>
            /// 解控
            /// </summary>
            Clearance = 1
        }

        /// <summary>
        /// 测试结束各种原因
        /// </summary>
        public enum TestResultType : uint
        {
            /// <summary>
            /// 正常成功结束
            /// </summary>
            Success = 0,
            /// <summary>
            /// 异常结束
            /// </summary>
            Fail = 1,
            /// <summary>
            /// 倒计时结束
            /// </summary>
            FixedSuccess = 2
        }
    }
}

using Common;
using JY_MODBUS_IO8R_IS_Soft.Config;
using LogManager;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JY_MODBUS_IO8R_IS_Soft.Business
{
    public class DeviceBll
    {
        private static DeviceBll bDeviceSingle = null;

        public static DeviceBll Single
        {
            get
            {
                if (bDeviceSingle == null) bDeviceSingle = new DeviceBll();
                return bDeviceSingle;
            }
        }
        //不允许外部New操作
        private DeviceBll() { }
        /// <summary>
        /// 硬件配置文件路径
        /// </summary>
        public string ChoosesetPath = AppDomain.CurrentDomain.BaseDirectory + "\\Chooseset.ini";
        /// <summary>
        /// 保存数据的路径
        /// </summary>
        public string SaveDataPath = string.Empty;
        /// <summary>
        /// 是否保存数据
        /// </summary>
        public bool IsSaveData = true;
        /// <summary>
        /// 保存数据最大的行数 到达之后重新创建文件
        /// </summary>
        public int ExportDataLines = 0;
        /// <summary>
        /// 通道数
        /// </summary>
        public int ChannelNum = 12;
        /// <summary>
        /// 设备通讯连接状态 true已连接 false未连接
        /// </summary>
        public bool IsLink = false;
        /// <summary>
        /// 锁对象
        /// </summary>
        public readonly object LockFileObj = new object();
        /// <summary>
        /// 配置文件
        /// </summary>
        public mainSet MainConfigSet = new mainSet();
        ///// <summary>
        ///// 设备接口对象
        ///// </summary>
        //public I_MUX _ifun;

        public delegate void DelUpdateConfig();
        /// <summary>
        /// 用户切换响应事件
        /// </summary>
        public static event DelUpdateConfig EventUpdateConfig;
        /// <summary>
        /// 串口对象
        /// </summary>
        public SerialPort SerialPort;
        /// <summary>
        /// 用户切换
        /// </summary>
        public static void UpdateConfig()
        {
            if (EventUpdateConfig != null)
            {
                EventUpdateConfig();
            }
        }

        public delegate void DelUpdateBtnStartAll();

        public static event DelUpdateBtnStartAll EventUpdateBtnStartAll;

        public static void UpdateBtnStartAll()
        {
            if (EventUpdateBtnStartAll != null)
            {
                EventUpdateBtnStartAll();
            }
        }

        /// <summary>
        ///系统硬件初始化
        /// </summary>
        public void Init()
        {
            try
            {
                DeviceInit();
                int delayTime = Convert.ToInt32(IniFileHelper.IniReadValue(DeviceBll.Single.ChoosesetPath, "DelayTime", "DelayTime_ms", ""));
                ChannelNum = Convert.ToInt32(IniFileHelper.IniReadValue(DeviceBll.Single.ChoosesetPath, "Channel", "ChannelNum", ""));
                LogManager.LogNetManagment.LogNet.WriteInfo("获取参数保护文件参数");
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException("Init", ex);
            }
        }

        /// <summary>
        /// 设备初始化加载
        /// </summary>
        public void DeviceInit()
        {
            SerialPort = new SerialPort();//串口对象
        }
    }
}

using JY_MODBUS_IO8R_IS_Soft.Model;
using LogManager;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JY_MODBUS_IO8R_IS_Soft.BLL
{
    public class Modbus_helper
    {
        /// <summary>
        /// 串口对象
        /// </summary>
        public SerialPort SerialPort { get; set; }
        /// <summary>
        /// 发送结果数据
        /// </summary>
        public Action<ResultModel> DelResult { get; set; }
        /// <summary>
        /// 发送执行的次数
        /// </summary>
        public Action<int> DelTime { get; set; }
        /// <summary>
        /// 获取结果类
        /// </summary>
        public ResultModel Result { get; set; }
        /// <summary>
        /// 测试状态
        /// </summary>
        public bool IsTestStatus { get; set; }
        public int WriteReadTime { get; set; }
        /// <summary>
        /// 锁对象
        /// </summary>
        private readonly object _lockWr = new object();
        public Modbus_helper(SerialPort serialPort)
        {
            this.SerialPort = serialPort;
            this.Result = new ResultModel();
            IsTestStatus = false;
        }

        /// <summary>
        /// 连接串口
        /// </summary>
        /// <param name="comName">串口号</param>
        /// <param name="comRate">串口速率</param>
        /// <param name="errMsg">错误信息</param>
        /// <returns></returns>
        public bool Connect(string comName, int comRate, int time, ref string errMsg)
        {
            try
            {
                SerialPort.BaudRate = comRate;
                SerialPort.StopBits = StopBits.One;
                SerialPort.PortName = comName;
                SerialPort.NewLine = "\r\n";
                SerialPort.ReadTimeout = 10000;
                SerialPort.WriteTimeout = 1000;
                SerialPort.Open();
                if (SerialPort.IsOpen.Equals(false))
                {
                    //串口连接失败!
                    errMsg = "连接串口失败";
                    return false;
                }
                else
                {
                    WriteReadTime = time;
                    return true;
                }
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException(nameof(Modbus_helper) + "_" + nameof(Connect), ex);
                errMsg = ex.ToString();
                return false;
            }
        }

        public bool Close(ref string errMsg)
        {
            try
            {
                if (SerialPort.IsOpen)
                {
                    SerialPort.Close();
                }
                if (!SerialPort.IsOpen)
                {
                    return true;
                }
                return true;
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException(nameof(Modbus_helper) + "_" + nameof(Close), ex);
                errMsg = ex.ToString();
                return false;
            }
        }

        public bool ContinueTest(int channel, int time, ref string errMsg)
        {
            try
            {
                for (int i=0;i<time;i++)
                {
                    if (!IsTestStatus)
                    {
                        return true;
                    }
                    int testtime = i + 1;
                    DelTime(testtime);
                    byte[] controlBytes = GetControlBytes(channel, Common.CommonEnum.OrderType.Control);
                    //控制
                    if (!WriteRead(controlBytes, ref errMsg))
                    {
                        Result.TestResult = 1;
                        Result.LabelTip = "当前正在执行" + testtime + "次吸合失败";
                        DelResult(Result);
                        return false;
                    }
                    byte[] clearanceBytes = GetControlBytes(channel, Common.CommonEnum.OrderType.Clearance);
                    //解控
                    if (!WriteRead(clearanceBytes, ref errMsg))
                    {
                        Result.TestResult = 1;
                        Result.LabelTip = "当前正在执行" + testtime + "次断开失败";
                        DelResult(Result);
                        return false;
                    }
                    Result.TestResult = 0;
                    Result.LabelTip = "执行成功";
                    DelResult(Result);
                }
                Result.LabelTip = "执行完毕";
                Result.TestResult = 2;
                DelResult(Result);
                return true;
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException(nameof(Modbus_helper) + "_" + nameof(ContinueTest), ex);
                errMsg = ex.ToString();
                return false;
            }
        }

        public bool TestByChannel(int channel, Common.CommonEnum.OrderType orderType, ref string errMsg)
        {
            try
            {
                if (orderType == Common.CommonEnum.OrderType.Control)
                {
                    byte[] controlBytes = GetControlBytes(channel, Common.CommonEnum.OrderType.Control);
                    //控制
                    if (!WriteRead(controlBytes, ref errMsg))
                    {
                        Result.TestResult = 1;
                        Result.LabelTip = $"当前正在执行channel{channel}吸合失败";
                        DelResult(Result);
                        return false;
                    }
                    else
                    {
                        Result.TestResult = 0;
                        Result.LabelTip = $"当前正在执行channel{channel}吸合成功";
                        DelResult(Result);
                        return true;
                    }
                }
                else if (orderType == Common.CommonEnum.OrderType.Clearance)
                {
                    byte[] clearanceBytes = GetControlBytes(channel, Common.CommonEnum.OrderType.Clearance);
                    //解控
                    if (!WriteRead(clearanceBytes, ref errMsg))
                    {
                        Result.TestResult = 1;
                        Result.LabelTip = $"当前正在执行channel{channel}断开失败";
                        DelResult(Result);
                        return false;
                    }
                    else
                    {
                        Result.TestResult = 0;
                        Result.LabelTip = $"当前正在执行channel{channel}断开成功";
                        DelResult(Result);
                        return true;
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException(nameof(Modbus_helper) + "_" + nameof(TestByChannel), ex);
                errMsg = ex.ToString();
                return false;
            }
        }

        public bool WriteRead(byte[] strWrite, ref string errMsg)
        {
            try
            {
                SerialPort.DiscardInBuffer();//丢弃缓冲区数据
                SerialPort.DiscardOutBuffer();//丢弃缓冲区数据
                SerialPort.DiscardInBuffer();//丢弃缓冲区数据
                SerialPort.DiscardOutBuffer();//丢弃缓冲区数据
                SerialPort.Write(strWrite, 0, 8);
                Thread.Sleep(WriteReadTime);
                SerialPort.ReadExisting();
                return true;
            }
            catch (Exception ex)
            {
                LogNetManagment.LogNet.WriteException(nameof(Modbus_helper) + "_" + nameof(WriteRead), ex);
                errMsg = ex.ToString();
                return false;
            }
        }

        public byte[] GetControlBytes(int channel, Common.CommonEnum.OrderType OrderType)
        {
            byte[] bytes = new byte[8];
            //01 05 00 00 FF 00 8C 3A   控制
            if (OrderType == Common.CommonEnum.OrderType.Control)
            {
                //bytes[0] = 01;
                //bytes[1] = 05;
                //bytes[2] = 00;
                //bytes[3] = 00;
                //bytes[4] = 0xFF;
                //bytes[5] = 00;
                //bytes[6] = 0x8C;
                //bytes[7] = 0x3A;
                //return bytes;
                byte address = Convert.ToByte(channel);
                byte[] cmd = GenerateCommand(0x01, address, true);
                return cmd;
            }
            else if (OrderType == Common.CommonEnum.OrderType.Clearance)
            {
                //01 05 00 00 00 00 CD CA
                //bytes[0] = 01;
                //bytes[1] = 05;
                //bytes[2] = 00;
                //bytes[3] = 00;
                //bytes[4] = 00;
                //bytes[5] = 00;
                //bytes[6] = 0xCD;
                //bytes[7] = 0xCA;
                //return bytes;
                byte address = Convert.ToByte(channel);
                byte[] cmd = GenerateOffCommand(0x01, address);
                return cmd;
            }
            return bytes;
        }

        // CRC16校验计算核心方法
        public static ushort CalculateCrc(byte[] data)
        {
            ushort crc = 0xFFFF;
            foreach (byte b in data)
            {
                crc ^= b;
                for (int i = 0; i < 8; i++)
                {
                    bool lsb = (crc & 1) == 1;
                    crc >>= 1;
                    if (lsb) crc ^= 0xA001;
                }
            }
            return crc;
        }

        // 生成完整Modbus指令(包含CRC)
        public static byte[] GenerateCommand(byte deviceId, ushort address, bool state)
        {
            byte[] cmd = new byte[6];
            cmd[0] = deviceId;
            cmd[1] = 0x05; // 功能码
            cmd[2] = (byte)(address >> 8); // 地址高字节
            cmd[3] = (byte)(address & 0xFF); // 地址低字节
            cmd[4] = state ? (byte)0xFF : (byte)0x00; // 状态值
            cmd[5] = 0x00; // 固定填充

            ushort crc = CalculateCrc(cmd);
            byte[] fullCmd = new byte[8];
            Array.Copy(cmd, fullCmd, 6);
            fullCmd[6] = (byte)(crc & 0xFF); // CRC低字节在前
            fullCmd[7] = (byte)(crc >> 8);

            return fullCmd;
        }

        // 生成断开继电器指令
        public static byte[] GenerateOffCommand(byte deviceId, ushort address)
        {
            byte[] cmd = new byte[6];
            cmd[0] = deviceId;
            cmd[1] = 0x05; // 功能码
            cmd[2] = (byte)(address >> 8); // 地址高字节
            cmd[3] = (byte)(address & 0xFF); // 地址低字节
            cmd[4] = 0x00; // 断开继电器
            cmd[5] = 0x00; // 固定填充

            ushort crc = CalculateCrc(cmd);
            byte[] fullCmd = new byte[8];
            Array.Copy(cmd, fullCmd, 6);
            fullCmd[6] = (byte)(crc & 0xFF); // CRC 低字节在前
            fullCmd[7] = (byte)(crc >> 8);

            return fullCmd;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JY_MODBUS_IO8R_IS_Soft.Config
{
    // 通过此类可以处理设置类的特定事件: 
    //  在更改某个设置的值之前将引发 SettingChanging 事件。
    //  在更改某个设置的值之后将引发 PropertyChanged 事件。
    //  在加载设置值之后将引发 SettingsLoaded 事件。
    //  在保存设置值之前将引发 SettingsSaving 事件。
    public sealed partial class mainSet
    {

        public mainSet()
        {
            // // 若要为保存和更改设置添加事件处理程序,请取消注释下列行: 
            //
            // this.SettingChanging += this.SettingChangingEventHandler;
            //
            // this.SettingsSaving += this.SettingsSavingEventHandler;
            //
        }

        private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e)
        {
            // 在此处添加用于处理 SettingChangingEvent 事件的代码。
        }

        private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // 在此处添加用于处理 SettingsSaving 事件的代码。
        }
    }
}

//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.42000
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

namespace JY_MODBUS_IO8R_IS_Soft.Config {
    
    
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
    public sealed partial class mainSet : global::System.Configuration.ApplicationSettingsBase {
        
        private static mainSet defaultInstance = ((mainSet)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new mainSet())));
        
        public static mainSet Default {
            get {
                return defaultInstance;
            }
        }
        
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("COM1")]
        public string ComName {
            get {
                return ((string)(this["ComName"]));
            }
            set {
                this["ComName"] = value;
            }
        }
        
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("115200")]
        public string ComRate {
            get {
                return ((string)(this["ComRate"]));
            }
            set {
                this["ComRate"] = value;
            }
        }
        
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("Q.0")]
        public string Channel {
            get {
                return ((string)(this["Channel"]));
            }
            set {
                this["Channel"] = value;
            }
        }
        
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("10")]
        public int TestTime {
            get {
                return ((int)(this["TestTime"]));
            }
            set {
                this["TestTime"] = value;
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JY_MODBUS_IO8R_IS_Soft.userControl
{
    public partial class SwitchButtons : UserControl
    {
        public SwitchButtons()
        {
            InitializeComponent();
            InitializeTableLayout();
        }

        private void InitializeTableLayout()
        {
            // 设置TableLayoutPanel的行和列
            tableLayoutPanel1.RowCount = 2; // 例如,3行
            tableLayoutPanel1.ColumnCount = 9; // 1列,可以根据需要调整
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F)); // 标题行占20%高度
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F)); // 按钮行占60%高度
        }

        private void SwitchButtons_Load(object sender, EventArgs e)
        {
            Label labelcol = new Label();
            labelcol.Text = $"Do0"; // 按钮的文本从"按钮2"开始计数
            labelcol.AutoSize = false;
            labelcol.TextAlign = ContentAlignment.MiddleCenter;
            labelcol.Dock = DockStyle.Fill; // 使按钮填充整个单元格
            tableLayoutPanel1.Controls.Add(labelcol, 0, 1); // 添加到相应的行,第一列
            for (int i = 1; i < 9; i++) // 假设你想添加4个按钮,从第二行开始(索引为1)
            {
                this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 60F));
                Label label = new Label();
                label.Text = $"Q.{i-1}"; // 按钮的文本从"按钮2"开始计数
                label.AutoSize = false;
                label.TextAlign = ContentAlignment.MiddleCenter;
                label.Dock = DockStyle.Fill; // 使按钮填充整个单元格
                Button button = new Button();
                button.Dock = DockStyle.Fill;
                button.Tag = (i - 1).ToString();
                button.Name = $"btn{(i-1)}";
                button.Click += new EventHandler(this.btn_click);
                tableLayoutPanel1.Controls.Add(label, i, 0); // 添加到相应的行,第一列
                tableLayoutPanel1.Controls.Add(button, i, 1); // 添加到相应的行,第一列
            }
        }

        //public void btn_click(Object sender, System.EventArgs e)
        //{
        //    string id = ((Button)sender).Tag.ToString();
        //    MessageBox.Show(id);
        //}
        /// <summary>
        /// 点击事件
        /// </summary>
        [Browsable(true), Category("自定义事件"), Description("点击事件")]
        public event EventHandler Btn_Click;

        private void btn_click(object sender, EventArgs e)
        {
            if (Btn_Click != null)
            {
                Btn_Click(sender, e);
            }
        }
    }
}

using JY_MODBUS_IO8R_IS_Soft.Business;
using JY_MODBUS_IO8R_IS_Soft.frms;
using LogManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JY_MODBUS_IO8R_IS_Soft
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            #region 日志构建
            //初始化日志
            string logPath = Application.StartupPath + "\\Log"; //日志路径
            LogManager.GenerateMode LogSaveMode = LogManager.GenerateMode.ByEveryDay; //日志存储方式 按天
            LogNetManagment.LogNet = new LogManager.LogNetDateTime(logPath, LogSaveMode);
            LogNetManagment.LogNet.WriteDebug("启动程序");
            #endregion
            DeviceBll.Single.Init();
            Application.Run(new frmMain());
        }
    }
}

### 关于艾莫触摸屏编程软件的信息 #### 艾莫触摸屏编程软件概述 艾莫作为一家专注于工业自动化产品的公司,其触摸屏产品通常搭配特定的编程软件来完成界面设计和逻辑控制。根据现有资料,虽然未明确提及具体的艾莫触摸屏编程软件名称,但从引用内容可以看出,这类触摸屏可能兼容第三方组态软件,例如MCGS[^2]。 #### 常见的触摸屏编程软件及其特点 1. **MCGS通用版** MCGS是一款广泛应用于工业领域的触摸屏开发工具,支持多种品牌PLC的连接,包括艾莫PLC。它提供了丰富的组件库和灵活的画面编辑功能,适合用于创建复杂的HMI(人机交互)界面[^2]。 2. **飞控触摸屏专用软件** 如果使用的触摸屏是由飞控生产,则需下载对应的飞控触摸屏编程软件。此类软件一般由厂家提供免费版本,并附带详细的使用手册和技术支持文档[^1]。 3. **其他可能性** 对于某些仿制或定制化的产品,可能会推荐使用类似于三菱GotCreator或者西门子WinCC Flexible这样的主流厂商提供的解决方案。不过具体取决于实际购买时的技术规格书说明。 #### 如何获取艾莫触摸屏编程软件? - **官方网站查询** 用户可以直接访问艾莫公司的官网,在技术支持栏目下查找最新发布的驱动程序以及配套的应用软件包。如果暂时无法定位确切位置,建议尝试联系客服代表寻求帮助。 - **第三方资源平台** 若官方渠道难以满足需求,还可以考虑从一些知名的工控行业论坛、技术博客或者授权经销商处获得合法途径下的安装文件。务必注意辨别真伪以防感染恶意代码。 #### 使用教程参考资料 针对初学者而言,除了阅读随附的操作指南外,网络上有不少关于如何快速入门MCGS或其他相似系统的教学视频可供参考学习。比如B站上就有专门讲解PID算法实现过程的教学片断可以借鉴思路[^4]。 ```python import requests def download_software(url, destination_folder): """ A simple function to demonstrate downloading software. Parameters: url (str): The URL of the file you want to download. destination_folder (str): Path where the downloaded file will be saved. Returns: str: Message indicating success or failure. """ try: response = requests.get(url) if response.status_code == 200: with open(f"{destination_folder}/software.exe", 'wb') as f: f.write(response.content) return "Download successful." else: return "Failed to retrieve data from server." except Exception as e: return f"An error occurred: {e}" # Example usage download_url = "http://example.com/software" save_path = "/path/to/save/directory" result_message = download_software(download_url, save_path) print(result_message) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值