美文网首页unity开发征服Unity3dUnity技术分享
unity串口数据传输(避免假死状况)

unity串口数据传输(避免假死状况)

作者: 湛月 | 来源:发表于2016-07-15 18:02 被阅读1354次

    unity接陀螺仪数据,走的串口,可以通过蓝牙或者usb传输数据。主要用来控制场景中相机方向,配合一些没有陀螺仪的头盔使用。

    关于串口获取数据,本人菜鸟一个,在网上找了一堆资料,最后自己改了一段代码,这篇文章写的比较晚,之前找资料的网址找不到了,

    如果有版权问题请发消息给我。

    代码如下:说明一下,里面注释的一段是网上找的串口消息解析,原作者使用了2中方法解析,我只看懂了笨办法,正则表达式那段代码开不明白,有大神能理解给我留言讲解下吧!本文只取的是JY-61的方向,没有取其他两种参数,有需要自己改代码。

    using UnityEngine;

    using System.Collections;

    using System.Collections.Generic;

    using System.Threading;

    sing System.IO.Ports;using System;

    using System.Text;

    sing System.Text.RegularExpressions;

    public class ReadIO : MonoBehaviour

    {    

    private Thread tPort;    

    private Thread tPortDeal;//这两个为两个线程,一个是读取串口数据的线程一个是处理数据的线程   

     bool isStartThread;//控制FixedUpdate里面的两个线程是否调用(当准备调用串口的Close方法时设置为false)    

    SerialPort spstart;    

    public static float angleX;   

     public static float angleY;   

    public static float angleZ;    

    string recData;   

     private byte[] DataBuf;   

     void Start()    {       

     DataBuf = new byte[11];  //如果取三组数据:加速度,角速度,角度则byte取长度33,单个取11长度       

     isStartThread = true;       

     spstart = new SerialPort("COM7", 9600, Parity.None, 8, StopBits.One);       

     try        {     

           spstart.Open();      

      }       

     catch (Exception e)        {            Debug.Log(e.ToString());        }    

     tPortDeal = new Thread(ReceiveData);       

    PortDeal.Start();       

     tPort = new Thread(DealData);      

      tPort.Start();    }   

     void Update()    {    }    

    void FixedUpdate()    {        

    //定期回收垃圾       

     if (Time.frameCount % 120 == 0) System.GC.Collect();    }    

    //接收数据    

    private void ReceiveData()

    {

    while (isStartThread)

    {

    #region

    try

    {

    //读取数据

    byte tempB = 0;

    tempB = (byte)spstart.ReadByte();

    //Read the header first

    if (tempB == 85)                //获取包头16进制的55,换算下来就是10进制的85

    {

    DataBuf[0] = tempB;

    tempB = (byte)spstart.ReadByte();

    if (tempB == 83)            //获取第二个字节53,换算下是83

    {

    DataBuf[1] = tempB;

    int DataNumber = 2;

    while (DataNumber < 11)

    {

    tempB = (byte)spstart.ReadByte();

    DataBuf[DataNumber] = tempB;

    DataNumber++;

    }

    recData = ToHexString(DataBuf);

    // Debug.Log(recData);

    }

    }

    // Thread.Sleep(10);

    }

    catch (Exception e)

    {

    StartCoroutine(ClosePort());

    Debug.LogError(e);

    }

    #endregion

    /*try

    {

    //从输入缓存区中去读取第一次出现"AA"时的内容

    Byte[] buf = new Byte[33];

    spstart.Read(buf, 0, 33);

    //如果没有接到到数据,就返回

    if (buf.Length == 0)

    {

    return;

    }

    string sbReadline2str = string.Empty;

    if (buf != null)

    {

    for (int i = 0; i < buf.Length; i++)

    {

    sbReadline2str += buf[i].ToString("X2");

    }

    }

    //提取完整的一个数据包,压入数据池中(队列中)

    if (sbReadline2str.StartsWith("5553"))

    {

    sbReadline2str = sbReadline2str.Substring(0, 11);

    //分组数据包

    //string[] _str = Regex.Split(sbReadline2str, "5553", RegexOptions.IgnoreCase);

    //foreach (string s in _str)

    //{

    //    if (s.Length == 31)

    //    {

    //        //数据进入队列

    //        queueDataPool.Enqueue( "5553"+s);

    //        Debug.LogError("5553" + s);

    //    }

    //}

    }

    else

    {

    sbReadline2str = sbReadline2str.Remove(0, sbReadline2str.IndexOf("5553"));

    if(sbReadline2str.Length >= 11)

    {

    sbReadline2str = sbReadline2str.Substring(0, 11);

    Debug.Log(sbReadline2str);

    }

    //string[] _str = Regex.Split(sbReadline2str, "5553", RegexOptions.IgnoreCase);

    //foreach (string s in _str)

    //{

    //    if (s.Length == 31)

    //    {

    //        //数据进入队列

    //        queueDataPool.Enqueue("5553" + s);

    //        Debug.LogError("5553" + s);

    //    }

    //}

    }

    }

    catch (Exception ex)

    {

    Debug.LogError(ex);

    }*/

    }

    }

    //byte转16进制字符串

    public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "

    {

    string hexString = string.Empty;

    if (bytes != null)

    {

    StringBuilder strB = new StringBuilder();

    for (int i = 0; i < bytes.Length; i++)

    {

    strB.Append(bytes[i].ToString("X2"));

    }

    hexString = strB.ToString();

    }

    return hexString;

    }

    private void DealData()

    {

    while (isStartThread)

    {

    CalculateAngle();

    }

    }

    void CalculateAngle()

    {

    if (recData == null) return;

    //Debug.Log("处理字符: " + recData);

    /*把16进制字符串转换成字节数组*/

    byte[] returnBytes = new byte[recData.Length / 2];

    for (int i = 0; i < returnBytes.Length; i++)

    returnBytes[i] = Convert.ToByte(recData.Substring(i * 2, 2), 16);

    float _FangXiangJiao = (float)((byte)returnBytes[2] + ((sbyte)returnBytes[3] << 8)) / 32768 * 180;

    //Debug.Log("x-->" + _FangXiangJiao);

    float _YangJiao = (float)((byte)returnBytes[4] + ((sbyte)returnBytes[5] << 8)) / 32768 * 180;

    // Debug.Log("y-->" + _YangJiao);

    float _XuanZhuanJiao = (float)((byte)returnBytes[6] + ((sbyte)returnBytes[7] << 8)) / 32768 * 180;

    // Debug.Log("z-->" + _XuanZhuanJiao);

    angleX = _FangXiangJiao;

    angleY = _YangJiao;

    angleZ = _XuanZhuanJiao;

    }

    void OnApplicationQuit()

    {

    StartCoroutine(ClosePort());

    }

    IEnumerator ClosePort()//该方法为关闭串口的方法,当程序退出或是离开该页面或是想停止串口时调用。

    {

    isStartThread = false;//停止两个线程的更新

    tPortDeal.Abort();

    tPort.Abort();

    yield return new WaitForSeconds(1);//等一秒钟,让两个线程确实停止之后在执行Close方法

    spstart.Close();

    yield return new WaitForSeconds(1);

    }

    }

    相关文章

      网友评论

      本文标题:unity串口数据传输(避免假死状况)

      本文链接:https://www.haomeiwen.com/subject/seiyjttx.html