1.下载汇川plc通讯API,然后下载文件,如下图:
解压上面下载的文件夹,在项目实例中找到两个动态链接库(ModbusTcpAPI.dll;StandardModbusApi.dll),如下图:
2.创建汇川PLC通讯测试项目,我用的VS2019软件,将上面的两个动态链接库(ModbusTcpAPI.dll;StandardModbusApi.dll)复制到创建的项目下,如图:
项目开发,UI界面如图:
通讯类SvMitsubishiEASY,代码如下:
public class SvMitsubishiEASY { #region //标准库 [DllImport("StandardModbusApi.dll", EntryPoint = "Init_ETH_String", CallingConvention = CallingConvention.Cdecl)] //连接PLC public static extern bool Init_ETH_String(string sIpAddr, int nNetId = 0, int IpPort = 502); [DllImport("StandardModbusApi.dll", EntryPoint = "Exit_ETH", CallingConvention = CallingConvention.Cdecl)] //关闭连接 public static extern bool Exit_ETH(int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Write_Soft_Elem", CallingConvention = CallingConvention.Cdecl)] public static extern int H5u_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Read_Soft_Elem", CallingConvention = CallingConvention.Cdecl)] public static extern int H5u_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Read_Device_Block", CallingConvention = CallingConvention.Cdecl)] public static extern int H5u_Read_Device_Block(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Write_Device_Block", CallingConvention = CallingConvention.Cdecl)] public static extern int H5u_Write_Device_Block(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H3u_Read_Soft_Elem", CallingConvention = CallingConvention.Cdecl)] public static extern int H3u_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); [DllImport("StandardModbusApi.dll", EntryPoint = "H3u_Write_Soft_Elem", CallingConvention = CallingConvention.Cdecl)] public static extern int H3u_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0); #endregion int nNetId = 1; public void Initial(string ip, int port) { bool result = Init_ETH_String(ip, nNetId, port); if (result == true) { MessageBox.Show("连接成功"); } else { MessageBox.Show("连接失敗"); } } public void Close() { bool result = Exit_ETH(nNetId); if (result == true) { MessageBox.Show("关闭连接成功"); } else { MessageBox.Show("关闭连接失敗"); } } public void ReadBlock16(string startAddress, ref short[] addressValues) { var addrType = startAddress.Substring(0, 1); var startAddr = Convert.ToInt32(startAddress.Substring(1, startAddress.Length - 1)); byte[] pBuf = new byte[16000]; int nCount = addressValues.Length; int nRet = H3u_Read_Soft_Elem(GetAddrTypeByte(addrType), startAddr, nCount, pBuf, nNetId); for (int i = 0; i < addressValues.Length; i++) { addressValues[i] = pBuf[i]; } } public void WriteBlock16(string startAddress, short[] addressValues) { var addrType = startAddress.Substring(0, 1); var startAddr = Convert.ToInt32(startAddress.Substring(1, startAddress.Length - 1)); int nCount = addressValues.Length; var sendByte = new List<byte>(); for (int i = 0; i < addressValues.Length; i++) { sendByte.AddRange(BitConverter.GetBytes(addressValues[i])); } int nRet = H3u_Write_Soft_Elem(GetAddrTypeByte(addrType), startAddr, nCount, sendByte.ToArray(), nNetId); } private SoftElemType GetAddrTypeByte(string addrType) { switch (addrType) { case "X": return SoftElemType.REGI_H3U_X; case "Y": return SoftElemType.REGI_H3U_Y; case "M": return SoftElemType.REGI_H3U_M; case "D": return SoftElemType.REGI_H3U_DW; case "R": return SoftElemType.REGI_H3U_R; default: return SoftElemType.REGI_H3U_SM; } } } public enum SoftElemType { //AM600 ELEM_QX = 0, //QX元件 ELEM_MW = 1, //MW元件 ELEM_X = 2, //X元件(对应QX200~QX300) ELEM_Y = 3, //Y元件(对应QX300~QX400) //H3U REGI_H3U_Y = 0x20, //Y元件的定义 REGI_H3U_X = 0x21,//X元件的定义 REGI_H3U_S = 0x22,//S元件的定义 REGI_H3U_M = 0x23,//M元件的定义 REGI_H3U_TB = 0x24,//T位元件的定义 REGI_H3U_TW = 0x25,//T字元件的定义 REGI_H3U_CB = 0x26,//C位元件的定义 REGI_H3U_CW = 0x27,//C字元件的定义 REGI_H3U_DW = 0x28,//D字元件的定义 REGI_H3U_CW2 = 0x29, //C双字元件的定义 REGI_H3U_SM = 0x2a,//SM REGI_H3U_SD = 0x2b,// REGI_H3U_R = 0x2c,// //H5u REGI_H5U_Y = 0x30, //Y元件的定义 REGI_H5U_X = 0x31,//X元件的定义 REGI_H5U_S = 0x32,//S元件的定义 REGI_H5U_M = 0x33,//M元件的定义 REGI_H5U_B = 0x34, //B元件的定义 REGI_H5U_D = 0x35, //D字元件的定义 REGI_H5U_R = 0x36, //R字元件的定义 }
实例调用代码:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } SvMitsubishiEASY PLC_EASY = new SvMitsubishiEASY(); //连接PLC private void button1_Click(object sender, EventArgs e) { var ip = textBox1.Text.Trim(); var port = Convert.ToInt32(textBox2.Text.Trim()); PLC_EASY.Initial(ip, port); } //断开PLC连接 private void button4_Click(object sender, EventArgs e) { PLC_EASY.Close(); } //读取数据 private void button2_Click(object sender, EventArgs e) { var addrass = textBox3.Text.Trim(); textBox4.Text=ReadSingle32(addrass).ToString(); } //写入数据 private void button3_Click(object sender, EventArgs e) { var addrass = textBox3.Text.Trim(); var value = Convert.ToInt32(textBox4.Text.Trim()); WriteSingle16(addrass, value); } public int ReadSingle32(string address) { try { var temp = new short[2]; PLC_EASY.ReadBlock16(address, ref temp); var tempByte = new List<byte>(); tempByte.AddRange(BitConverter.GetBytes(temp[0])); tempByte.AddRange(BitConverter.GetBytes(temp[1])); return BitConverter.ToInt32(tempByte.ToArray(), 0); } catch (Exception ex) { MessageBox.Show("PLC Read Fail:" + address); return -999; } } public bool WriteSingle16(string address, int value) { try { var temp = new short[] { (short)value }; PLC_EASY.WriteBlock16(address, temp); return true; } catch (Exception ex) { MessageBox.Show("PLC Read Fail:" + address); return false; } } }
本篇文章主要介绍汇川PLC通讯开发实例,实例项目用的H3U系列通讯,目前只能读取写入整数,其他还未研究,可以读取写入X,Y,M,D,R码。