Unity串口通信详解,附源码!

【前言】

实习生第一份工作做的是街机游戏,看到自己开发游戏给很多小孩子玩,爷的青春也就结束了,因为这一片都是做街机、VR,所以会接触到很多关于硬件设备的通信,到现在为止,还是挺喜欢这种基于硬件的游戏开发,做街机的时候,没做多久,所以当初最遗憾的事情就是没有学会串口通信,到现在为止,我觉得Unity的串口类主要是一个收发消息的集成类。

有兴趣的话也可以关注我的蛮牛专栏🖱点击跳转
懒的话可以直接下载使用,直接拖进Asset里,附上码云链接:🖱点击跳转串口通信源码下载

【对于刚接触串口的同学们来说】

一定要了解串口的几个属性和串口接收助手的使用,串口的属性在串口助手面板也有所体现,需要设置才能打开串口,完成连接。
如果没有串口设备想了解串口通信的话,可以使用串口模拟消息接收,相关链接:串口通讯调试与开发

以下我们都是通过实际开发串口通信来说明:
串口的几个属性,一定要与之对应才能正确连接,一般来说,硬件没有做特殊设置,只需要设置串口名,其他保持默认就行了
在这里插入图片描述
串口接收助手下载链接:链接:https://pan.baidu.com/s/1aPfa7u_RKvfaGicMno3Vfg
提取码:ui2r
在这里插入图片描述
在做项目时,先使用串口接收助手方便接收串口数据,这样可以用现成的工具先检测串口设备的收发信息的状况,如果通信良好,则开始程序的编写了。

【串口通信的程序编写,无码何以平天下,Show Me Code~

一.先展示一下我们的硬件手柄(有两个按钮+前后左右的遥感功能)

在这里插入图片描述

二.插上我们的串口设备之后,然后在我的电脑-属性-设备管理器中查看当前插入的串口设备号(COM*),当前我的串口设备名是COM3

在这里插入图片描述

三.开始编写串口通信的类

1.首先定义我们的设备的输入按钮,方便后面判断输入调用
public enum KeyType { 圆形按钮, 方形按钮, 前, 后, 左, 右 }//按钮    
 public KeyType keyType;
2.定义我们的串口属性变量,建议串口属性使用配置文件来管理方便适配不同的串口设备
    public string portName = "COM3";
    public int baudRate = 9600;
    public int dataBits = 8;
    public StopBits stopBits = StopBits.None;    
    public Parity parity = Parity.None;
3.Start里打开串口和开启线程处理串口消息
void Start()
    {
        OpenPort();
        thread_reviceData = new Thread(new ThreadStart(DataReviceThread));
        thread_reviceData.Start();
    }
4.打开串口和关闭串口的方法,关闭串口一般用于关闭程序之后调用
void OpenPort()
    {
        print("打开串口");
        try
        {
            serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
            serialPort.Open();
        }
        catch (System.Exception ex)
        {
            print("串口打开异常:"+ex);
        }
        
    }

    void ClosePort()
    {
        print("关闭串口");
        try
        {
            serialPort.Close();
            thread_reviceData.Abort();
        }
        catch (System.Exception ex)
        {
            print("串口关闭异常:" + ex);
        }        
    }
5.发送消息到串口测试,OnGUI方法用作发送测试,不用时可以自行删除OnGUI方法
#region 发送数据
    public void WriteData(string dataStr)
    {
        if (sp.IsOpen)
        {
            sp.Write(dataStr);
        }
    }
    void OnGUI()
    {
        message = GUILayout.TextField(message, GUILayout.Width(200), GUILayout.Height(50));
        if (GUILayout.Button("发送输入信息到串口对象", GUILayout.Width(200), GUILayout.Height(50)))
        {
            WriteData(message);
        }
        string test = "AA BB 01 12345 01AB 0@ab 发送";//测试字符串
        if (GUILayout.Button("发送默认信息到串口对象", GUILayout.Width(200), GUILayout.Height(50)))
        {
            WriteData(test);
        }
    }//OnGUI方法调试串口发送指令,如果不需要调试时,则可以自行注释OnGUI方法
    #endregion
