Unity3d读写COM串口

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO.Ports;
using UnityEngine;
using UnityEngine.UI;

public class ComPortControl : MonoBehaviour {
    //COM串口
    [Header("------COM串口------")]
    public Image imgComStatus;
    public Dropdown dropdownComList;
    public Button bntOpenCom;

    SerialPort sp = null;
    bool isAlive = true;

    // Use this for initialization
    void Start()
    {
        //打开串口
        bntOpenCom.onClick.AddListener(new UnityEngine.Events.UnityAction(delegate ()
        {
            ClosePort();

            OpenPort(dropdownComList.options[dropdownComList.value].text);
        }));

        string[] portNames = System.IO.Ports.SerialPort.GetPortNames();
        dropdownComList.AddOptions(new List<string>(portNames));

        if (portNames.Length > 0)
        {
            OpenPort(portNames[0]);
        }
    }


    IEnumerator WriteCOMData()
    {
        if (sp != null)
        {
            for (int i = 0; i < 15; i++)
            {
                Byte[] TxData = { 0xF3, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x3F };
                sp.Write(TxData, 0, 8);

                Debug.Log(i + "次发串口指令成功");
                yield return new WaitForSeconds(0.1f);
            }
        }
        else
        {
            Debug.Log("发串口指令失败");
        }
    }

    #region 创建串口,并打开串口
    public void OpenPort(string portName)
    {
        string openPortName = portName;

        //创建串口
        int comNum = int.Parse(portName.Substring(3));
        if (comNum > 9)
        {
            openPortName = "\\\\.\\" + portName;
        }


        try
        {
            sp = new SerialPort(openPortName, 9600, Parity.None, 8, StopBits.One);
            sp.ReadTimeout = 50;
            sp.Open();

            if (sp != null && sp.IsOpen)
            {
                Debug.Log(portName + "串口已打开");
                PlayerPrefs.SetString("IceBreakerComPort", portName);
                imgComStatus.sprite = Resources.Load<Sprite>("Texture/greencircle");

                StartCoroutine(DataReceiveFunction());
            }
            else
            {
                imgComStatus.sprite = Resources.Load<Sprite>("Texture/redcircle");
                Debug.Log(portName + "串口未打开");
            }
        }
        catch (Exception ex)
        {
            Debug.Log(ex.Message);
        }
    }
    #endregion

    IEnumerator DataReceiveFunction()
    {
        //应该读取的字节长度,可能多次读取才能成功
        const int BYTE_ARRAY_SIZE = 36;

        byte[] buffer = new byte[BYTE_ARRAY_SIZE];
        int len = 0;
        int previouseLen = 0;
        while (isAlive)
        {
            if (sp != null && sp.IsOpen)
            {
                try
                {
                    //接收字节
                    byte[] recData = new byte[BYTE_ARRAY_SIZE];
                    len = sp.Read(recData, 0, recData.Length);

                    if (previouseLen + len > BYTE_ARRAY_SIZE)
                    {
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            buffer[i] = 0x00;
                        }
                        previouseLen = 0;
                    }
                    //和之前的字节拼接
                    for (int i = 0; i < len; i++)
                    {
                        buffer[previouseLen + i] = recData[i];
                    }

                    //拼接后的长度
                    int newLen = previouseLen + len;

                    string dataFromComPort = byteToHexStr(buffer, newLen);
                    if (!string.IsNullOrEmpty(dataFromComPort) && newLen == BYTE_ARRAY_SIZE)
                    {
                        Debug.Log(DateTime.Now.ToShortDateString()+ "串口消息:" + dataFromComPort);
                    }

                    //从后往前搜
                    int endIndex = ByteArrayReverseIndex(buffer, 0x3f);
                    int firstValueIndex = endIndex - 5;

                    //如果不满足要求继续接收
                    if (endIndex == -1 || firstValueIndex < 0)
                    {
                        previouseLen = newLen;
                        continue;
                    }

                    if (buffer[firstValueIndex] == 0x01)
                    {
                        Debug.Log("串口调试:识别到 0x01 运行");
                    }
                    else if (buffer[firstValueIndex] == 0x02)
                    {
                        Debug.Log("串口调试:识别到 0x02 急停");
                    }
                    else if (buffer[firstValueIndex] == 0x03)
                    {
                        Debug.Log("串口调试:识别到 0x03 复位");
                    }

                    //复制3f后面的数据作为下次起点
                    if (endIndex > 0)
                    {
                        //截取3f后面的字符串
                        byte[] tmpBuffer = new byte[newLen - (endIndex + 1)];
                        for (int j = endIndex + 1; j < newLen; j++)
                        {
                            tmpBuffer[j - (endIndex + 1)] = buffer[j];
                        }

                        //前移
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            if (i < newLen - (endIndex + 1))
                            {
                                buffer[i] = tmpBuffer[i];
                            }
                            else
                            {
                                buffer[i] = 0x00;
                            }
                        }

                        //下次起点
                        previouseLen = newLen - (endIndex + 1);
                    }
                }
                catch (Exception ex)
                {
                    //Debug.Log(ex.Message);
                }
            }
            yield return null;
        }
    }

    #region 程序退出时关闭串口
    public void ClosePort()
    {
        if (sp == null)
            return;

        try
        {
            sp.Close();
            isAlive = false;
            //dataReceiveThread.Abort();
        }
        catch (Exception ex)
        {
            Debug.Log(ex.Message);
        }
    }
    #endregion

    /// 查找最后一个字符出现的索引
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    private int ByteArrayReverseIndex(byte[] buffer, byte b)
    {
        int index = -1;
        for (int i = 0; i < buffer.Length; i++)
        {
            if (buffer[i] == b)
            {
                index = i;
            }
        }

        return index;
    }

    void OnDestroy()
    {
        ClosePort();
    }

    /// <summary>
    /// 获取下拉列表某项的索上
    /// </summary>
    /// <param name="dd">下拉列表</param>
    /// <param name="str">某项文字</param>
    /// <returns>索引</returns>
    public static int GetDropdownIndex(Dropdown dd, string str)
    {
        int i = 0;
        int index = 0;
        foreach (var op in dd.options)
        {
            if (op.text.Equals(str))
            {
                index = i;
                break;
            }
            i++;
        }
        return index;
    }

    private static string byteToHexStr(byte[] bytes, int length)
    {
        string returnStr = "";
        if (bytes != null)
        {
            for (int i = 0; i < length; i++)
            {
                returnStr += bytes[i].ToString("X2");
            }
        }
        return returnStr;
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值