您的位置:首页 > 汽车 > 新车 > C#通过MXComponent与三菱PLC通信

C#通过MXComponent与三菱PLC通信

2024/10/18 19:27:45 来源:https://blog.csdn.net/lingxiao16888/article/details/142333036  浏览:    关键词: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 远程Pauseint 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://Stopled_PLC.LEDBackColor = Color.Red;break;default://pauseled_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 远程Pauseint 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://Stopled_PLC.LEDBackColor = Color.Red;break;default://pauseled_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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com