6.多线程接收串口消息方法并将解析的消息放入队列池,注意else要根据协议来自行解析
void DataReviceThread()
    {
        byte[] bytes_read = new byte[1024];
        int count = 0;
        while (serialPort != null && serialPort.IsOpen)
        {
            try
            {
                count = serialPort.Read(bytes_read, 0, bytes_read.Length);//读取消息并获取字节数
                if (count == 0)
                    continue;
                else
                {//===================else部分就是接收到的串口消息,关于解析也是在这个逻辑之下,由于每种协议的制定和解析各不相同,这里就留给读者自行分析解析数据了                    
                    //print("字节数量:" + count);
                    //if (count == 6)
                    //{
                    //    StringBuilder stringBuilder = new StringBuilder();
                    //    for (int i = 0; i < count; i++)
                    //    {
                    //        stringBuilder.Append(Convert.ToString(bytes_read[i]));
                    //    }
                    //    str_data = stringBuilder.ToString();
                    //    //print(str_data);
                    //    queue_data.Enqueue(str_data);//将接收的消息放入队列                        
                    //}                       
                }
            }
            catch (Exception ex)
            {
                print("串口读取数据异常:" + ex);
            }
            Thread.Sleep(10);
        }

        //while (serialPort != null && serialPort.IsOpen)
        //{
        //    Thread.Sleep(1);
        //    try
        //    {
        //        byte byte_read = Convert.ToByte(serialPort.ReadByte());
        //        serialPort.DiscardInBuffer();//清楚串口数据
        //        list_data.Add(byte_read);//将接收的字节放入列表中
        //        PrintData();
        //    }
        //    catch (Exception ex)
        //    {
        //        print("串口读取数据异常:" + ex);
        //        list_data.Clear();
        //    }            
        //}
    }//数据接收的多线程

在这里插入图片描述图文无关

7.将解析的数据做处理,用bool来检测我们的按键输入,以便于我们转换成输入的方法
public bool[] KeyClickState = new bool[6];//手柄按钮点击的状态

void Update()
    {        
        if (queue_data.Count > 0)
        {
            queue_data.Dequeue();//清除第一条队列
            switch (str_data)
            {
                case "255142542515"://圆形
                    KeyClickState[0] = true;
                    //print("圆形按钮");
                    break;
                case "255152542504"://方形
                    KeyClickState[1] = true;
                    //print("方形按钮");
                    break;
                case "255182542479"://前
                    KeyClickState[2] = true;
                    //print("前");
                    break;
                case "255172542486"://后
                    KeyClickState[3] = true;
                    //print("后");
                    break;
                case "255162542497"://左
                    KeyClickState[4] = true;
                    //print("左");
                    break;
                case "255112542540"://右
                    KeyClickState[5] = true;
                    //print("右");
                    break;
                default:
                    break;
            }
        }
        else
        {
            for (int i = 0; i < KeyClickState.Length; i++)
            {
                KeyClickState[i] = false;//重置所有的按钮状态
            }
        }
    }

8.按下判定和任意键按钮判定
    public bool InputKeyClickDown(KeyType keyType)
    {        
        return KeyClickState[(int)keyType];
    }//如果按下按钮,由于update刷新bool为false,所以只返回一次true

    public bool anyKeyDown()
    {
        count_key = Enum.GetNames(keyType.GetType()).Length;//获取枚举的长度
        for (int i = 0; i < count_key; i++)
        {
            if (KeyClickState[i])
            {
                return KeyClickState[i];
            }            
        }
        return false;
    }//如果按下了任意的按键

【调用测试】

void Update()
    {
        if(SerialPortManagr.Instance.InputKeyClickDown(KeyType.圆形按钮))
        {
            print("点击了圆形按钮");
        }

        if (SerialPortManagr.Instance.anyKeyDown())
        {
            foreach (KeyType type in Enum.GetValues(typeof(KeyType)))
            {
                if (SerialPortManagr.Instance.InputKeyClickDown(type))
                {
                    print("点击了" + type);
                }
            }
        }
    }

【最后想说】

如果想要源码记得看开头的的前言部分↑↑
有兴趣的话也可以关注我的蛮牛专栏
🖱点击跳转

  • 24
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值