C#通过MXComponent与三菱PLC通信

1,MXComponent安装包与手册。

https://download.csdn.net/download/lingxiao16888/89767137

2,使用管理员权限打开MXComponent,并进行配置。

3,引用相应的类库。

//通信类库
ActUtlTypeLib.dll或者ActProgType.dll
注明:ActUtlTypeLib.dll与ActProgType.dll的区别是:ActUtlTypeLib.dll完全依赖CommunicationSetupUtility软件的配置,只需要通过CommunicationSetupUtility配置中提供的逻辑站号即可实现与PLC的连接。ActProgType.dll需要自行在C#代码中设置通信的方式,目标,物理连接方式等才可实现与PLC的连接。

//错误代码解析库
ActSupportMsgLib.dll
解析返回的代码(代码类型为int)。正常返回0,异常返回非0数字,通过该类库提供的函数解析出该代码的具体意思。

//类型或者控件所在的位置
以上类库均位于MXComponent安装目录的\Act\Control\下,例如:D:\Program Files\MXComponent\Act\Control

4,应用

1,引用相关命令控件,创建相关类。

  ActUtlTypeLib.ActUtlTypeClass PLC = new ActUtlTypeLib.ActUtlTypeClass();
        ActSupportMsgLib.ActMLSupportMsgClass support = new ActSupportMsgLib.ActMLSupportMsgClass();

2,读取PLC CPU信息。

  //获取当前PLC型号信息
                    string cpuName;
                    int cpuCode;
                    result = PLC.GetCpuType(out cpuName, out cpuCode);
                    if (result == 0)
                    {
                        lblCPUModel.Text = cpuName;
                        lblCPUCode.Text = "0x" + cpuCode.ToString("X8");
                        AddLog(0, "已成功获取PLC CPU信息");
                    }
                    else
                    {
                        AddLog(1, "获取PLC CPU信息失败,原因:" + GetErrorMessage(result));
                    }

效果

3,读写PLC当前时钟。

注明:模拟状态不支持时钟写入。

 private void btnReadPLCTime_Click(object sender, EventArgs e)
        {
            short year, month, day, dayOfWeek, hour, minute, second;
            int result = PLC.GetClockData(out year, out month, out day, out dayOfWeek, out hour, out minute, out second);
            if (result == 0)
            {
                lblPLCDateTime.Text = $"PLC时钟:{year}/{month}/{day} {hour}:{minute}:{second} 星期{dayOfWeek}";
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "读取PLC时钟错误,原因:" + msg);
            }

        }
 private void btnWritePLCTime_Click(object sender, EventArgs e)
        {
            //向PLC写入时钟
            DateTime dt = dateTimePicker1.Value;
            int result = PLC.SetClockData((short)dt.Year, (short)dt.Month, (short)dt.Day, (short)dt.DayOfWeek, (short)dt.Hour, (short)dt.Minute, (short)dt.Second);
            if (result == 0)
            {
                AddLog(0, "PLC时钟设置成功!");
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "PLC时钟设置失败,原因:" + msg);
            }
        }

效果:

4,远程控制PLC状态(Run,Stop,Pause)

  private void plcSwitch_Click(object sender, EventArgs e)
        {
            //参数IOperator:0 远程Run;1 远程 Stop;2 远程Pause
            int result = PLC.SetCpuStatus(plcSwitch.CurrentPosition);
            if (result != 0)
            {
                string msg;
                msg = GetErrorMessage(result);
                AddLog(2, "PLC状态切换失败,原因:" + msg);
            }
            else
            {
                switch (plcSwitch.CurrentPosition)
                {
                    case 0:
                        //自动
                        led_PLC.LEDBackColor = Color.Green;
                        break;
                    case 1:
                        //Stop
                        led_PLC.LEDBackColor = Color.Red;
                        break;
                    default:
                        //pause
                        led_PLC.LEDBackColor = Color.Orange;
                        break;
                }
            }
        }

