当前位置: 首页 > news >正文

C#实现三菱FX3SA PLC串口通信测试实例

  1. 硬件:

    • 使用RS232或RS485转USB转换器

    • 连接PLC的编程口(通常是8针圆口)

  2. 软件VS2019

  3. PLC设置

    • 确保PLC的通信参数与程序设置一致:

      • 波特率:9600

      • 数据位:7

      • 校验位:偶校验

      • 停止位:1

程序功能实发送报文 0x02, 0x30, 0x31, 0x30, 0x31, 0x34, 0x30, 0x32, 0x03, 0x35, 0x42

      对接收到的报文数据进行处理实时读取PLC中数据寄存器D10存储数据,程序如下:

using System;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.Diagnostics;namespace PLCCommunicationTest
{public partial class Form1 : Form{private ComboBox comboBoxPorts;private Button btnRefreshPorts;private Button btnConnect;private Button btnDisconnect;private Button btnStartReading;private Button btnStopReading;private Label lblValueDisplay;private Label lblStatus;private Label lblRawData;private SerialPort serialPort1;private Thread readThread;private ManualResetEvent stopEvent = new ManualResetEvent(false);private object serialLock = new object();private bool isReading = false;public Form1(){InitializeCustomComponents();InitializeSerialPort();RefreshSerialPorts();}private void InitializeCustomComponents(){this.Text = "三菱FX3SA PLC数据监视 - 修正版";this.Size = new Size(600, 450);this.FormClosing += Form1_FormClosing;this.BackColor = Color.White;// 创建控件comboBoxPorts = new ComboBox();btnRefreshPorts = new Button();btnConnect = new Button();btnDisconnect = new Button();btnStartReading = new Button();btnStopReading = new Button();lblValueDisplay = new Label();lblStatus = new Label();lblRawData = new Label();serialPort1 = new SerialPort();// 配置comboBoxPortscomboBoxPorts.Location = new Point(12, 12);comboBoxPorts.Size = new Size(80, 21);comboBoxPorts.DropDownStyle = ComboBoxStyle.DropDownList;// 配置btnRefreshPortsbtnRefreshPorts.Location = new Point(100, 10);btnRefreshPorts.Size = new Size(60, 23);btnRefreshPorts.Text = "刷新";btnRefreshPorts.Click += btnRefreshPorts_Click;// 配置btnConnectbtnConnect.Location = new Point(170, 10);btnConnect.Size = new Size(60, 23);btnConnect.Text = "连接";btnConnect.Click += btnConnect_Click;// 配置btnDisconnectbtnDisconnect.Location = new Point(240, 10);btnDisconnect.Size = new Size(60, 23);btnDisconnect.Text = "断开";btnDisconnect.Enabled = false;btnDisconnect.Click += btnDisconnect_Click;// 配置btnStartReadingbtnStartReading.Location = new Point(310, 10);btnStartReading.Size = new Size(80, 23);btnStartReading.Text = "开始读取";btnStartReading.Enabled = false;btnStartReading.Click += btnStartReading_Click;// 配置btnStopReadingbtnStopReading.Location = new Point(400, 10);btnStopReading.Size = new Size(80, 23);btnStopReading.Text = "停止读取";btnStopReading.Enabled = false;btnStopReading.Click += btnStopReading_Click;// 配置lblValueDisplaylblValueDisplay.Location = new Point(12, 50);lblValueDisplay.Size = new Size(560, 150);lblValueDisplay.Text = "0";lblValueDisplay.TextAlign = ContentAlignment.MiddleCenter;lblValueDisplay.Font = new Font("Arial", 48, FontStyle.Bold);lblValueDisplay.ForeColor = Color.Blue;lblValueDisplay.BackColor = Color.LightGray;lblValueDisplay.BorderStyle = BorderStyle.FixedSingle;// 配置状态标签lblStatus.Location = new Point(12, 210);lblStatus.Size = new Size(560, 25);lblStatus.Text = "就绪";lblStatus.TextAlign = ContentAlignment.MiddleCenter;lblStatus.ForeColor = Color.Green;lblStatus.Font = new Font("Arial", 10, FontStyle.Regular);// 配置原始数据显示lblRawData.Location = new Point(12, 245);lblRawData.Size = new Size(560, 60);lblRawData.Text = "原始数据: 无";lblRawData.TextAlign = ContentAlignment.MiddleCenter;lblRawData.ForeColor = Color.DarkBlue;lblRawData.Font = new Font("Arial", 9, FontStyle.Regular);lblRawData.BorderStyle = BorderStyle.FixedSingle;// 添加控件到窗体this.Controls.Add(comboBoxPorts);this.Controls.Add(btnRefreshPorts);this.Controls.Add(btnConnect);this.Controls.Add(btnDisconnect);this.Controls.Add(btnStartReading);this.Controls.Add(btnStopReading);this.Controls.Add(lblValueDisplay);this.Controls.Add(lblStatus);this.Controls.Add(lblRawData);}private void InitializeSerialPort(){serialPort1.BaudRate = 9600;serialPort1.DataBits = 7;serialPort1.Parity = Parity.Even;serialPort1.StopBits = StopBits.One;serialPort1.Handshake = Handshake.None;serialPort1.ReadTimeout = 1000;serialPort1.WriteTimeout = 1000;}private void RefreshSerialPorts(){comboBoxPorts.Items.Clear();string[] ports = SerialPort.GetPortNames();comboBoxPorts.Items.AddRange(ports);if (comboBoxPorts.Items.Count > 0)comboBoxPorts.SelectedIndex = 0;}private void ReadThreadMethod(){while (!stopEvent.WaitOne(0) && isReading){if (serialPort1.IsOpen){PerformSingleRead();}Thread.Sleep(300);}}private void PerformSingleRead(){lock (serialLock){try{serialPort1.DiscardInBuffer();serialPort1.DiscardOutBuffer();// 发送读取命令byte[] commandBytes = new byte[]{0x02, 0x30, 0x31, 0x30, 0x31, 0x34, 0x30, 0x32, 0x03, 0x35, 0x42};serialPort1.Write(commandBytes, 0, commandBytes.Length);Thread.Sleep(150);if (serialPort1.BytesToRead > 0){byte[] buffer = new byte[serialPort1.BytesToRead];int bytesRead = serialPort1.Read(buffer, 0, buffer.Length);if (bytesRead > 0){string result = ProcessPLCData(buffer);UpdateUI(result, buffer);}}else{UpdateUI("无响应", new byte[0]);}}catch (Exception ex){UpdateUI($"错误: {ex.Message}", new byte[0]);}}}private void UpdateUI(string value, byte[] rawData){if (lblValueDisplay.InvokeRequired){lblValueDisplay.Invoke(new Action<string, byte[]>(UpdateUI), value, rawData);return;}if (value.StartsWith("错误") || value == "无响应"){lblValueDisplay.Text = value;lblValueDisplay.ForeColor = Color.Red;lblStatus.Text = "读取失败";lblStatus.ForeColor = Color.Red;}else{lblValueDisplay.Text = value;lblValueDisplay.ForeColor = Color.Blue;lblStatus.Text = "读取成功";lblStatus.ForeColor = Color.Green;}// 显示原始数据if (rawData.Length > 0){string hexString = BitConverter.ToString(rawData).Replace("-", " ");lblRawData.Text = $"原始数据: {hexString}";}else{lblRawData.Text = "原始数据: 无";}}// 处理接收到的PLC数据并提取数值 - 修正版本private string ProcessPLCData(byte[] receivedData){try{// 检查数据长度是否足够且格式正确if (receivedData.Length < 6 || receivedData[0] != 0x02){return "格式错误";}// 查找结束符int endIndex = -1;for (int i = 1; i < receivedData.Length; i++){if (receivedData[i] == 0x03){endIndex = i;break;}}if (endIndex == -1 || endIndex < 5){return "帧错误";}// 提取第2到第5个字节 (索引1-4)byte[] extractedBytes = new byte[4];Array.Copy(receivedData, 1, extractedBytes, 0, 4);// 重新排列: 第4、5字节在前,第2、3字节在后byte[] rearrangedBytes = new byte[4];rearrangedBytes[0] = extractedBytes[2]; // 原第4字节rearrangedBytes[1] = extractedBytes[3]; // 原第5字节rearrangedBytes[2] = extractedBytes[0]; // 原第2字节rearrangedBytes[3] = extractedBytes[1]; // 原第3字节// 关键修正:将ASCII字节转换为字符串,然后解析为十六进制string hexString = Encoding.ASCII.GetString(rearrangedBytes);// 将十六进制字符串转换为十进制int decimalValue = Convert.ToInt32(hexString, 16);return decimalValue.ToString();}catch (Exception ex){return $"解析错误: {ex.Message}";}}// 其他方法保持不变...private void btnRefreshPorts_Click(object sender, EventArgs e){RefreshSerialPorts();}private void btnConnect_Click(object sender, EventArgs e){if (comboBoxPorts.SelectedItem == null){MessageBox.Show("请选择串口");return;}try{serialPort1.PortName = comboBoxPorts.SelectedItem.ToString();serialPort1.Open();btnConnect.Enabled = false;btnDisconnect.Enabled = true;btnStartReading.Enabled = true;UpdateUI("0", new byte[0]);lblStatus.Text = "已连接";lblStatus.ForeColor = Color.Green;}catch (Exception ex){MessageBox.Show($"连接失败: {ex.Message}");}}private void btnDisconnect_Click(object sender, EventArgs e){StopReading();try{if (serialPort1.IsOpen)serialPort1.Close();btnConnect.Enabled = true;btnDisconnect.Enabled = false;btnStartReading.Enabled = false;btnStopReading.Enabled = false;UpdateUI("0", new byte[0]);lblStatus.Text = "已断开";lblStatus.ForeColor = Color.Blue;}catch (Exception ex){MessageBox.Show($"断开连接失败: {ex.Message}");}}private void btnStartReading_Click(object sender, EventArgs e){StartReading();}private void btnStopReading_Click(object sender, EventArgs e){StopReading();}private void StartReading(){if (!isReading && serialPort1.IsOpen){isReading = true;stopEvent.Reset();readThread = new Thread(ReadThreadMethod);readThread.IsBackground = true;readThread.Start();btnStartReading.Enabled = false;btnStopReading.Enabled = true;lblStatus.Text = "正在读取...";lblStatus.ForeColor = Color.Blue;}}private void StopReading(){if (isReading){isReading = false;stopEvent.Set();if (readThread != null && readThread.IsAlive){readThread.Join(1000);}btnStartReading.Enabled = true;btnStopReading.Enabled = false;lblStatus.Text = "读取已停止";lblStatus.ForeColor = Color.Blue;}}private void Form1_FormClosing(object sender, FormClosingEventArgs e){StopReading();if (serialPort1.IsOpen)serialPort1.Close();}private void InitializeComponent(){this.SuspendLayout();this.ClientSize = new System.Drawing.Size(284, 261);this.Name = "Form1";this.ResumeLayout(false);}}
}

运行后如图:

http://www.dtcms.com/a/447593.html

相关文章:

  • 公司网站如何注册政务门户网站建设
  • 10.5交作业
  • 网站建设的数据所有权网页浏览器是系统软件吗
  • 事业单位网站后台建设方案建立网站一般包括什么等方式
  • 外贸做网站公司哪家好郑州高端网站案例
  • html5做网站优势东莞公司企业设计网站建设
  • 制作网站图片不显示百度招商加盟
  • 建设实验教学网站的作用有免费建站的网站
  • 表白网页制作免费网站深圳人口1756万
  • 沈阳网站建设找思路手机上干点啥能挣零花钱
  • 企业网站软件用asp做网站遇到的问题
  • 【Android】支持在线打开的文件浏览服务器开发流程讲解
  • 太原做企业网站的简洁企业网站
  • 中国邮政做特产的网站建一个网站怎么赚钱
  • 广州网站建设知名乐云seoseo关键词排名软件流量词
  • 网站备案 图标郑州做网站的论坛
  • 【Java核心技术/基础】30道Java集合框架面试题及答案
  • 福州市建设局网站 动态网站更改
  • 北京移动网站建设公司排名网站优化效果
  • ip子域名二级域名解析企业网站优化分为哪两个方向
  • 做网贷网站宁波公司建站模板
  • 怎么搭建自己的网站平台cms模板
  • 营销网站建设制作电商网站对比 京东商城 淘宝网 阿里巴巴
  • AI时代工作与学习的秘密武器:如何最大化利用大模型
  • 携程网站 建设平台分析logo在线设计图片
  • 网站建设案例企业网站怎样优化seo
  • 网站建设合同书品牌公关案例
  • wamp做的网站标签图标案例中优衣库所采用的网络营销方式
  • 河南省建设厅网站资质平移办法佛山服务类网站建设
  • wordpress安装tomcat江门排名优化怎么做