实例介绍
【实例简介】
【实例截图】
【实例截图】
【核心代码】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Drawing;
public class XinJie //信捷PLC通信协议
{
SerialPort Port = new SerialPort();
private int PortBusy;
private byte cmdType;
public object LockcomportObj = new object();
private int returnValue;
private int dataCnt = 1;
private int[] returnArr;
public double comErrorCnt = 0;
public bool bConnection = false;
public string comStatus = "OK";
private byte modbus = 0x01;
public bool readM(int address, out bool M)
{
int[] re = new int[0];
bool result;
result = comPLC(0x01, address, 1, 1, ref re);
if (result == true)
{
if (re[0] == 1) M = true;
else M = false;
return true;
}
else
{
M = false;
return false;
}
}
public bool writeM(int address, bool state)
{
int[] re = new int[0];
bool result;
if (state == true)
{
result = comPLC(0x05, address, 1, 1, ref re);
}
else
{
result = comPLC(0x05, address, 0, 1, ref re);
}
if (result == true)
{
return true;
}
else
{
return false;
}
}
public bool writeHM(int address, bool state)
{
int[] re = new int[0];
bool result;
if (state == true)
{
result = comPLC(0x105, address, 1, 1, ref re);
}
else
{
result = comPLC(0x105, address, 0, 1, ref re);
}
if (result == true)
{
return true;
}
else
{
return false;
}
}
public bool readSingleD(int address, out int Data)
{
bool result;
int[] re;
re = new int[0];
result = comPLC(0x03, address, 1, 1, ref re);
if (result == true)
{
Data = re[0];
return true;
}
else
{
Data = 0;
return false;
}
}
public bool readDoubleD(int address, out int Data)
{
bool result;
int[] re;
re = new int[0];
result = comPLC(0x20, address, 1, 1, ref re);
if (result == true)
{
Data = re[0];
return true;
}
else
{
Data = 0;
return false;
}
}
public bool readMultipleD(int address, int cnt, out int[] Data)
{
bool result;
int[] re;
re = new int[0];
result = comPLC(0x20, address, 1, cnt, ref re);
if (result == true)
{
Data = re;
return true;
}
else
{
Data = new int[0];
return false;
}
}
//public bool writeSingleD(int address, int state)
//{
// bool result;
// int[] re;
// re = new int[0];
// result = comPLC(0x10, address, state, 1, ref re);
// return true;
//}
public bool writeDoubleD(int address, int state)
{
bool result;
int[] re;
re = new int[0];
result = comPLC(0x10, address, state, 1, ref re);
if (result == true)
{
return true;
}
else
{
return false;
}
}
public bool writeDoubleHD(int address, int state)
{
bool result;
int[] re;
re = new int[0];
result = comPLC(0x110, address, state, 1, ref re);
if (result == true)
{
return true;
}
else
{
return false;
}
}
public XinJie()
{
this.Port.DataReceived = new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);
}
public void OpenPort(int PortID, int BaudRate)
{
try
{
Port.PortName = "COM" PortID.ToString(); //选择COM端口
Port.BaudRate = BaudRate; //设置波特率
Port.DataBits = 8; //设置每个字节的标准数据位长度
Port.StopBits = StopBits.One; //设置每个字节的标准停止位数
Port.Parity = Parity.Even; //设置奇偶校验检查协议
Port.ReadBufferSize = 2048; //设置输入缓冲区的大小
Port.WriteBufferSize = 2048; //设置输出缓冲区的大小
Port.ReadTimeout = 500; //设置读取操作未完成时发生超时之前的毫秒数
Port.WriteTimeout = 500; //设置写入操作未完成时发生超时之前的毫秒数
Port.ReceivedBytesThreshold = 5; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Open();
PortBusy = 0;
}
catch (Exception ex)
{
//MessageBox.Show("COM" PortID.ToString() "打开失败!");
}
}
public void ClosePort()
{
Port.Close();
}
public bool comPLC(int type, int address, int state, int DataCnt, ref int[] result)
{
lock (LockcomportObj)
{
byte[] Mdata = new byte[30];
uint crcbuf;
try
{
if (DataCnt < 1) throw new Exception();
dataCnt = DataCnt;//先声明读数据长度
int returnData = -1;
result = new int[DataCnt];
while (PortBusy != 0)//如果串口被占用,则等待
{
Application.DoEvents();
}
int resendCnt;
DateTime sendtime = DateTime.Now;
PortBusy = 1;
resendCnt = 1;
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
switch (type)
{
case 0x01://读单个线圈状态
#region 读单个线圈状态
cmdType = 0x01;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x01;//功能码
Mdata[2] = Convert.ToByte(address >> 8); ;//线圈起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//线圈起始地址低位
Mdata[4] = 0x00;//数据总位数高位
Mdata[5] = 0x10;//数据总位数低位
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 7; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 2)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done1;
}
}
}
result[0] = returnArr[0];
returnData = 1;
Done1:
#endregion
break;
case 0x03://读单个寄存器
#region 读单个寄存器
cmdType = 0x03;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x03;//功能码 写多个寄存器
Mdata[2] = Convert.ToByte(address >> 8); //起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//起始地址地位
Mdata[4] = 0x00;//寄存器总数高位
Mdata[5] = 0x01;//寄存器总数低位 1
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 7; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 2)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done3;
}
}
}
result[0] = returnArr[0];
returnData = 1;
Done3:
#endregion
break;
case 0x05://强制写单个线圈
#region 强制写单个线圈
cmdType = 0x05;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x05;//功能码 强制单个线圈
Mdata[2] = Convert.ToByte(address >> 8); ;//线圈地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//线圈地址地位
if (state == 0)
{
Mdata[4] = 0x00;//强制OFF
Mdata[5] = 0x00;
}
else
{
Mdata[4] = 0xFF;//强制ON
Mdata[5] = 0x00;
}
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 8; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 3)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done5;
}
}
}
returnData = 1;
Done5:
#endregion
break;
case 0x10://强制写双个寄存器
#region 强制写双个寄存器
cmdType = 0x10;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x10;//功能码 写多个寄存器
Mdata[2] = Convert.ToByte(address >> 8); //起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//起始地址地位
Mdata[4] = 0x00;//寄存器总数高位
Mdata[5] = 0x02;//寄存器总数低位 2
Mdata[6] = 0x04;//寄存数总字节数 4byte
Mdata[7] = Convert.ToByte(((state & 0xFFFF) >> 8) & 0xFF); //D0
Mdata[8] = Convert.ToByte((state & 0xFFFF) & 0xFF);
Mdata[9] = Convert.ToByte(((state >> 16) >> 8) & 0xFF); //D1
Mdata[10] = Convert.ToByte((state >> 16) & 0xFF);
crcbuf = CRC16(Mdata, 11);
Mdata[11] = Convert.ToByte(crcbuf & 0xFF);
Mdata[12] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 8; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 13);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 5)//超时最多连续发送5次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 13);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done10;
}
}
}
returnData = 1;
Done10:
#endregion
break;
case 0x20://读多个寄存器
#region 读多个寄存器
cmdType = 0x20;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x03;//功能码 写多个寄存器
Mdata[2] = Convert.ToByte(address >> 8); //起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//起始地址地位
Mdata[4] = 0x00;//寄存器总数高位
Mdata[5] = Convert.ToByte(DataCnt * 2);//寄存器总数低位
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 5 4 * DataCnt; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 2)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done3;
}
}
}
result = returnArr;
returnData = 1;
Done20:
#endregion
break;
//XDplc
case 0x101://读单个线圈状态-HM
#region 读单个线圈状态
cmdType = 0x01;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x01;//功能码
address = 49408;
Mdata[2] = Convert.ToByte(address >> 8); ;//线圈起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//线圈起始地址低位
Mdata[4] = 0x00;//数据总位数高位
Mdata[5] = 0x10;//数据总位数低位
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 7; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 2)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done101;
}
}
}
result[0] = returnArr[0];
returnData = 1;
Done101:
#endregion
break;
case 0x103://读单个寄存器-HD
#region 读单个寄存器
cmdType = 0x03;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x03;//功能码 写多个寄存器
address = 41088;
Mdata[2] = Convert.ToByte(address >> 8); //起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//起始地址地位
Mdata[4] = 0x00;//寄存器总数高位
Mdata[5] = 0x01;//寄存器总数低位 1
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 7; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 2)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done103;
}
}
}
result[0] = returnArr[0];
returnData = 1;
Done103:
#endregion
break;
case 0x105://强制写单个线圈-HM
#region 强制写单个线圈
cmdType = 0x05;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x05;//功能码 强制单个线圈
address = 49408;
Mdata[2] = Convert.ToByte(address >> 8); ;//线圈地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//线圈地址地位
if (state == 0)
{
Mdata[4] = 0x00;//强制OFF
Mdata[5] = 0x00;
}
else
{
Mdata[4] = 0xFF;//强制ON
Mdata[5] = 0x00;
}
crcbuf = CRC16(Mdata, 6);
Mdata[6] = Convert.ToByte(crcbuf & 0xFF);
Mdata[7] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 8; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 8);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 3)//超时最多连续发送2次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 8);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done105;
}
}
}
returnData = 1;
Done105:
#endregion
break;
case 0x110://强制写双个寄存器-HD
#region 强制写双个寄存器
cmdType = 0x10;
Mdata[0] = modbus;//modbus站号
Mdata[1] = 0x10;//功能码 写多个寄存器
address = 41088;
Mdata[2] = Convert.ToByte(address >> 8); //起始地址高位
Mdata[3] = Convert.ToByte(address & 0xFF);//起始地址地位
Mdata[4] = 0x00;//寄存器总数高位
Mdata[5] = 0x02;//寄存器总数低位 2
Mdata[6] = 0x04;//寄存数总字节数 4byte
Mdata[7] = Convert.ToByte(((state & 0xFFFF) >> 8) & 0xFF); //D0
Mdata[8] = Convert.ToByte((state & 0xFFFF) & 0xFF);
Mdata[9] = Convert.ToByte(((state >> 16) >> 8) & 0xFF); //D1
Mdata[10] = Convert.ToByte((state >> 16) & 0xFF);
crcbuf = CRC16(Mdata, 11);
Mdata[11] = Convert.ToByte(crcbuf & 0xFF);
Mdata[12] = Convert.ToByte(crcbuf >> 8);
Port.ReceivedBytesThreshold = 8; //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
Port.Write(Mdata, 0, 13);
resendCnt = 1;
while (PortBusy != 0)
{
if (sendtime.AddMilliseconds(100) < DateTime.Now)//串口通讯超时
{
if (resendCnt < 5)//超时最多连续发送5次
{
Port.DiscardInBuffer();//清空接收缓冲区
Port.DiscardOutBuffer();
Port.Write(Mdata, 0, 13);
sendtime = DateTime.Now;
resendCnt = resendCnt 1;
}
else
{
returnData = -1;
goto Done110;
}
}
}
returnData = 1;
Done110:
#endregion
break;
default:
returnData = -1;
break;
}
PortBusy = 0;
if (returnData == -1)
{
comErrorCnt ;
comStatus = "NG";
return false;
}
else
{
comStatus = "OK";
return true;
}
}
catch (Exception ex)
{
result = new int[1];
PortBusy = 0;
comErrorCnt ;
comStatus = "NG";
return false;
}
}
}
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] readBuf = new byte[Port.ReadBufferSize];//返回字节数据
int readcnt = Port.Read(readBuf, 0, Port.ReadBufferSize);
//uint readcrc;
//byte readcrcHi, readcrcLo;
//readcrc = CRC16(readBuf, readcnt - 2);
//readcrcHi = Convert.ToByte(readcrc & 0xFF);
//readcrcLo = Convert.ToByte(readcrc >> 8);
//if ((readcrcHi == readBuf[readcnt - 2]) & (readcrcLo == readBuf[readcnt - 1]))//CRC校验码正确
if (readBuf[0] == modbus)//modbus站号正确
{
switch (cmdType)//功能码
{
case 0x01://读单个线圈状态
if ((readBuf[1] == cmdType) && (readcnt >= (7 - 2)))//功能码正确并且返回字节长度
{
if ((readBuf[3] & 0x0001) == 0x01)
{
returnValue = 1;
returnArr = new int[dataCnt];
returnArr[0] = returnValue;
PortBusy = 0;
}
if ((readBuf[3] & 0x0001) == 0x00)
{
returnValue = 0;
returnArr = new int[dataCnt];
returnArr[0] = returnValue;
PortBusy = 0;
}
}
break;
case 0x03://读单个寄存器
if ((readBuf[1] == cmdType) && (readcnt >= (7 - 2)))//功能码正确并且返回字节长度正确
{
returnValue = readBuf[3] * 256 readBuf[4] * 1;
if (returnValue >= 32768)
{
returnValue = returnValue - 65536;
}
returnArr = new int[dataCnt];
returnArr[0] = returnValue;
PortBusy = 0;
}
break;
case 0x05://强制写单个线圈
if ((readBuf[1] == cmdType) && (readcnt >= (8 - 2)))//功能码正确并且返回字节长度正确
{
PortBusy = 0;
}
break;
case 0x10://强制写双个寄存器
if ((readBuf[1] == cmdType) && (readcnt >= (8 - 2)))//功能码正确并且返回字节长度正确
{
PortBusy = 0;
}
break;
case 0x20://读取多个寄存器
if ((readBuf[1] == 0x03) && (readcnt >= (5 4 * dataCnt - 2)))//功能码正确并且返回字节长度正确
{
returnArr = new int[dataCnt];
for (int i = 0; i < dataCnt; i )
{
long d0 = readBuf[3 i * 4] * 256 readBuf[4 i * 4] * 1;
long d1 = readBuf[5 i * 4] * 256 readBuf[6 i * 4] * 1;
double dd = d1 * 65536 d0;
if (dd >= 2147483648)
{
dd = dd - 2147483648 - 2147483648;
}
returnArr[i] = Convert.ToInt32(dd);
}
PortBusy = 0;
}
break;
default:
break;
}
}
}
catch (Exception ex)
{
}
}
private uint CRC16(byte[] cmdstring, int lenstring)
{
int i, j;
uint tmp;
uint crc = 0xFFFF;
for (i = 0; i < lenstring; i )
{
crc = crc ^ cmdstring[i];
for (j = 0; j < 8; j )
{
tmp = crc & 0x0001;
crc = crc >> 1;
if (tmp == 1)
{
crc = crc ^ 0xA001;
}
}
}
return (crc);
}
}
好例子网口号:伸出你的我的手 — 分享!
网友评论
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


支持(0) 盖楼(回复)