效果:

 5,连续的块数据读取。

   private void btnReadDeviceBlock_Click(object sender, EventArgs e)
        {
            //以4个byte为单位的int块读取
            if (Verification(txt_ReadBlockAddress, txt_ReadBlockSize))
            {
                int num = int.Parse(txt_ReadBlockSize.Text.Trim());
                short[] arr = new short[num];
                int result = PLC.ReadDeviceBlock2(txt_ReadBlockAddress.Text.Trim(), num, out arr[0]);
                if (result == 0)
                {
                    string msg = $"{txt_ReadBlockAddress.Text}连续{num}个地址值为:{string.Join(",", arr)}";
                    AddLog(0, msg);
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, txt_ReadBlockAddress.Text + "块读取失败,原因:" + msg);
                }
            }

        }

        private void btnWriteDeviceBlock_Click(object sender, EventArgs e)
        {
            if (Verification(txt_WriteBlockAddress, txt_WriteBlockValue))
            {


                int num;
                if (!int.TryParse(txt_WriteBlockSize.Text.Trim(), out num))
                {
                    MessageBox.Show("请输入正确的数量!");
                    return;
                }
                int[] arr = txt_WriteBlockValue.Lines.Select(item => Convert.ToInt32(item)).ToArray();
                int result = PLC.WriteDeviceBlock(txt_ReadBlockAddress.Text.Trim(), num, ref arr[0]);
                if (result == 0)
                {
                    string msg = $"从{txt_ReadBlockAddress.Text}开始连续写入{num}个地址值为:{string.Join(",", arr)}";
                    AddLog(0, msg);
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, txt_ReadBlockAddress.Text + "块写入失败,原因:" + msg);
                }
            }
        }
注意事项:使用块连续读写时是以1个word为基准,例如读取数量为1,起始地址为M0的软元件时,返回的是M0-M15的集合;读取数量为1,起始地址为D0的寄存器时返回的时D0。这有别与后面出现的GetDevice()方法。

6,非连续的块数据读写。

 private void btnReadDeviceRandom_Click(object sender, EventArgs e)
        {
            if (Verification(txt_ReadRandomAddress, txt_ReadRandomSize))
            {
                int num;
                if (!int.TryParse(txt_ReadRandomSize.Text.Trim(), out num))
                {
                    MessageBox.Show("只能为正整数");
                    return;

                }
                //对地址进行离散读取,例如一次读取D0,D2,D3,D6等非连续地址
                string[] arr = txt_ReadRandomAddress.Lines;
                short[] values = new short[arr.Length];
                string addres = string.Join("\n", arr);//地址间使用\n进行分割
                //注意这里特意使用ReadDeviceRandom2,而不是ReadDeviceRandom,
                //就是为表示两者除了读取的值,除类型(一个是Int 一个是Short)不同外其他都一样
                int result = PLC.ReadDeviceRandom2(addres, num, out values[0]);
                if (result == 0)
                {
                    //读取成功
                    string[] strs = arr.Where((item, index) => index < num).Select((item, index) => $"{item}={values[index]}").ToArray();
                    AddLog(0, "读取成功:" + string.Join(",", strs));
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "离散读取地址值失败,失败原因:" + msg);
                }
            }
        }

        private void btnWriteDeviceRandom_Click(object sender, EventArgs e)
        {
            if (Verification(txt_WriteRandomAddress, txt_WriteRandomValue))
            {
                string[] address = txt_WriteRandomAddress.Lines;
                int[] values = txt_WriteRandomValue.Lines.Select(item => Convert.ToInt32(item)).ToArray();
                //各地址之间使用\n进行分割
                string addStr = string.Join("\n", address);

                int result = PLC.WriteDeviceRandom(addStr, values.Length, ref values[0]);
                if (result == 0)
                {
                    AddLog(0, "成功写入值。");
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "离散写入失败,失败原因:" + msg);
                }
            }
        }

7,对单个软元件或者寄存器进行读写。

  private void btnGetDevice_Click(object sender, EventArgs e)
        {
            //获取单个寄存器的值
            if (!Regex.IsMatch(txt_ReadDeviceAddress.Text.Trim(), @"^[a-zA-Z]+\d+(\.\d+)?$"))
            {
                MessageBox.Show("地址格式错误!");
                txt_ReadDeviceAddress.Focus();
                return;
            }
            short value;
            int result = PLC.GetDevice2(txt_ReadDeviceAddress.Text.Trim(), out value);
            if (result == 0)
            {
                string msg = $"读取成功,{value}";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "读取失败,原因:" + msg);
            }

        }

        private void btnSetDevice_Click(object sender, EventArgs e)
        {
            //对单个寄存器进行写入
            if (Verification(txt_WriteDeviceAddress, txt_WriteDeviceValue))
            {
                int value = int.Parse(txt_WriteDeviceValue.Text.Trim());
                int result = PLC.SetDevice(txt_WriteDeviceAddress.Text, value);
                if (result == 0)
                {
                    AddLog(0, "成功写入!");
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "写入失败,原因:" + msg);
                }
            }
        }

