C# 跨线程调用form控件技巧及byte[]与string型相互转换

本文介绍了一种在Windows Forms应用程序中实现跨线程调用Form控件的方法,并提供了具体的代码示例。此外,还介绍了如何在byte数组与string类型之间进行转换。

 跨线程调用form控件技巧

private delegate void MethodSocket(object obj);//使用托管
ss = "OK";       
 this.BeginInvoke(new MethodSocket(InvokerReadMsg), ss);//this指向本窗口,回调函数InvokerReadMsg,

        private void InvokerReadMsg(object obj)//在这个函数里面能够直接訪问Form控件<span style="font-family: Arial, Helvetica, sans-serif;">txtContent</span>

        {
            this.txtContent.Text += obj.ToString() + "\r\n";
        }


byte[]与string型相互转换

//byte 转string
string test = Encoding.Default.GetString(bytes, 0, length);
//string 转 byte
 byte[] bytes = System.Text.Encoding.Default.GetBytes(test);


<think>我们正在讨论如何使用C#通过MXComponent控件三菱PLC进行float数据通讯。根据用户需求,需要示例代码。参考之前的引用[1]中提到了使用ActUtlType64Lib,这是MXComponent提供的库。MXComponent提供了多种控件,ActUtlType64Lib是其中的一个ActiveX控件,用于PLC通信。对于float数据的读写,我们需要知道三菱PLC中存储float数据的内存区域(如D寄存器)以及地址。然后使用相应的方法进行读写。步骤:1.建立连接(如示例代码中的Open方法)2.使用ReadDeviceBlock或ReadDeviceRandom方法读取多个寄存器(因为一个float占用两个连续的16位寄存器)3.使用WriteDeviceBlock或WriteDeviceRandom方法写入多个寄存器注意:float在PLC中存储为32位,占用两个连续的16位寄存器。读取时,需要读取两个寄存器,然后将这两个寄存器中的值(一个字)组合成一个float。写入同理。由于MXComponent提供的ActUtlType64Class控件的读写方法通常操作的是short类(16位整数),我们需要将float转换为两个short,或者将两个short组合为float。示例代码将包括:1.连接PLC2.读取一个float(从指定的寄存器地址开始,如D100)3.写入一个float到指定的寄存器地址需要处理的数据转换:读取:从PLC读取两个连续的寄存器(例如D100和D101),然后将这两个16位整数合并成一个32位浮点数。写入:将一个32位浮点数拆分成两个16位整数,然后写入两个连续的寄存器。我们可以使用BitConverter类来帮助完成转换。注意:三菱PLC中float的存储顺序(字节序)可能是小端模式(little-endian),但根据三菱PLC的文档,其存储顺序是高位在前(大端模式)。然而,在MXComponent中,当我们读取两个寄存器时,第一个寄存器对应的是float的高16位,第二个是低16位。但是,在C#中,BitConverter默认使用小端模式,所以我们需要根据实际情况调整。实际上,MXComponent读取回来的两个short,第一个short对应的是float的高16位(在内存中的前两个字节),第二个short对应的是低16位(后两个字节)。因此,我们可以将这两个short按顺序组成一个32位整数,然后用BitConverter转换为float。但是要注意,如果我们按顺序将高16位和低16位组合,那么得到的字节数组应该是大端模式。而BitConverter.ToSingle要求的是小端模式。因此,我们需要进行字节顺序的转换。另一种做法是:将两个short的字节按照大端顺序组合成4个字节的数组,然后反转这个数组(如果系统是小端),再用BitConverter转换为float。或者,我们可以使用以下方法:1.读取两个寄存器,得到两个short:s1(高16位)和s2(低16位)。2.将s1和s2转换为两个字节数组(每个short转换为两个字节),然后连接成一个4字节数组。3.由于三菱PLC使用大端模式,而我们的系统通常是小端模式,所以需要将整个4字节数组反转(即大端转小端)。4.用BitConverter.ToSingle将字节数组转换为float。写入时则相反:1.将float用BitConverter.GetBytes转换为4字节数组(小端模式)。2.反转这个数组(小端转大端)。3.将前两个字节转换为一个short(高16位),后两个字节转换为一个short(低16位)。4.写入两个连续的寄存器。但是,MXComponent的读写方法使用的是16位整数(short),所以我们需要按上述方式拆分。另外,MXComponent提供了ReadDeviceBlock2和WriteDeviceBlock2方法,可以直接读取多个寄存器,并以数组形式返回。具体代码实现:连接部分参考之前的代码。读取float的示例函数:注意:由于ActUtlType64Class的方法参数要求,我们需要使用数组来存储读取结果。步骤:1.声明一个short数组,大小为2。2.调用ReadDeviceBlock方法,从起始地址读取2个寄存器(注意地址的表示方法,如"D100")。3.将两个short合并成一个float。写入float的示例函数:1.将float转换为4字节数组(小端模式)。2.反转数组(变成大端模式)。3.将前两个字节作为第一个short,后两个字节作为第二个short。4.调用WriteDeviceBlock方法,写入两个寄存器。但是,MXComponent的ReadDeviceBlock和WriteDeviceBlock方法在读写多个寄存器时比较方便。然而,我们也可以使用ReadDeviceRandom和WriteDeviceRandom方法,但这里使用ReadDeviceBlock和WriteDeviceBlock。另外,注意MXComponent中地址的表示:对于D寄存器,直接使用"D100"。代码示例:首先,确保已经添加了ActUtlType64Lib的引用(COM组件:ActMELib64Library,或者通过添加引用的COM选项卡中找到“ActMELib64TypeLibrary”)。由于ActUtlType64Class的ReadDeviceBlock和WriteDeviceBlock方法需要传入数组,并且要求数组是传引用(ref),同时需要指定读取/写入的个数。下面我们编写代码:</think>以下是使用C#通过MX Component控件三菱PLC进行float数据通讯的完整解决方案和示例代码: ### 解决方案核心要点 1. **数据格式转换** PLC中的float类占用2个连续的16位寄存器(32位),需进行高低位转换: ```csharp // float转PLC寄存器数组 byte[] floatBytes = BitConverter.GetBytes(value); Array.Reverse(floatBytes); // 大端字节序转换 short high = BitConverter.ToInt16(floatBytes, 0); short low = BitConverter.ToInt16(floatBytes, 2); ``` 2. **通讯协议选择** 使用`ActUtlType64Lib`组件,支持以下通讯方式: - MC协议(推荐) - Q系列CPU通讯 - FX系列编程口通讯 3. **关键方法** - `ReadDeviceBlock()`:读取连续寄存器 - `WriteDeviceBlock()`:写入连续寄存器 ### 完整示例代码 ```csharp using System; using System.Windows.Forms; using ActUtlType64Lib; // 添加引用: COM组件 -> ActMELib64 Library public class MitsubishiPLCCommunicator { private ActUtlType64Class plc = new ActUtlType64Class(); public bool Connect(int stationNo = 1) { plc.ActLogicalStationNumber = stationNo; int result = plc.Open(); return result == 0; // 返回0表示成功 } public void Disconnect() { plc.Close(); } // 读取float值 (从起始寄存器地址) public float ReadFloat(string startAddress) { short[] data = new short[2]; int result = plc.ReadDeviceBlock(startAddress, 2, out data[0]); if (result != 0) throw new Exception($"读取失败, 错误码: {result}"); byte[] bytes = new byte[4]; byte[] highBytes = BitConverter.GetBytes(data[0]); byte[] lowBytes = BitConverter.GetBytes(data[1]); // 组合高低位并转换字节序 Buffer.BlockCopy(highBytes, 0, bytes, 0, 2); Buffer.BlockCopy(lowBytes, 0, bytes, 2, 2); Array.Reverse(bytes); return BitConverter.ToSingle(bytes, 0); } // 写入float值 (到起始寄存器地址) public void WriteFloat(string startAddress, float value) { byte[] floatBytes = BitConverter.GetBytes(value); Array.Reverse(floatBytes); // 转为大端字节序 short[] regValues = new short[2]; regValues[0] = BitConverter.ToInt16(floatBytes, 0); // 高16位 regValues[1] = BitConverter.ToInt16(floatBytes, 2); // 低16位 int result = plc.WriteDeviceBlock(startAddress, 2, ref regValues[0]); if (result != 0) throw new Exception($"写入失败, 错误码: {result}"); } } // 使用示例 public partial class MainForm : Form { MitsubishiPLCCommunicator plcComm = new MitsubishiPLCCommunicator(); private void btnConnect_Click(object sender, EventArgs e) { if (plcComm.Connect()) MessageBox.Show("PLC连接成功"); else MessageBox.Show("连接失败"); } private void btnRead_Click(object sender, EventArgs e) { try { float temp = plcComm.ReadFloat("D100"); // 读取D100-D101 txtValue.Text = temp.ToString(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btnWrite_Click(object sender, EventArgs e) { try { float newValue = float.Parse(txtValue.Text); plcComm.WriteFloat("D200", newValue); // 写入D200-D201 MessageBox.Show("写入成功"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } ``` ### 关键配置步骤 1. **组件引用** 在VS解决方案资源管理器中: - 右键"引用" → 添加引用 → COM → 搜索`ActMELib64` → 勾选`ActMELib64 Library` 2. **PLC参数设置** 使用MX Component自带的配置工具设置: - 逻辑站号(需代码中`ActLogicalStationNumber`一致) - 通讯协议(推荐MC协议) - PLC系列(Q/L/FX系列) - 端口参数(以太网/串口) 3. **寄存器地址规则** | PLC类 | 浮点地址示例 | 占用寄存器 | |---------|-------------|-----------| | FX系列 | D100 | D100-D101 | | Q/L系列 | D100 | D100-D101 | | 特殊模块 | U0\G100 | 2个连续字 | ### 注意事项 1. **字节序问题** 三菱PLC采用**大端字节序**(Big-Endian),PC系统通常为小端,必须进行字节反转操作(如示例中的`Array.Reverse()`)[^1]。 2. **错误处理** 所有MX Component方法返回0表示成功,其他值为错误码,可通过`plc.GetErrorMessage(result)`获取详细错误信息。 3. **数据类匹配** PLC中的浮点数必须为IEEE754标准的32位格式(三菱称REAL),验证方法: ```csharp // 检查PLC程序中的数据类声明 // 示例:D100 REAL (GX Works2中需明确定义) ``` 4. **通讯性能优化** - 批量读写时使用`ReadDeviceBlock2`/`WriteDeviceBlock2`方法 - 异步通信使用`ActSupport`类 - 保持TCP连接避免频繁重连
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值