将Unity3D的API平台切换成.NET2.0,切换方法: “Edit–>project Setting–>Player–>Other Setting –>Api Compatibility level”。在这里将“.NET2.0 Subset”切换为“.NET4.X”(.NET2.0也可以)。以unity2019.3.2为例
在使用线程接收byte数据时,按字节数组发送处理信息,会出现数据分两次接收问题(往往在第一次接收时,只接收第一个数据)`
byte[] buffer = new byte[1024];
int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
bytes = sp.Read(buffer, 0, buffer.Length);//接收字节
if (bytes == 0)
{
continue;
}
else
{
string strbytes = Encoding.Default.GetString(buffer);
Debug.Log(strbytes);
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
}
Thread.Sleep(10);
}
**
**
using UnityEngine;
using System.Collections;
using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Text;
public class SerialPortReciever : MonoBehaviour
{
//串口的通信类
private SerialPort sp;
//队列(先后存储消息,以便处理)
private Queue<string> queueDataPool;
private List<string> list;
private List<string> strList = new List<string>();
//处理数据的线程
private Thread tPort;
//接收数据的线程
private Thread tPortDeal;
//输出池
private string strOutPool = string.Empty;
//最终的值
string finalstring = string.Empty;
//临时的值
string tempstring = string.Empty;
// Use this for initialization
void Start()
{
//创建一个队列
queueDataPool = new Queue<string>();
//创建一个串口
sp = new SerialPort("COM5", 9600, Parity.None, 8, StopBits.One);
//判断是否打开串口
if (!sp.IsOpen)
{
sp.Open();
}
//创建一个线程(方法),开始执行是调用的方法
tPort = new Thread(DealData);
tPort.Start();
tPortDeal = new Thread(ReceiveData);
tPortDeal.Start();
}
// Update is called once per frame
void Update()
{
//当前线程的执行状态
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 (sp.IsOpen) sp.Read(buf, 0, 1);
foreach (var item in buf)
{
Debug.Log(item.ToString());
}
if (buf.Length == 0)
{
return;
}
if (buf != null)
{
for (int i = 0; i < buf.Length; i++)
{
sbReadline2str += Encoding.Default.GetString(buf);
queueDataPool.Enqueue(sbReadline2str);
}
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
//满16个字节打印
private void DealData()
{
while (queueDataPool.Count != 0)
{
list = new List<string>(queueDataPool);
queueDataPool.Clear();
for (int i = 0; i < list.Count; i ++)
{
strOutPool += list[i];
strList.Add(strOutPool);
strOutPool = string.Empty;
}
// Debug.Log(strList.Count);
for (int i = 0; i < queueDataPool.Count; i++)
{
strOutPool += queueDataPool.Dequeue();
//switch (queueDataPool.Peek())
//{
// default:
// break;
//}
if (strOutPool.Length == 16)
{
Debug.Log(strOutPool);
}
// Debug.Log(strOutPool);
}
}
}
//输出信息
private void SendSerialPortData(string data)
{
if (sp.IsOpen)
{
sp.WriteLine(data);
}
}
//当程序退出时的操作
void OnApplicationQuit()
{
sp.Close();
}
}
using UnityEngine;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Threading;
public class PortControl : MonoBehaviour
{
#region 定义串口属性
public string portName = "COM5";//串口名
public int baudRate = 9600;//波特率
public Parity parity = Parity.None;//效验位
public int dataBits = 8;//数据位
public StopBits stopBits = StopBits.One;//停止位
SerialPort sp = null;
Thread dataReceiveThread;
public static List<byte> bytelist = new List<byte>();
#endregion
public ThreeAxis threeAxis;
void Start()
{
OpenPort();
dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
dataReceiveThread.Start();
}
#region 创建串口,并打开串口
public void OpenPort()
{
//创建串口
sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
sp.ReadTimeout = 400;
try
{
sp.Open();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
#region 程序退出时关闭串口
void OnApplicationQuit()
{
ClosePort();
}
public void ClosePort()
{
try
{
sp.Close();
dataReceiveThread.Abort();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
#region 接收数据
void DataReceiveFunction()
{
while (true)
{
if (sp != null && sp.IsOpen)
{
int bytes = sp.BytesToRead;
byte[] buffer = new byte[bytes];
try
{
sp.Read(buffer, 0, bytes);
if (bytes == 0)
{
continue;
}
else
{
bytelist.AddRange(buffer);
}
}
catch (Exception ex)
{
}
}
Thread.Sleep(100);
}
}
#endregion
#region 发送数据
public void WriteData(string dataStr)
{
if (sp.IsOpen)
{
sp.Write(dataStr);
}
}
同样需要设定初始值,比如:
if (bytelist.Count >3)//3是帧头加帧尾加最小一位数据
{
#region 根据帧头判断数据类型
switch (bytelist[0])
{
case :
break;
}
#endregion
bytelist.Clear();//处理一次数据,清空list
}
需要注意: 在每次读取list数据,然后就清空整个list,再进行下一次数据处理,可能会造成数据丢失,建议按位取数据,清除已取出的数据。
comdemo
串口调试工具
虚拟串口工具