第一次在csdn上写文章,各种格式之类的完全不熟悉,请见谅。 串口是用来做pc端中控程序与硬件对接的,本来嘛,可以用c++或者vs的wpf这些来做的,但实际上做出来的界面比较丑,很难做得好,也试过用flash加载ane来做串口,但flash貌似有可能被淘汰了,所以现在选择用unity来做中控程序界面试试,感觉有点大材小用了。
一开始以为unity可以采用c#编程,那么串口就应该不会有什么问题了,但其实不是,unity貌似对串口支持不算很好,会出现各种意想不到的事情。测试了几个,才找到一个可以使用的代码,链接如下:http://www.cnblogs.com/zhaozhengling/p/3696251.html,采用两个线程一个接收,一个处理。但在这里有个缺点,他是一次处理固定的数据长度,但接收数据的长度有时未必固定,或者是只要有一个数据丢失,后面的数据将会全部错误。
上述链接中最致命的缺点在于没有适当清空liststr的数据,当出现各种意外,使得某次发送长度大于所需长度时,下一次的计算就会从多出的数据开始计算长度。那么解决的方式也很简单。开启个定时器计数,时间间隔为inftimer,定时刷新检测liststr的长度,如果liststr.Count不为0,也就是数据在接收中,当下次liststr.Count大于上次,表示在接收中,否则接收完毕并重置清零。代码如下:
/****************长时间没继续接收到数据,默认输出读取到的数据,并清空数据**************/
if (liststr.Count != 0)
{
timer -= Time.deltaTime;
if (timer <= 0)
{
if (liststr.Count > countcom)
{
countcom = liststr.Count;
}
else
{
Porthandle(); //处理函数
}
timer = inftimer;
}
}
在这里会引起其它的问题,一:串口读取后有一个延迟,取决于设定的inftimer的大小;二:这里是读取完数据后才响应的,对于数据连续循环的时候,将毫无办法,然而很多硬件的串口数据其实是不停的。我们着重对处理函数做修改,代码已经补充了很多了,代码如下:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using UnityEngine;
using System.Collections;
/// <summary>
/// C#用SerialPort类实现串口编程
/// </summary>
public class MePortDataHandle : MonoBehaviour
{
public bool Specialformat = false; //特殊格式项选择
public bool Continuousreading = true; //是否连续读取
List<byte> liststr;//在ListByte中读取数据,用于做数据处理
List<byte> ListByte;//存放读取的串口数据
int Frameheadloopindex = 0; //用于循环计数判断
bool isFrameheadmain = false; //判断是否接收到开始符
bool[] isFramehead; //开始符每一个对应的校正对应符
public string[] Framehead; //帧头1:字符的ASCII的16进制表示
int Headtruecount = 0; //开始校验正确位计算
bool initFrameheadmain = true; //是否是第一次前缀判断结束
bool isEnddatamain = false; //判断是否接收到结束符
bool[] isEnddata; //结束符每一个对应的校正对应符
public string[] Enddata; //结束符1:字符的ASCII的16进制表示
int Endtruecount = 0; //结束校验正确位计算
private Thread tPort; //读取串口数据的线程
private Thread tPortDeal;//处理数据的线程
bool isStartThread;//控制FixedUpdate里面的两个线程是否调用(当准备调用串口的Close方法时设置为false)
public SerialPort spstart; //串口变量
public ComType Comnow=ComType.COM1; //串口选择
public BaudRateType BaudRatenow=BaudRateType.B9600; //波特率选择
public float inftimer = 0.05f; //串口读取超时参数
float timer; //串口读取超时变量
int countcom = 0; //串口读取超时辅助计数
public int revlenght=-1; //在无前后缀的时候,读取数据的长度
private byte[] tempArr; //读取到的byte数据
/****************输出16进制字符串****************************/
private string temp16String; //读取到的16进制字符串数据
private string tempString; //读取到的字符串
private string NoSpecialformatstr16=null;
private string NoSpecialformatstr=null;
public MeRevPortclass MeNoSpecialPortdata = new MeRevPortclass();
private string Specialformatstr16 = null;
private string Specialformatstr = null;
public MeRevPortclass MeSpecialPortdata = new MeRevPortclass();
void Start()
{
if (Specialformat)
{
Continuousreading = false;
}
timer = inftimer;
InitJudgementsign();
OpenSerialPort(Comnow.ToString(), (int)BaudRatenow);
}
/****************开启串口函数***************/
void OpenSerialPort(string portName, int BaudRateindex)
{
isStartThread = true;
liststr = new List<byte>();
ListByte = new List<byte>();