欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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();
        }
       
    }