8,对缓冲区进行读写。

  private void btnReadBuffer_Click(object sender, EventArgs e)
        {
            //缓冲区地址读取
            int ioNum, num, address;
            if (!int.TryParse(txt_ReadBufferStartIO.Text.Trim(), out ioNum))
            {
                MessageBox.Show("起始地址格式错误");
                return;
            }
            if (!int.TryParse(txt_ReadBufferSize.Text.Trim(), out num))
            {
                MessageBox.Show("数量格式错误");
                return;
            }
            if (!int.TryParse(txt_ReadBufferStartAddress.Text.Trim(), out address))
            {
                MessageBox.Show("地址格式错误,地址只能为数字");
                return;
            }
            short[] values = new short[num];
            int result = PLC.ReadBuffer(ioNum, address, num, out values[0]);
            if (result == 0)
            {
                string msg = $"缓冲区读取成功:{string.Join(",", values)}";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "缓冲区读取失败,原因:" + msg);
            }

        }

        private void btnWriteBuffer_Click(object sender, EventArgs e)
        {
            //缓冲区地址写入
            int ioNum, address;
            if (!int.TryParse(txt_WriteBufferIO.Text.Trim(), out ioNum))
            {
                MessageBox.Show("起始地址格式错误");
                return;
            }

            if (!int.TryParse(txt_WriteBufferAddress.Text.Trim(), out address))
            {
                MessageBox.Show("地址格式错误,地址只能为数字");
                return;
            }
            if (string.IsNullOrEmpty(txt_WriteBufferValue.Text.Trim()))
            {
                MessageBox.Show("请勿写入空值");
                return;
            }
            foreach (var item in txt_WriteBufferValue.Lines)
            {
                if (!Regex.IsMatch(item, @"^\d+(\r|\n|\r\n)?$"))
                {
                    MessageBox.Show("写入的数据格式错误,写入的数据只能是short.");
                    return;
                }
            }
            short[] values = txt_WriteBufferValue.Lines.Select(item => Convert.ToInt16(item)).ToArray();
            int result = PLC.WriteBuffer(ioNum, address, values.Length, ref values[0]);
            if (result == 0)
            {
                string msg = $"缓冲区成功写入。";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "缓冲区写入失败,原因:" + msg);
            }
        }

效果

9,软元件登录,解除。

  private void btn_AddEntryDevice_Click(object sender, EventArgs e)
        {
            //软元件之间使用\n进行分割
            if (string.IsNullOrEmpty(txt_EntryDevices.Text.Trim()))
            {
                MessageBox.Show("登录的软元件不能为空");
                return;
            }
            foreach (var item in txt_EntryDevices.Lines)
            {
                if (!Regex.IsMatch(item, @"[a-zA-Z]+\d+(\.\d+)?"))
                {
                    MessageBox.Show("登录的软元件格式错误!");
                    return;
                }
            }
            //周期,单位为秒,范围为1s-1hour超过这个范围将报异常
            int cycle;
            if (!int.TryParse(txt_Cycle.Text, out cycle))
            {
                MessageBox.Show("周期值只能为正正数");
                return;
            }
            //规定需要使用\n进行分割
            string devices = string.Join("\n", txt_EntryDevices.Lines);
            //登录的软元件数量,单次登录的软元件数量不能超过20个。
            int num = txt_EntryDevices.Lines.Length;
            //----------------------------------------
            //登录软元件触发OnDeviceStatus的条件,例如M0,对应的条件设置为1,则只有当M0为1(即ON)时才定时触发该事件
            int[] entryDeviceConditionList = new int[num];
            for (int i = 0; i < txt_EntryDeviceCondition.Lines.Length; i++)
            {
                if (i < num)
                {
                    entryDeviceConditionList[i] = Convert.ToInt32(txt_EntryDeviceCondition.Lines[i]);
                }
               
            }
            int result = PLC.EntryDeviceStatus(devices, num, cycle, ref entryDeviceConditionList[0]);
            if (result == 0)
            {
                AddLog(0, "软元件登录成功");
                foreach (var item in txt_EntryDevices.Lines)
                {
                    lst_EntryDevice.Items.Add(item);
                }
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, $"软元件登录失败,原因:{msg}");
            }
        }

        private void btn_RemoveEntryDevice_Click(object sender, EventArgs e)
        {
           int result=   PLC.FreeDeviceStatus();
            if (result == 0)
            {
                AddLog(0, "软元件释放成功");
                lst_EntryDevice.Items.Clear();
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, $"软元件释放失败,原因:{msg}");
            }
        }

