C#读写台达PLC源代码,分别操控D、M、X、Y、T寄存器的读写,代码注释详细、分类说明,附带文档有台达PLC与上位机通讯协议(逐条解释详细)、PLC各种寄存器通讯地与16进制对照表。 不需要再花时间精力研究台达PLC官方文档,直接套用。 适合赶项目又未接触过台达的老手和想学上位机的电气工程人员。
在项目开发中,快速上手读写台达 PLC 寄存器对老手和电气工程人员来说十分关键。今天就来给大家分享如何用 C# 操控台达 PLC 的 D、M、X、Y、T 寄存器,并详细解释通讯协议及寄存器地址对照。
台达 PLC 与上位机通讯协议
台达 PLC 与上位机采用特定通讯协议进行交互。以下是协议的逐条详细解释:
1. 通讯帧格式
通讯帧一般由起始字符、设备地址、功能码、数据区、校验码和结束字符组成。例如,起始字符可能为0x02,表示一帧数据的开始;结束字符如0x03,标志数据帧的结束。
2. 设备地址
每台 PLC 在网络中有唯一地址,范围通常是0x01 - 0x7F。通过这个地址,上位机可精准定位要通讯的 PLC 设备。比如地址0x01代表网络中的第一台 PLC。
3. 功能码
功能码决定了通讯的操作类型。像0x03功能码表示读取保持寄存器,0x10功能码表示写入多个保持寄存器。不同功能码对应不同的寄存器操作。
4. 数据区
存放具体要读写的数据内容。根据功能码和操作寄存器的不同,数据区的格式和长度也有差异。比如读取多个寄存器时,数据区会指定起始寄存器地址和寄存器数量。
5. 校验码
用于验证数据传输的正确性。常见的校验方式有 CRC16 校验。通过对通讯帧中除起始、结束字符外的数据进行计算得到校验码,接收方重新计算校验码并与接收到的校验码对比,一致则说明数据传输无误。
PLC 各种寄存器通讯地址与 16 进制对照表
| 寄存器类型 | 16 进制地址范围 | 说明 |
|---|---|---|
| D 寄存器 | 0x0000 - 0xFFFF | 数据寄存器,用于存储各种数据 |
| M 寄存器 | 0x0000 - 0xFFFF | 辅助继电器,常用于逻辑控制 |
| X 寄存器 | 0x0000 - 0xFFFF | 输入继电器,反映外部输入信号状态 |
| Y 寄存器 | 0x0000 - 0xFFFF | 输出继电器,控制外部输出设备 |
| T 寄存器 | 0x0000 - 0xFFFF | 定时器,用于定时控制 |
C# 代码实现
1. 引用必要的命名空间
using System; using System.IO.Ports; using System.Text;这里System.IO.Ports用于串口通讯,System.Text用于字符串编码转换。
2. 计算 CRC16 校验码
public static ushort CalculateCRC16(byte[] data) { ushort crc = 0xFFFF; foreach (byte b in data) { crc ^= b; for (int i = 0; i < 8; i++) { if ((crc & 0x0001)!= 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; }这段代码通过对传入的字节数组进行循环运算,得出 CRC16 校验码。
3. 发送串口数据
public static void SendData(string portName, byte[] data) { using (SerialPort serialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One)) { serialPort.Open(); serialPort.Write(data, 0, data.Length); serialPort.Close(); } }此方法通过指定的串口,以 9600 波特率、无校验位、8 位数据位和 1 位停止位发送数据。
4. 读取 D 寄存器
public static byte[] ReadDRegister(byte deviceAddress, ushort registerAddress, ushort registerCount) { byte[] data = new byte[8]; data[0] = 0x02; // 起始字符 data[1] = deviceAddress; data[2] = 0x03; // 读取保持寄存器功能码 data[3] = (byte)(registerAddress >> 8); data[4] = (byte)(registerAddress & 0xFF); data[5] = (byte)(registerCount >> 8); data[6] = (byte)(registerCount & 0xFF); ushort crc = CalculateCRC16(new ArraySegment<byte>(data, 1, 6).ToArray()); data[7] = (byte)(crc & 0xFF); data[8] = (byte)(crc >> 8); data[9] = 0x03; // 结束字符 SendData("COM1", data); // 这里可添加接收数据处理逻辑 return data; }该函数构建读取 D 寄存器的通讯帧,设置设备地址、功能码、寄存器起始地址和数量,计算校验码后发送数据。
5. 写入 D 寄存器
public static byte[] WriteDRegister(byte deviceAddress, ushort registerAddress, byte[] values) { int dataLength = 6 + values.Length; byte[] data = new byte[dataLength + 3]; data[0] = 0x02; data[1] = deviceAddress; data[2] = 0x10; // 写入多个保持寄存器功能码 data[3] = (byte)(registerAddress >> 8); data[4] = (byte)(registerAddress & 0xFF); data[5] = (byte)(values.Length >> 1); data[6] = (byte)(values.Length & 0xFF); Buffer.BlockCopy(values, 0, data, 7, values.Length); ushort crc = CalculateCRC16(new ArraySegment<byte>(data, 1, dataLength - 2).ToArray()); data[dataLength + 1] = (byte)(crc & 0xFF); data[dataLength + 2] = (byte)(crc >> 8); data[dataLength + 3] = 0x03; SendData("COM1", data); // 这里可添加接收数据处理逻辑 return data; }此函数用于写入 D 寄存器,根据传入的寄存器地址和要写入的值构建通讯帧,同样计算校验码并发送。
6. 读取 M 寄存器
M 寄存器的读取与 D 寄存器类似,只是功能码和地址对应不同。假设 M 寄存器读取功能码为0x01,代码如下:
public static byte[] ReadMRegister(byte deviceAddress, ushort registerAddress, ushort registerCount) { byte[] data = new byte[8]; data[0] = 0x02; data[1] = deviceAddress; data[2] = 0x01; // 读取 M 寄存器功能码 data[3] = (byte)(registerAddress >> 8); data[4] = (byte)(registerAddress & 0xFF); data[5] = (byte)(registerCount >> 8); data[6] = (byte)(registerCount & 0xFF); ushort crc = CalculateCRC16(new ArraySegment<byte>(data, 1, 6).ToArray()); data[7] = (byte)(crc & 0xFF); data[8] = (byte)(crc >> 8); data[9] = 0x03; SendData("COM1", data); // 这里可添加接收数据处理逻辑 return data; }7. 读取 X、Y、T 寄存器
读取 X、Y、T 寄存器也遵循类似的逻辑,根据各自的功能码和地址范围进行操作。例如读取 X 寄存器:
public static byte[] ReadXRegister(byte deviceAddress, ushort registerAddress, ushort registerCount) { byte[] data = new byte[8]; data[0] = 0x02; data[1] = deviceAddress; // 假设读取 X 寄存器功能码为 0x02 data[2] = 0x02; data[3] = (byte)(registerAddress >> 8); data[4] = (byte)(registerAddress & 0xFF); data[5] = (byte)(registerCount >> 8); data[6] = (byte)(registerCount & 0xFF); ushort crc = CalculateCRC16(new ArraySegment<byte>(data, 1, 6).ToArray()); data[7] = (byte)(crc & 0xFF); data[8] = (byte)(crc >> 8); data[9] = 0x03; SendData("COM1", data); // 这里可添加接收数据处理逻辑 return data; }通过以上内容,无论是赶项目的老手,还是想学习上位机的电气工程人员,都能快速掌握 C# 读写台达 PLC 寄存器的方法,希望对大家有所帮助!