一个类解决通讯问题
using System;using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
namespace MODBUS_通讯助手
{
public class ModbusHple
{
//新建一个串口对象
public static SerialPort sp = new SerialPort();
//查询结果
public byte[] bytes = new byte[1024];
/// <summary>
/// 获取可用的串口
/// </summary>
/// <returns></returns>
public List<string> GetCOM() {
List<string> list = new List<string>();
//检测串口是否存在
for (int i = 0; i < 30; i )
{
try
{
SerialPort sp = new SerialPort("COM" (i 1).ToString());
sp.Open();
sp.Close();
list.Add("COM" (i 1).ToString());
}
catch
{
continue;
}
}
return list;
}
/// <summary>
/// 设施串口参数并绑定事件
/// </summary>
private void setPortProperty(string cbxcomport, string cbxbaudrate, string cbxdatabit, string cbxstopbit, string cbxparity)
{
sp = new SerialPort();
sp.PortName = cbxcomport;//设置串口名
sp.BaudRate = Convert.ToInt32(cbxbaudrate); //设置波特率
sp.DataBits = Convert.ToInt32(cbxdatabit); //设置数据位
float f = Convert.ToSingle(cbxstopbit); //设置停止位
if (f == 0)
sp.StopBits = StopBits.None;
if (f == 1)
sp.StopBits = StopBits.One;
if (f == 1.5)
sp.StopBits = StopBits.OnePointFive;
if (f == 2)
sp.StopBits = StopBits.Two;
string property = cbxparity; //校验位设置
if (property == "无校验")
sp.Parity = Parity.None;
if (property == "奇校验")
sp.Parity = Parity.Odd;
if (property == "偶校验")
sp.Parity = Parity.Even;
sp.ReadTimeout = -1;
sp.RtsEnable = true;
//定义Recevied事件
sp.DataReceived = new SerialDataReceivedEventHandler(sp_DataRecevied);
sp.Open();
}
/// <summary>
/// 串口控件接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sp_DataRecevied(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(100);//延时100ms,等待接收数据完成
Byte[] ReceviedData = new Byte[sp.BytesToRead];
sp.Read(ReceviedData, 0, ReceviedData.Length);
//结果复制给全局变量
bytes = ReceviedData;
}
/// <summary>
/// 打开串口
/// </summary>
/// <param name="cbxcomport">串口 (例:COM1)</param>
/// <param name="cbxbaudrate">波特率 (例:9600)</param>
/// <param name="cbxdatabit">数据位 (例:8)</param>
/// <param name="cbxstopbit">停止位 (例:1)</param>
/// <param name="cbxparity">校验位 (例:无效验)</param>
public bool OpenPort(string cbxcomport, string cbxbaudrate, string cbxdatabit, string cbxstopbit, string cbxparity) {
#region 验证参数
if (cbxcomport==""|| cbxcomport == null ||
cbxbaudrate == "" || cbxcomport == null ||
cbxdatabit == "" || cbxdatabit == null ||
cbxstopbit == "" || cbxstopbit == null ||
cbxparity == "" || cbxparity == null)
{
return false;
}
#endregion
if (sp.IsOpen == false)
{
setPortProperty(cbxcomport, cbxbaudrate, cbxdatabit, cbxstopbit, cbxparity);
}
return sp.IsOpen;
}
/// <summary>
/// 获取数据(获取10个值)
/// </summary>
/// <param name="strstationnum1">站号</param>
/// <returns></returns>
public bool 获取数据(string strstationnum1)
{
#region 验证参数
if (strstationnum1 == "" || strstationnum1 == null|| sp.IsOpen == false)
{
return false;
}
#endregion
//站号
string strstationnum = strstationnum1;
//模式
string strfunctioncode = "03";
//起始位
string straddress = "0000";
//数量位
string straddrsize = "000A";
string senddatas1 = "";
string senddatas2 = "";
int len1 = straddress.Length;
int len2 = straddrsize.Length;
string addr1 = "";
string addrsize1 = "";
for (int a = 0; a < len1; a = a 2) //地址加上空格
{
string addr2 = straddress.Substring(a, 2);
addr1 = addr1 " " addr2;
}
for (int a = 0; a < len2; a = a 2) //地址数量加上空格
{
string addrsize2 = straddrsize.Substring(a, 2);
addrsize1 = addrsize1 " " addrsize2;
}
//模式
senddatas2 = strstationnum " " strfunctioncode addr1 addrsize1;
//MODBUS RTU模式CRC校验计算
string[] datas = senddatas2.Split(' '); //去掉空格
List<byte> bytedata = new List<byte>();
foreach (string str in datas)
{
bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
}
byte[] crcbuf = bytedata.ToArray();
//计算并填写CRC校验
int crc = 0xffff;
int len = crcbuf.Length;
for (int n = 0; n < len; n )
{
byte i;
crc = crc ^ crcbuf[n];
for (i = 0; i < 8; i )
{
int tt;
tt = crc & 1;
crc = crc >> 1;
crc = crc & 0x7fff;
if (tt == 1)
{
crc = crc ^ 0xa001;
}
crc = crc & 0xffff;
}
}
string[] redata = new string[2];
redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);
redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);
if (redata[0].Length == 1)
{
redata[0] = "0" redata[0];
}
if (redata[1].Length == 1)
{
redata[1] = "0" redata[1];
}
senddatas1 = senddatas2 " " redata[0] " " redata[1];
//发送hex
string strSend = senddatas1;
string sendBuf = strSend;
string sendnoNull = sendBuf.Trim();
string sendNOComma = sendnoNull.Replace(',', ' '); //去掉英文逗号
string sendNOComma1 = sendNOComma.Replace(',', ' '); //去掉中文逗号
string strSendNoComma2 = sendNOComma1.Replace("0x", ""); //去掉0x
strSendNoComma2.Replace("0X", ""); //去掉0X
string[] strArray = strSendNoComma2.Split(' ');
int byteBufferLength = strArray.Length;
for (int i = 0; i < strArray.Length; i )
{
if (strArray[i] == "")
{
byteBufferLength--;
}
}
byte[] byteBuffer = new byte[byteBufferLength];
int ii = 0;
for (int i = 0; i < strArray.Length; i )
{
Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);
int decNum = 0;
if (strArray[i] == "")
{
continue;
}
else
{
decNum = Convert.ToInt32(strArray[i], 16);
}
try
{
byteBuffer[ii] = Convert.ToByte(decNum);
}
catch
{
return false;
}
ii ;
}
sp.Write(byteBuffer, 0, byteBuffer.Length);
return true;
}
/// <summary>
/// 修改数据(修改10个值)
/// </summary>
/// <param name="strstationnum1">站号</param>
/// <param name="strdatas1">数据</param>
/// <returns></returns>
public bool 修改数据(string strstationnum1,string strdatas1)
{
#region 参数验证
if (strstationnum1==""|| strstationnum1==null||
strdatas1==""|| strdatas1==null||
strdatas1.Length!=40 || sp.IsOpen == false)
{
return false;
}
#endregion
//站号
string strstationnum = strstationnum1;
//模式
string strfunctioncode = "10";
//起始位
string straddress = "0000";
//数量位
string straddrsize = "000A";
//字节数
string strbytenum = "14";
//数据
string strdatas = strdatas1;
string senddatas1 = "";
string senddatas2 = "";
int len1 = straddress.Length;
int len2 = straddrsize.Length;
int len3 = strdatas.Length;
int len4 = strbytenum.Length;
string addr1 = "";
string addrsize1 = "";
string datas1 = "";
string bytenum1 = "";
for (int a = 0; a < len1; a = a 2) //地址加上空格
{
string addr2 = straddress.Substring(a, 2);
addr1 = addr1 " " addr2;
}
for (int a = 0; a < len2; a = a 2) //地址数量加上空格
{
string addrsize2 = straddrsize.Substring(a, 2);
addrsize1 = addrsize1 " " addrsize2;
}
for (int a = 0; a < len3; a = a 2) //数据加上空格
{
string datas2 = strdatas.Substring(a, 2);
datas1 = datas1 " " datas2;
}
for (int a = 0; a < len4; a = a 2) //字节数加上空格
{
string bytenum2 = strbytenum.Substring(a, 2);
bytenum1 = bytenum1 " " bytenum2;
}
//模式
senddatas2 = strstationnum " " strfunctioncode addr1 addrsize1 bytenum1 datas1;
//MODBUS RTU模式CRC校验计算
string[] datas = senddatas2.Split(' '); //去掉空格
List<byte> bytedata = new List<byte>();
foreach (string str in datas)
{
bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
}
byte[] crcbuf = bytedata.ToArray();
//计算并填写CRC校验
int crc = 0xffff;
int len = crcbuf.Length;
for (int n = 0; n < len; n )
{
byte i;
crc = crc ^ crcbuf[n];
for (i = 0; i < 8; i )
{
int tt;
tt = crc & 1;
crc = crc >> 1;
crc = crc & 0x7fff;
if (tt == 1)
{
crc = crc ^ 0xa001;
}
crc = crc & 0xffff;
}
}
string[] redata = new string[2];
redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);
redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);
if (redata[0].Length == 1)
{
redata[0] = "0" redata[0];
}
if (redata[1].Length == 1)
{
redata[1] = "0" redata[1];
}
senddatas1 = senddatas2 " " redata[0] " " redata[1];
//发送hex
string strSend = senddatas1;
string sendBuf = strSend;
string sendnoNull = sendBuf.Trim();
string sendNOComma = sendnoNull.Replace(',', ' '); //去掉英文逗号
string sendNOComma1 = sendNOComma.Replace(',', ' '); //去掉中文逗号
string strSendNoComma2 = sendNOComma1.Replace("0x", ""); //去掉0x
strSendNoComma2.Replace("0X", ""); //去掉0X
string[] strArray = strSendNoComma2.Split(' ');
int byteBufferLength = strArray.Length;
for (int i = 0; i < strArray.Length; i )
{
if (strArray[i] == "")
{
byteBufferLength--;
}
}
byte[] byteBuffer = new byte[byteBufferLength];
int ii = 0;
//对获取的字符做相加运算
for (int i = 0; i < strArray.Length; i )
{
Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);
int decNum = 0;
if (strArray[i] == "")
continue;
decNum = Convert.ToInt32(strArray[i], 16);
try
{
byteBuffer[ii] = Convert.ToByte(decNum);
}
catch
{
return false;
}
ii ;
}
sp.Write(byteBuffer, 0, byteBuffer.Length);
return true;
}
/// <summary>
/// 通用发送
/// </summary>
/// <param name="strstationnum">站号</param>
/// <param name="tbxfunctioncode">模式(01:获取数据 02:获取数据 03:获取数据 05:置位 06:置位 10:设置数据 0F:设置数据)</param>
/// <param name="straddress">起始位(双字节4位)</param>
/// <param name="straddrsize">数量位(双字节4位)</param>
/// <param name="strbytenum">字节数(单字节2位)</param>
/// <param name="strdatas">数据位(多字节 数量位*4 )</param>
/// <returns></returns>
public bool 通用发送(string strstationnum,string tbxfunctioncode,string straddress,string straddrsize,string strbytenum,string strdatas)
{
#region 参数验证
int nsfasgf = (Convert.ToInt32(straddrsize, 16) * 4);
if (sp.IsOpen == false||tbxfunctioncode.Length!=2|| straddress.Length!=4
|| straddrsize.Length != 4 || strbytenum.Length != 2
|| strdatas.Length != (Convert.ToInt32(straddrsize, 16) * 4))
{
return false;
}
#endregion
string senddatas1 = "";
string senddatas2 = "";
int len1 = straddress.Length;
int len2 = straddrsize.Length;
int len3 = strdatas.Length;
int len4 = strbytenum.Length;
string addr1 = "";
string addrsize1 = "";
string datas1 = "";
string bytenum1 = "";
for (int a = 0; a < len1; a = a 2) //地址加上空格
{
string addr2 = straddress.Substring(a, 2);
addr1 = addr1 " " addr2;
}
for (int a = 0; a < len2; a = a 2) //地址数量加上空格
{
string addrsize2 = straddrsize.Substring(a, 2);
addrsize1 = addrsize1 " " addrsize2;
}
for (int a = 0; a < len3; a = a 2) //数据加上空格
{
string datas2 = strdatas.Substring(a, 2);
datas1 = datas1 " " datas2;
}
for (int a = 0; a < len4; a = a 2) //字节数加上空格
{
string bytenum2 = strbytenum.Substring(a, 2);
bytenum1 = bytenum1 " " bytenum2;
}
if (tbxfunctioncode == "01" | tbxfunctioncode == "02" | tbxfunctioncode == "03") //
{
senddatas2 = strstationnum " " tbxfunctioncode addr1 addrsize1;
}
if (tbxfunctioncode == "05" | tbxfunctioncode == "06") //置位
{
senddatas2 = strstationnum " " tbxfunctioncode addr1 datas1;
}
if (tbxfunctioncode == "0F" | tbxfunctioncode == "10")
{
senddatas2 = strstationnum " " tbxfunctioncode addr1 addrsize1 bytenum1 datas1;
}
//MODBUS RTU模式CRC校验计算
string[] datas = senddatas2.Split(' '); //去掉空格
List<byte> bytedata = new List<byte>();
string str1 = "";
foreach (string str in datas)
{
bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
str1 = str;
}
byte[] crcbuf = bytedata.ToArray();
//计算并填写CRC校验
int crc = 0xffff;
int len = crcbuf.Length;
for (int n = 0; n < len; n )
{
byte i;
crc = crc ^ crcbuf[n];
for (i = 0; i < 8; i )
{
int tt;
tt = crc & 1;
crc = crc >> 1;
crc = crc & 0x7fff;
if (tt == 1)
{
crc = crc ^ 0xa001;
}
crc = crc & 0xffff;
}
}
string[] redata = new string[2];
redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);
redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);
if (redata[0].Length == 1)
{
redata[0] = "0" redata[0];
}
if (redata[1].Length == 1)
{
redata[1] = "0" redata[1];
}
senddatas1 = senddatas2 " " redata[0] " " redata[1];
//发送hex
string strSend = senddatas1;
string sendBuf = strSend;
string sendnoNull = sendBuf.Trim();
string sendNOComma = sendnoNull.Replace(',', ' '); //去掉英文逗号
string sendNOComma1 = sendNOComma.Replace(',', ' '); //去掉中文逗号
string strSendNoComma2 = sendNOComma1.Replace("0x", ""); //去掉0x
strSendNoComma2.Replace("0X", ""); //去掉0X
string[] strArray = strSendNoComma2.Split(' ');
int byteBufferLength = strArray.Length;
for (int i = 0; i < strArray.Length; i )
{
if (strArray[i] == "")
{
byteBufferLength--;
}
}
byte[] byteBuffer = new byte[byteBufferLength];
int ii = 0;
//对获取的字符做相加运算
for (int i = 0; i < strArray.Length; i )
{
Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);
int decNum = 0;
if (strArray[i] == "")
continue;
decNum = Convert.ToInt32(strArray[i], 16); //atrArray[i] == 12时,temp == 18
try //防止输错,使其只能输入一个字节的字符
{
byteBuffer[ii] = Convert.ToByte(decNum);
}
catch
{
return false;
}
ii ;
}
sp.Write(byteBuffer, 0, byteBuffer.Length);
return true;
}
}
}
评论