10,项目编译注意事项

如果出现编译异常,提示需要注册等信息,请将项目属性->生成->目标平台 设置为x86,再重新编译。

5,Demo代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace Demo
{
    public partial class Form1 : Form
    {
        ActUtlTypeLib.ActUtlTypeClass PLC = new ActUtlTypeLib.ActUtlTypeClass();
        ActSupportMsgLib.ActMLSupportMsgClass support = new ActSupportMsgLib.ActMLSupportMsgClass();
        public Form1()
        {
            InitializeComponent();
            AddLog(0, "应用启动!");
            groupBox1.Enabled = false;
            groupBox2.Enabled = false;
            groupBox3.Enabled = false;
            PLC.OnDeviceStatus += PLC_OnDeviceStatus;
        }
        private void PLC_OnDeviceStatus(string szDevice, int lData, int lReturnCode)
        {
            //登录软元件的所触发的事件
            if (lReturnCode == 0)
            {
                AddLog(0, $"登录的软元件:{szDevice}={lData}");
            }
            else
            {
                string msg = GetErrorMessage(lReturnCode);
                AddLog(2, $"登录的软元件异常,原因:{msg}");
            }
        }
        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txt_Station.Text.Trim()))
            {
                MessageBox.Show("逻辑站点不能为空");
                return;
            }
            int stationNum;
            if (int.TryParse(txt_Station.Text.Trim(), out stationNum))
            {
                if (stationNum < 0)
                {
                    MessageBox.Show("逻辑站点必须为正数");
                    return;
                }
            }
            else
            {
                MessageBox.Show("逻辑站点必须为正数");
                return;
            }
            if (btnConnect.Text.Equals("连接"))
            {
                PLC.ActLogicalStationNumber = stationNum;
                PLC.ActPassword = txt_Pwd.Text.Trim();
                int result = PLC.Open();
                if (result == 0)
                {
                    AddLog(0, "PLC已成功连接!");
                    btnConnect.Text = "断开";
                    btnConnect.BackColor = Color.Green;
                    groupBox1.Enabled = true;
                    groupBox2.Enabled = true;
                    groupBox3.Enabled = true;
                    //获取当前PLC型号信息
                    string cpuName;
                    int cpuCode;
                    result = PLC.GetCpuType(out cpuName, out cpuCode);
                    if (result == 0)
                    {
                        lblCPUModel.Text = cpuName;
                        lblCPUCode.Text = "0x" + cpuCode.ToString("X8");
                        AddLog(0, "已成功获取PLC CPU信息");
                    }
                    else
                    {
                        AddLog(1, "获取PLC CPU信息失败,原因:" + GetErrorMessage(result));
                    }
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "PLC 连接失败!原因:" + msg);
                }
            }
            else
            {
                int result = PLC.Close();
                if (result == 0)
                {
                    lblCPUCode.Text = "";
                    lblCPUModel.Text = "";
                    lblPLCDateTime.Text = "";
                    groupBox1.Enabled = false;
                    groupBox2.Enabled = false;
                    groupBox3.Enabled = false;
                    AddLog(0, "PLC已断开连接");
                    btnConnect.Text = "连接";
                    btnConnect.BackColor = Color.DarkKhaki;
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "PLC 断开连接失败!原因:" + msg);
                }
            }
        }
        private void btnReadPLCTime_Click(object sender, EventArgs e)
        {
            short year, month, day, dayOfWeek, hour, minute, second;
            int result = PLC.GetClockData(out year, out month, out day, out dayOfWeek, out hour, out minute, out second);
            if (result == 0)
            {
                lblPLCDateTime.Text = $"PLC时钟:{year}/{month}/{day} {hour}:{minute}:{second} 星期{dayOfWeek}";
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "读取PLC时钟错误,原因:" + msg);
            }
        }
        private void plcSwitch_Click(object sender, EventArgs e)
        {
            //参数IOperator:0 远程Run;1 远程 Stop;2 远程Pause
            int result = PLC.SetCpuStatus(plcSwitch.CurrentPosition);
            if (result != 0)
            {
                string msg;
                msg = GetErrorMessage(result);
                AddLog(2, "PLC状态切换失败,原因:" + msg);
            }
            else
            {
                switch (plcSwitch.CurrentPosition)
                {
                    case 0:
                        //自动
                        led_PLC.LEDBackColor = Color.Green;
                        break;
                    case 1:
                        //Stop
                        led_PLC.LEDBackColor = Color.Red;
                        break;
                    default:
                        //pause
                        led_PLC.LEDBackColor = Color.Orange;
                        break;
                }
            }
        }
        private void btnWritePLCTime_Click(object sender, EventArgs e)
        {
            //向PLC写入时钟
            DateTime dt = dateTimePicker1.Value;
            int result = PLC.SetClockData((short)dt.Year, (short)dt.Month, (short)dt.Day, (short)dt.DayOfWeek, (short)dt.Hour, (short)dt.Minute, (short)dt.Second);
            if (result == 0)
            {
                AddLog(0, "PLC时钟设置成功!");
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "PLC时钟设置失败,原因:" + msg);
            }
        }
        /// <summary>
        /// 根据错误代码获取错误信息
        /// </summary>
        /// <param name="errorCode"></param>
        /// <returns></returns>
        string GetErrorMessage(int errorCode)
        {
            object str;
            support.GetErrorMessage(errorCode, out str);
            if (str != null)
            {
                return System.Text.RegularExpressions.Regex.Replace(str.ToString(), @"\r|\n", "");
            }
            return "";
        }
        void AddLog(int level, string msg)
        {
            ListViewItem item = new ListViewItem();
            item.ImageIndex = level;
            item.SubItems.Add(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
            item.SubItems.Add(msg);
            listView1.Items.Add(item);
            listView1.EnsureVisible(listView1.Items.Count - 1);
        }
        private void btnReadDeviceBlock_Click(object sender, EventArgs e)
        {
            //以4个byte为单位的int块读取
            if (Verification(txt_ReadBlockAddress, txt_ReadBlockSize))
            {
                int num = int.Parse(txt_ReadBlockSize.Text.Trim());
                short[] arr = new short[num];
                int result = PLC.ReadDeviceBlock2(txt_ReadBlockAddress.Text.Trim(), num, out arr[0]);
                if (result == 0)
                {
                    string msg = $"{txt_ReadBlockAddress.Text}连续{num}个地址值为:{string.Join(",", arr)}";
                    AddLog(0, msg);
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, txt_ReadBlockAddress.Text + "块读取失败,原因:" + msg);
                }
            }
        }
        private void btnWriteDeviceBlock_Click(object sender, EventArgs e)
        {
            if (Verification(txt_WriteBlockAddress, txt_WriteBlockValue))
            {
                int num;
                if (!int.TryParse(txt_WriteBlockSize.Text.Trim(), out num))
                {
                    MessageBox.Show("请输入正确的数量!");
                    return;
                }
                int[] arr = txt_WriteBlockValue.Lines.Select(item => Convert.ToInt32(item)).ToArray();
                int result = PLC.WriteDeviceBlock(txt_ReadBlockAddress.Text.Trim(), num, ref arr[0]);
                if (result == 0)
                {
                    string msg = $"从{txt_ReadBlockAddress.Text}开始连续写入{num}个地址值为:{string.Join(",", arr)}";
                    AddLog(0, msg);
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, txt_ReadBlockAddress.Text + "块写入失败,原因:" + msg);
                }
            }
        }
        bool Verification(TextBox tb01, TextBox tb02)
        {
            //第一个必须为有效的PLC地址,第一个必须为数字
            if (string.IsNullOrEmpty(tb01.Text.Trim()))
            {
                MessageBox.Show("不能为空!");
                tb01.Focus();
                return false;
            }
            if (string.IsNullOrEmpty(tb02.Text.Trim()))
            {
                MessageBox.Show("不能为空!");
                tb02.Focus();
                return false;
            }
            foreach (var item in tb01.Lines)
            {
                if (!Regex.IsMatch(item, @"^[a-zA-Z]+\d+(\.\d+)?(\r|\n|\r\n)?$"))
                {
                    MessageBox.Show("地址格式错误!");
                    tb01.Focus();
                    return false;
                }
            }
            foreach (var item in tb02.Lines)
            {
                double val;
                if (!double.TryParse(item, out val))
                {
                    MessageBox.Show("数据格式错误!");
                    tb02.Focus();
                    return false;
                }
            }
            return true;
        }
        private void btnReadDeviceRandom_Click(object sender, EventArgs e)
        {
            if (Verification(txt_ReadRandomAddress, txt_ReadRandomSize))
            {
                int num;
                if (!int.TryParse(txt_ReadRandomSize.Text.Trim(), out num))
                {
                    MessageBox.Show("只能为正整数");
                    return;
                }
                //对地址进行离散读取,例如一次读取D0,D2,D3,D6等非连续地址
                string[] arr = txt_ReadRandomAddress.Lines;
                short[] values = new short[arr.Length];
                string addres = string.Join("\n", arr);//地址间使用\n进行分割
                //注意这里特意使用ReadDeviceRandom2,而不是ReadDeviceRandom,
                //就是为表示两者除了读取的值,除类型(一个是Int 一个是Short)不同外其他都一样
                int result = PLC.ReadDeviceRandom2(addres, num, out values[0]);
                if (result == 0)
                {
                    //读取成功
                    string[] strs = arr.Where((item, index) => index < num).Select((item, index) => $"{item}={values[index]}").ToArray();
                    AddLog(0, "读取成功:" + string.Join(",", strs));
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "离散读取地址值失败,失败原因:" + msg);
                }
            }
        }
        private void btnWriteDeviceRandom_Click(object sender, EventArgs e)
        {
            if (Verification(txt_WriteRandomAddress, txt_WriteRandomValue))
            {
                string[] address = txt_WriteRandomAddress.Lines;
                int[] values = txt_WriteRandomValue.Lines.Select(item => Convert.ToInt32(item)).ToArray();
                //各地址之间使用\n进行分割
                string addStr = string.Join("\n", address);
                int result = PLC.WriteDeviceRandom(addStr, values.Length, ref values[0]);
                if (result == 0)
                {
                    AddLog(0, "成功写入值。");
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "离散写入失败,失败原因:" + msg);
                }
            }
        }
        private void btnGetDevice_Click(object sender, EventArgs e)
        {
            //获取单个寄存器的值
            if (!Regex.IsMatch(txt_ReadDeviceAddress.Text.Trim(), @"^[a-zA-Z]+\d+(\.\d+)?$"))
            {
                MessageBox.Show("地址格式错误!");
                txt_ReadDeviceAddress.Focus();
                return;
            }
            short value;
            int result = PLC.GetDevice2(txt_ReadDeviceAddress.Text.Trim(), out value);
            if (result == 0)
            {
                string msg = $"读取成功,{value}";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "读取失败,原因:" + msg);
            }
        }
        private void btnSetDevice_Click(object sender, EventArgs e)
        {
            //对单个寄存器进行写入
            if (Verification(txt_WriteDeviceAddress, txt_WriteDeviceValue))
            {
                int value = int.Parse(txt_WriteDeviceValue.Text.Trim());
                int result = PLC.SetDevice(txt_WriteDeviceAddress.Text, value);
                if (result == 0)
                {
                    AddLog(0, "成功写入!");
                }
                else
                {
                    string msg = GetErrorMessage(result);
                    AddLog(2, "写入失败,原因:" + msg);
                }
            }
        }
        private void btnReadBuffer_Click(object sender, EventArgs e)
        {
            //缓冲区地址读取
            int ioNum, num, address;
            if (!int.TryParse(txt_ReadBufferStartIO.Text.Trim(), out ioNum))
            {
                MessageBox.Show("起始地址格式错误");
                return;
            }
            if (!int.TryParse(txt_ReadBufferSize.Text.Trim(), out num))
            {
                MessageBox.Show("数量格式错误");
                return;
            }
            if (!int.TryParse(txt_ReadBufferStartAddress.Text.Trim(), out address))
            {
                MessageBox.Show("地址格式错误,地址只能为数字");
                return;
            }
            short[] values = new short[num];
            int result = PLC.ReadBuffer(ioNum, address, num, out values[0]);
            if (result == 0)
            {
                string msg = $"缓冲区读取成功:{string.Join(",", values)}";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "缓冲区读取失败,原因:" + msg);
            }
        }
        private void btnWriteBuffer_Click(object sender, EventArgs e)
        {
            //缓冲区地址写入
            int ioNum, address;
            if (!int.TryParse(txt_WriteBufferIO.Text.Trim(), out ioNum))
            {
                MessageBox.Show("起始地址格式错误");
                return;
            }
            if (!int.TryParse(txt_WriteBufferAddress.Text.Trim(), out address))
            {
                MessageBox.Show("地址格式错误,地址只能为数字");
                return;
            }
            if (string.IsNullOrEmpty(txt_WriteBufferValue.Text.Trim()))
            {
                MessageBox.Show("请勿写入空值");
                return;
            }
            foreach (var item in txt_WriteBufferValue.Lines)
            {
                if (!Regex.IsMatch(item, @"^\d+(\r|\n|\r\n)?$"))
                {
                    MessageBox.Show("写入的数据格式错误,写入的数据只能是short.");
                    return;
                }
            }
            short[] values = txt_WriteBufferValue.Lines.Select(item => Convert.ToInt16(item)).ToArray();
            int result = PLC.WriteBuffer(ioNum, address, values.Length, ref values[0]);
            if (result == 0)
            {
                string msg = $"缓冲区成功写入。";
                AddLog(0, msg);
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, "缓冲区写入失败,原因:" + msg);
            }
        }
        private void btn_AddEntryDevice_Click(object sender, EventArgs e)
        {
            //软元件之间使用\n进行分割
            if (string.IsNullOrEmpty(txt_EntryDevices.Text.Trim()))
            {
                MessageBox.Show("登录的软元件不能为空");
                return;
            }
            foreach (var item in txt_EntryDevices.Lines)
            {
                if (!Regex.IsMatch(item, @"[a-zA-Z]+\d+(\.\d+)?"))
                {
                    MessageBox.Show("登录的软元件格式错误!");
                    return;
                }
            }
            //周期,单位为秒,范围为1s-1hour超过这个范围将报异常
            int cycle;
            if (!int.TryParse(txt_Cycle.Text, out cycle))
            {
                MessageBox.Show("周期值只能为正正数");
                return;
            }
            //规定需要使用\n进行分割
            string devices = string.Join("\n", txt_EntryDevices.Lines);
            //登录的软元件数量,单次登录的软元件数量不能超过20个。
            int num = txt_EntryDevices.Lines.Length;
            //----------------------------------------
            //登录软元件触发OnDeviceStatus的条件,例如M0,对应的条件设置为1,则只有当M0为1(即ON)时才定时触发该事件
            int[] entryDeviceConditionList = new int[num];
            for (int i = 0; i < txt_EntryDeviceCondition.Lines.Length; i++)
            {
                if (i < num)
                {
                    entryDeviceConditionList[i] = Convert.ToInt32(txt_EntryDeviceCondition.Lines[i]);
                }
            }
            int result = PLC.EntryDeviceStatus(devices, num, cycle, ref entryDeviceConditionList[0]);
            if (result == 0)
            {
                AddLog(0, "软元件登录成功");
                foreach (var item in txt_EntryDevices.Lines)
                {
                    lst_EntryDevice.Items.Add(item);
                }
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, $"软元件登录失败,原因:{msg}");
            }
        }
        private void btn_RemoveEntryDevice_Click(object sender, EventArgs e)
        {
           int result=   PLC.FreeDeviceStatus();
            if (result == 0)
            {
                AddLog(0, "软元件释放成功");
                lst_EntryDevice.Items.Clear();
            }
            else
            {
                string msg = GetErrorMessage(result);
                AddLog(2, $"软元件释放失败,原因:{msg}");
            }
        }
    }
}

6,Demo链接。

https://download.csdn.net/download/lingxiao16888/89767457

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值