.Net平台下,微软已经把串口部分封装地非常好了,大多出场景下我们都直接用。
其中在接收串口数据的时候比较常见的有三种实现方式。
1.用串口封装的DataReceived事件,当串口接收到数据时,会触发这个回调函数,在回调函数中读出串口中的数据。
如下回调
private void _Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = sender as SerialPort;
if (sp == null) return;
int tmpBytesCount = sp.BytesToRead;
byte[] tmpData = new byte[tmpBytesCount];
int tmpRealDataCount = sp.Read(tmpData, 0, tmpBytesCount);
byte[] tmpValidData = null;
if (tmpRealDataCount == tmpBytesCount)
{
tmpValidData = tmpData;
}
else
{
tmpValidData = new byte[tmpRealDataCount];
Array.Copy(tmpData, 0, tmpValidData, 0, tmpRealDataCount);
}
logClass.WriteLog(LogFile.appData, string.Format("发送:{0}", BytesToStr(tmpValidData)));
if (DataReceiveEvent != null)
DataReceiveEvent(tmpValidData);
}
2.写死循环,不停地在串口中读取数据,如下代码
private void ReadDataPro()
{
int readCount = 0;
byte[] data;
byte[] buffer = new byte[2048];
Stream baseStream = _Serial.BaseStream;
baseStream.ReadByte();
while (ReadDataRunFlag)
{
if (_Serial == null || !_Serial.IsOpen) continue;
readCount = _Serial.Read(buffer, 0, buffer.Length);
if (readCount > 0)
{
data = new byte[readCount];
Array.Copy(buffer, 0, data, 0, data.Length);
if (DataReceiveEvent != null)
DataReceiveEvent(data);
}
else
{
Thread.Sleep(1);
}
}
}
3.拿到串口基础流,对流进行操作。对流进行操作时比较灵活,所有Steam的方法都可以实用,用这种方式可是实现更复杂的功能。
private void ReadDataBasePro()
{
int readCount = 0;
byte[] data;
byte[] buffer = new byte[2048];
Stream baseStream = _Serial.BaseStream;
while (ReadDataRunFlag)
{
if (_Serial == null || !_Serial.IsOpen) continue;
readCount = baseStream.Read(buffer, 0, buffer.Length);
if (readCount > 0)
{
data = new byte[readCount];
Array.Copy(buffer, 0, data, 0, data.Length);
if (DataReceiveEvent != null)
DataReceiveEvent(data);
}
else
{
Thread.Sleep(1);
}
}
}
二.unity中串口通讯
说明:小弟我是做C#的,unity 只是了解那么一丢丢。但是最近用到unity中的串口通讯,掉进了一些坑,在这里拿出来分享,以免用到相关知识的朋友走弯路。
1.经测试,DataReceived事件在unity中不触发。在unity中如果用DataReceived事件触发接收数据逻辑,会发现串口代码不报错,但是只能发送数据,不能接收数据,其实就是这个里在作祟,事件不触发,一直没有执行接收数据的代码。
2.BytesToRead方法会报错。所以在unity中不要使用这个方法来判断当前串口缓冲中有多少可用数据。而是直接使用 readCount = _Serial.Read(buffer, 0, buffer.Length);这个方法,通过返回值来判断。
3.当使用全双工通讯并且收发时间密集时,接收偶尔会丢失首个字节,这里需要把unity环境改外4.x
三.总结
通常把功能性相关类直接从.Net C#项目中移植到unity中,修改编译错误后,会遇到很多莫名其妙的运行中问题。
这是为什么呢?
今天没事看了一下,.net平台和unity框架 下的.net平台,他们所用的基础类库是不一样的。
比如说Unity 的system类库在我电脑上路径为D:\Program Files\Unity\Editor\Data\MonoBleedingEdge\lib\mono\4.7.1-api\System.dll
而标准.net下system类库为C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll
所以,虽然表面上类、方法、属性都一样,但是可能实现不一样,会导致各种运行中问题。