最近公司用U3D開發一個應用,需要用到串口,便研究了兩天串口編程,C#用SerialPort類實現串口編程,便開始使用SerialPort類編寫代碼。后來發現一個問題,Unity不支持DataReceived的方法。遇到這個問題很是棘手啊,后來在網上搜了一下,發現這個問題確實存在,解決的方法是開啟兩個線程,一個用來接收數據,一個用來處理數據。將兩個線程分別放在FixedUpdate里面調用,這樣便可以快速的讀取和處理數據了。但是程序運行時,開啟Open()方法時,會報System.IO.IOException這個異常。檢察了一下應該是該串口被占用。之所以被占用,是因為上次沒Close,而每次完成或退出時我確實寫了SerialPort的Close()方法。后來在網上查了一下相關的資料,發現如果Close的時候正好趕上讀取串口數據,這樣兩個線程便發生了矛盾,Close方法無法完成。但是代碼也不會報錯或是拋異常(據說這是微軟的一個bug,是不是就不清楚了)。所以說問題就出在了這里。那解決該問題的方法是當啟用Close的方法時,必須停止接受串口數據的線程。這樣該問題就解決了,代碼大致如下:
List<byte> liststr;//在ListByte中讀取數據,用於做數據處理
List<byte> ListByte;//存放讀取的串口數據
private Thread tPort;
private Thread tPortDeal;//這兩個為兩個線程,一個是讀取串口數據的線程一個是處理數據的線程
bool isStartThread;//控制FixedUpdate里面的兩個線程是否調用(當准備調用串口的Close方法時設置為false)
byte[] strOutPool = new byte[6];
SerialPort spstart;
void Start()
{
isStartThread=true;
liststr = new List<byte>();
ListByte = new List<byte>();
isStartThread = true;
spstart = new SerialPort("COM3", 57600, Parity.None, 8, StopBits.One);
try
{
spstart.Open();
}
catch (Exception e)
{
Debug.log(e.Tostring());
}
tPort = new Thread(DealData);
tPort.Start();
tPortDeal = new Thread(ReceiveData);
tPortDeal.Start();
}
void FixedUpdate()
{
if (isStartThread)
{
if (!tPortDeal.IsAlive)
{
tPortDeal = new Thread(ReceiveData);
tPortDeal.Start();
}
if (!tPort.IsAlive)
{
tPort = new Thread(DealData);
tPort.Start();
}
}
}
private void ReceiveData()
{
try
{
Byte[] buf = new Byte[1];
string sbReadline2str = string.Empty;
if (spstart.IsOpen)
{
tickcount++;
spstart.Read(buf, 0, 1);
}
if (buf.Length == 0)
{
return;
}
if (buf != null)
{
for (int i = 0; i < buf.Length; i++)
{
ListByte.Add(buf[i]);
}
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
spantime = 0;
}
}
private void DealData()
{
liststr.Add(ListByte[0]);
ListByte.Remove(ListByte[0]);
if (liststr.Count == 6)//串口發過來的數據的位數(我的應用中位數為6)
{
{
//這個地方寫處理的邏輯代碼
}
}
liststr.Clear();
}
}
IEnumerator ClosePort()//該方法為關閉串口的方法,當程序退出或是離開該頁面或是想停止串口時調用。
{
isStartThread=false;//停止掉FixedUpdate里面的兩個線程的調用
yield return new WaitForSeconds(1);//等一秒鍾,讓兩個線程確實停止之后在執行Close方法
spstart.Close();
}