Unity接硬件串口
程序员文章站
2022-04-03 12:21:04
...
一、PortControl脚本(硬件串口数据)
using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using UnityEngine.UI;
public class PortControl : MonoBehaviour
{
public static PortControl Instance;
#region 定义串口属性
//定义基本信息
public string portName = "COM5";//串口名
public int baudRate = 115200;//波特率
public Parity parity = Parity.None;//效验位
public int dataBits = 8;//数据位
public StopBits stopBits = StopBits.One;//停止位
public SerialPort sp = null;
public Thread dataReceiveThread;
public Thread dataSendThread;
//发送数据
public List<byte> listReceive = new List<byte>();
public Queue<byte[]> recBuffer = new Queue<byte[]>();//接受所有的buffer 队列 先进先出
public Queue<byte[]> sendBuffer = new Queue<byte[]>();//发包 队列
char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
string str;
byte[] buffer = new byte[1024];
byte[] receiveBuffer = new byte[1024];
int receivePosition;
#endregion
void Start()
{
Instance = this;
dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
dataReceiveThread.Start();
dataSendThread = new Thread(new ThreadStart(WriteData));
dataSendThread.Start();
//ThreadPool.QueueUserWorkItem(new WaitCallback(WriteData));
}
#region 创建串口,并打开串口
public void OpenPort()
{
//创建串口
sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
sp.ReadTimeout =800;//操作超出时间 这个时间越长报错越少,但不能太长
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
/// <summary>
/// 打印接收的信息
/// </summary>
void PrintData()
{
for (int i = 0; i < listReceive.Count; i++)
{
strchar[i] = (char)(listReceive[i]);
str = new string(strchar);
}
Debug.Log(str);
}
public byte[] Dispatch()
{
//判断接受的数据是否为空
if (recBuffer.Count == 0) return null;
return recBuffer.Dequeue();//头部读取并删除
}
#region 接收数据
public void DataReceiveFunction()
{
#region 按字节数组发送处理信息,信息缺失
int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
bytes = 0;
bytes = sp.Read(buffer, 0, buffer.Length);//接收字节 数
if (bytes == 0)
{
continue;
}
else
{
Array.Copy(buffer, 0, receiveBuffer, receivePosition, bytes);
Array.Clear(buffer, 0, buffer.Length);//清空buffer数组
receivePosition += bytes;
int index = 0;
while (index <= 50)
{
index++;
bool has7E = false;
//一串数中,第一个126
var first7E = receiveBuffer[index];
if (first7E == 0x7E)
{
has7E = true;
var head = receiveBuffer[0];//第一个刚才跳过了,现在额外判断
if (head == 0x7E)
{
if (index == 16 || index == 7)
{
var bbuffer = new byte[index];
Array.Copy(receiveBuffer, 0, bbuffer, 0, index);
recBuffer.Enqueue(bbuffer);
}
}
for (int i = 0; i < 50; i++)
{
receiveBuffer[i] = receiveBuffer[index + i];
}
receivePosition -= index;
break;
}
if (index == 50 && has7E == false && receivePosition >= 50)
{
for (int i = 0; i < 50; i++)
{
receiveBuffer[i] = receiveBuffer[index + i];
}
receivePosition -= index;
}
}
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
}
Thread.Sleep(10);
}
}
#endregion
#endregion
#region 发送数据
//public void WriteData(string dataStr)
//{
// //传进来的是字符串
// if (sp.IsOpen)
// {
// sp.Write(dataStr);
// }
//}
//public void WriteData(byte[] buffer)
//{
// //传进来的是十六进制的,例如:byte []byte1 =new byte[] { 0X7E, 0X02, 0X01, 0X00, 0X01, 0X01 };
// if (sp.IsOpen)
// {
// sp.Write(buffer, 0, buffer.Length);
// }
//}
public void WriteData()
{
while (true)
{
if (sp.IsOpen)
{
try
{
var datas = SendBuffer();
sp.Write(datas, 0, datas.Length);
}
catch (Exception ex)
{
Debug.Log(ex .Message);
}
}
Thread.Sleep(20);
}
}
byte []SendBuffer()
{
if (sendBuffer.Count == 0)
{
byte[] buffer = new byte[] { 0X7E, 0X02, 0X01, 0X00, 0X01, 0X01 };
return buffer;
}
else
{
return sendBuffer.Dequeue();
}
}
#endregion
}
二、PortDispose脚本 ( 串口数据读取处理)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
public class PortDispose : MonoBehaviour {
public static PortDispose Instance;
public PortControl control;
private bool Ischange = false;
public int stateValueDO1 = 0X05;//灯 送风阀和排风阀红灯亮
public int stateValueDO2 = 0X09;//灯 1#启动灯 2#停止灯
public int stateValueDI3 = 0X50;//按钮 送风阀自动 排风阀自动
public int stateValueDI4 = 0X00;//按钮
public int stateValueDO5 = 0X01;//灯 电源指示灯亮
public int stateValueDO6 = 0X00;//灯
public int stateValueDI7 = 0X10;//按钮 1#主2#备
public int stateValueDI8 = 0X40;//按钮 pulse 自动
public int stateValueDI9 = 0X00;
public int stateValueDI10 = 0X00;
public int SumValue;
private void Awake()
{
Instance = this;
Open();
}
void Update()
{
if (control == null)
return;
DisposeData();
}
public bool IsOne(int bit, int which)
{
//是否可以按下这个按钮
return (which & 1 << bit)!=0;
}
public void SetValue(int bit, ref int which,int isOn)
{
Ischange = true;
//设置按钮/灯 状态
if (isOn == 0)
{
which=which & ~(1 << bit);
}
else if (isOn == 1)
{
which =which | (1 << bit);
}
}
private void DisposeData()
{
var datas = control.Dispatch();
while (datas != null)
{
//这里写接收到各种数据的处理逻辑
if (datas.Length == 16)
{
int sum = 0;
//接收到的 按钮数据包 长度是16
for (int i = 0; i < datas.Length; i++)
{
//判断数据 校验和是否一致
if (i > 4 && i < datas.Length - 1) sum += datas[i];
}
if (sum == datas[datas.Length - 1])
{
//7E 01 02 0a 11 00 00 01 00 00 00 00 32 00 00 33(校验和)
stateValueDO1 = datas[5];
stateValueDO2 = datas[6];
stateValueDI3 = datas[7];
stateValueDI4 = datas[8];
stateValueDO5 = datas[9];
stateValueDO6 = datas[10];
stateValueDI7 = datas[11];
stateValueDI8 = datas[12];
stateValueDI9 = datas[13];
stateValueDI10 = datas[14];
UpdateData();
}
else
{
string itemstr="";
foreach (var item in datas)
{
itemstr += item+" ";
}
Debug.Log(itemstr +"校验和不匹配");
}
}
else if (datas.Length == 7)
{
if (datas[5] != 0) Debug.Log("灯 收包异常");
}
datas = control.Dispatch();
}
}
上一篇: 获取手机的系统信息