zoukankan      html  css  js  c++  java
  • Unity3D串口处理

      最近公司用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();
    }

  • 相关阅读:
    开源界的 5 大开源许可协议
    如何选择开源许可证?
    Ubuntu下Qt编译报错“cannot find -lGL”的解决方案
    How to Cracked Sublime Text 3 Build 3065 in Ubuntu (Linux)
    一个C语言宏展开问题
    C语言预处理运算符
    Linux线程编程之信号处理
    Linux终端多用户通信实用命令
    守护进程接收终端输入的一种变通性方法(二)
    通过printf设置Linux终端输出的颜色和显示方式
  • 原文地址:https://www.cnblogs.com/zhaozhengling/p/3696251.html
Copyright © 2011-2022 走看看