上周五,下了班,老板找我让我把C#里的串口类(SerialPort)封装下,我当时没多想,封装就封装呗,反正这事儿我没干过,摸石头过河,顺便锻炼下自己的技术。周日没事儿,写了点儿。可写到datareceived的时候写不下去了。因为牵扯到协议的原因,实际使用的时候,SerialPort的datareceived都是自己实现的。这就意味着我得定义一个接口,使用的时候,还得继承我写的这个类,然后再对继承后的类实例化,然后才能使用。这兜了一大圈子又回来了,这不是白白的浪费了么。请大家积极发言,讨论下封装类的常规做法和封装c#的SerialPort类有无实际意义。
解决方案 »
- 数据库连接字符串
- 如何用WF实现用户登录
- datagrid 怎么给模板列中的下拉框赋值
- c# 调用webservice 时需要soapheder ? 怎么做(急!)
- Windows Moible下用代码删除所有短信和日历时间
- 使用SeialPort的串口通讯
- C#可以做嵌入式开发或是底层开发么?
- 请高手出招了。顶者有分,,,object Main 这地方怎么写呀。。。不对呀。
- 如何在C#中建立各個窗体都能使用的變量??
- 大神求指教!关于c#的文件下载。
- windows 7 64位操作系统,数据库为oralce 11g,vs2010不能连接上
- 成功获得前台Request的值,但是在绑定GridView的时候Request值用不了
我现在配合着用c#写点儿小程序。
个人觉得没有必要。
还不如把这几个方法写好,每次去调用呢。
这样,debug时也方便纠错。工作中:
还是很有必要的,老板的话永远是对的。如果某天他觉得不好用,你再给拆了也不费时。
方法
ExecuteCommand
//从上位机接收命令,然后发送到下位机。
//将参数按照规则转换为byte[]事件
HaveSomeData
//接收到下位机数据,通知上位机。
//将byte[]转换为结构或者类。这样下位机与上位机没有任何的直接关联。
封装产生的类,相当于一个翻译程序。
不同的协议可以用派生类实现。
接口不用定义,使用Action<>或Func<>就行
我觉得封装很有必要
SerialPort类本身之提供了串口的通信,如果你们公司自己有自己的通信协议,你封装的目的就是把自己的通信协议写进去。比如你说的CRC16,CRC32之类。
比如你们自己的协议里规定0x0d,0x0e是数据结尾,那么你就可以根据这个,等整个一个数据包都收完了再触发数据接收完成的事件,而不需要一个byte触发一次。
这样别人用你封装好的方法,接受到的就是完整的包,不需要自己再做其他处理了
SerialPortBase : ICommunication
{
}
TCPClientBase : ICommunication
{
}IProtocal 协议接口
{
ICommunication Communication{
get;
}
}
#region 字符串和字节数组相互转换
/// <summary>
/// 将字符串转换成16进制字节数组,并自动在字节数组后面加cs校验和
/// </summary>
/// <param name="_data">要转换的string</param>
/// <param name="byteArray">转换之后的字节数组</param>
/// <returns>为空则表示执行正确,否则,表示错误信息</returns>
public static string ChangeHexStringToByteArray(string _data, out byte[] byteArray)
{
string sResult = "";
byteArray = null;
if (_data == "")
{
sResult = "请不要传入空值。函数:ChangeHexStringToByteArray。";
}
else if (_data.Length % 2 != 0)
{
sResult = "请传入正确的十六进制字符串,字符串的个数必须是偶数个。函数:ChangeHexStringToByteArray。";
}
else
{
try
{
_data = _data.Replace(" ", "");
int sendLength = _data.Length / 2;
byteArray = new byte[sendLength];
string hexstring = "";
int k = 0;
for (int i = 0; i < _data.Length; )
{
hexstring = _data.Substring(i, 2);
int j;
j = int.Parse(hexstring, System.Globalization.NumberStyles.HexNumber);
byteArray[k] = (byte)j;
i += 2;
k++;
}
}
catch (Exception ex)
{
sResult = ex.Message;
}
}
return sResult;
}
/// <summary>
/// 将字节数组转换成十六进制字符串
/// </summary>
/// <param name="data">要转换的字节数组</param>
/// <param name="HexString">转换后的字符串</param>
/// <returns>为空则表示执行正确,否则,表示错误信息</returns>
public static string ChangeByteArrayToHexString(byte[] data, out string HexString)
{
string sResult = "";
HexString = "";
StringBuilder sb = new StringBuilder(data.Length * 3);
try
{
foreach (byte b in data)
sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
}
catch (Exception ex)
{
sResult = "将字节数组转换成字符串时出错,函数:ChangeByteArrayToHexString。异常信息:" + ex.Message;
}
HexString = sb.ToString().ToUpper();
return sResult;
} #endregion
/// <summary>
/// 对16进制数字的进行CRC16校验,然后把校验值返回
/// </summary>
/// <param name="str">要进行校验的数据</param>
/// <param name="CRC16Result">校验值(校验结果)</param>
/// <returns>为空则表示执行正确,否则,表示错误信息</returns>
public string GetCRC16ResultByHexString(string str,string CRC16Result)
{
ushort crcResult;
byte[] byArr;
string sResult = "";
CRC16Result = "";
try
{
sResult = ChangeHexStringToByteArray(str, out byArr);
if ((sResult == "") && (byArr != null))
{
sResult= CalculateCRC(byArr, byArr.Length, out crcResult);
if (sResult == "")
{
ushort h = (byte)(crcResult & 0xFF);
ushort l = (byte)((crcResult & 0xFF00) >> 8);
string height = Convert.ToString(h, 16);
string low = Convert.ToString(l, 16);
if (height.Length == 1)
height = height.Insert(0, "0");
if (low.Length == 1)
low = low.Insert(0, "0");
CRC16Result = low.ToUpper() + height.ToUpper();
}
}
}
catch (Exception ex)
{
sResult += ex.Message;
} return sResult;
} /// <summary>
/// crc16算法
/// </summary>
/// <param name="pByte">要校验的字节数组</param>
/// <param name="nNumberOfBytes">字节个数</param>
/// <param name="pChecksum">校验结果</param>
/// <returns>为空则表示执行正确,否则,表示错误信息</returns>
public static string CalculateCRC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
{
int nBit;
ushort nShiftedBit;
pChecksum = 0xFFFF;
string sResult = "";
if (nNumberOfBytes > pByte.Length)
{
sResult = "传入的参数nNumberOfBytes(字节个数)大于pByte(要校验的字节数组)的长度";
}
else
{
try
{
for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
{
pChecksum ^= pByte[nByte];
for (nBit = 0; nBit < 8; nBit++)
{
if ((pChecksum & 0x1) == 1)
{
nShiftedBit = 1;
}
else
{
nShiftedBit = 0;
}
pChecksum >>= 1;
if (nShiftedBit != 0)
{
pChecksum ^= 0xA001;
}
}
}
}
catch (Exception ex)
{
sResult = ex.Message;
}
}
return sResult;
}
/// <summary>
/// 计算累加校验和
/// </summary>
/// <param name="SendByteArray">要校验的字节数组</param>
/// <returns>对字节数组进行校验所得到的校验和</returns>
public static byte GetSumCS(byte[] SendByteArray)
{
byte rst = 0x00;
//计算累加和
for (int j = 2; j < SendByteArray.Length; j++)
{
unchecked
{
rst += SendByteArray[j];
}
}
//累加和计算结束
return rst;
}
#endregion