通过Unity在PC上实现简单的串口通信

代码仅实现了简单的字符串收发操作,关闭串口,代码内有详细注释,学习串口通信用到的方法笔记

错误:关闭串口时会有串口读取异常的提示,本人新手,一直未找到原因

附上代码

脚本名为“zibian”

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System.Threading;
using System;
using System.Text;

public class zibian : MonoBehaviour
{
    public string portName = "COM3";//串口
    public int baudRate = 9600;//波特率
    public Parity parity = Parity.None;//效验位
    public int dataBits = 8;//数据位
    public StopBits stopBits = StopBits.None;//停止位
    SerialPort serialPort=null;//端口
    Thread thread;//数据接收线程
    List<byte> list=new List<byte>();//泛型队列
    Queue<string> queue = new Queue<string>();
    string str_data;//接收消息队列
    char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
    

    // Start is called before the first frame update
    void Start()
    {
        OpenPort();//打开串口
        thread = new Thread(new ThreadStart(DataReviceThread));//创建线程方法和处于线程中的方法
        thread.Start();//启动线程
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void OpenPort()//打开串口
    {
        print("打开串口");
        serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
       
        try
        {
            serialPort.Open();
        }
        catch(Exception ex)
        {
            print("串口打开异常:" + ex.Message);
        }
    }

    public void ClosePort()//关闭串口
    {
        print("关闭串口");
        try
        {
            serialPort.Close();//关闭端口
            thread.Abort();//终止线程
        }
        catch (Exception ex)
        {
            print("串口关闭异常:" + ex);
           
        }
    }

    private void OnApplicationQuit()//关闭程序或退出播放时调用关闭串口方法
    {
        ClosePort();
    }

    public void WriteData(string dataStr)//发送数据电脑往硬件发送
    {
        if (serialPort.IsOpen)
        {
            serialPort.Write(dataStr);//发送数据
        }
    }

    void DataReviceThread()//接收数据 外设到电脑
    {
        byte[] bytes_vs = new byte[1024];//存储字节
        int count;//存储字节长度
        while (serialPort != null && serialPort.IsOpen)
        {
            try
            {
                count = serialPort.BytesToRead;//获取接收缓冲区中数据的字节数。
                serialPort.Read(bytes_vs, 0, count);//读取消息并获取字节
                //count = serialPort.Read(bytes_vs, 0, bytes_vs.Length);//读取消息并获取字节
                if (count==0)
                {
                    continue;
                }
                else
                {
                    print("字节数量:" + count);//输出字节数
                    //string str1 = Encoding.UTF8.GetString(bytes_vs);//将字节转换成字符串并输出
                    //print(str1);


                    StringBuilder stringBuilder = new StringBuilder();//创建动态可变字符串
                    for (int i = 0; i < count; i++)
                    {
                        stringBuilder.Append(Convert.ToString(bytes_vs[i]));//将Bytes数据类型转换位string数据类型,并添加在字符串末尾
                    }
                    str_data = stringBuilder.ToString();//StringBuilder对象转换为string对象
                    print(str_data);//输出字符串
                    queue.Enqueue(str_data);//将接收的消息放入队列
                }
            }
            catch (Exception ex)
            {
                print("串口读取异常:" + ex.Message);
                
            }
            Thread.Sleep(10);//将当前线程挂起指定的时间。
        }
    }

    void PrintData()  //打印数据
    {
        for (int i = 0; i < list.Count; i++)
        {
            strchar[i] = (char)(list[i]);
            str_data = new string(strchar);
        }
        Debug.Log(str_data);
    }
}

简单使用步骤

1.在Unity中创建一个空对象a1将脚本拖入。

2.在Unity中创建按钮button,在单击事件中创建一个事件,将a1拖入事件,并引用脚本中的WriteData()方法。

3.下载安装虚拟串口vspdconfig,在软件中创建虚拟串口COM3和COM4

4.安装串口调试助手,XCOM或XTC-ISP等都行,本人用的时XCOM

5.打开串口助手,串口选择为COM4,并打开串口。

6.进入Unity 点击运行,控制台提示打开串口后即可实现在电脑上的字符串串口通信,双方的通信时传递ASCII 码。

下面时学习串口通信时用到的方法和类

注意:更多更好更详细的方法和类介绍还是要到VS的.NET 文档里面查看

Unity 串口通信

使用教程

引用命名空间:System.IO.Ports

Serialport  类

流程是设置通信端口号及波特率、数据位、停止位和校验位,再打开端口连接、发送数据、接收数据,最后关闭端口连接步骤。

用到的命名空间

using System.IO.Ports;

using System.IO;

using System.Threading;

using System;

using System.Text;

声明变量

public string portName = "COM4";//串口号

    public int baudRate = 9600;//波特率

    public Parity parity = Parity.None;//效验位

    public int dataBits = 8;//数据位

    public StopBits stopBits = StopBits.One;//停止位

    SerialPort sp = null;//声明串口端口

SerialPort(); 使用时要先声明一个此变量类型 表示串行端口资源,

SerialPort (string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits);

SerialPort(端口名称波特率奇偶校验位数据位停止位)

例SerialPort sp=new SerialPort(portName, baudRate, parity, dataBits, stopBits)

要指定端口名称、波特率、奇偶校验位、数据位和停止位,请使用此构造函数创建类的新实例。

IsOpen;获取一个值,该值指示SerialPort(串口)对象的打开或关闭状态。默认为false。串口名.IsOpen;

sp.Open();  打开串口。

sp.Close();  关闭串口.

ReadTimeout 操作未完成时发生超时之前的毫秒数,读取超时值最初设置为500毫秒。超时值可以设置为大于零的任何值.

例:Sp. ReadTimeout=400;

_data==System.Text.Encoding.ASCII.GetBytes(testString)[0].ToString()

把字符串tesString按照简体中文(ASCIIEncoding.ASCII)的编码方式,

编码成 Bytes类型的字节流数组; 判断外设输入的字符串的ASCII码转换成字符串是否与_data字符串一致

sp.Read(Byte[], Int32, Int32)sp.Read(Char[], Int32, Int32)

     字节数组 ,偏移量,最多读取的字节数       字符数组

从 SerialPort(串口) 输入缓冲区读取一些字节并将那些字节写入字节数组中指定的偏移量处。

System.Text. 引用命名空间

Encoding 类 表示字符编码

Encoding.Default 属性,获取此 .NET 实现的默认编码。建议使用Encoding.UTF8 属性,效果一样且更好,不易丢失数据

Encoding.ASCII 获取ASCII(7 位)字符集的编码。

Encoding.ASCII.GetBytes(字符串) 在派生类中重写时,将一组字符编码为一个字节序列。

Encoding.UTF8.GetString(Byte[ ]) : 在派生类中重写时,将一个字节序列解码为一个字符串。

Write():将数据写入串行端口输出缓冲区

WriteLine():将指定的字符串写入串行端口输出缓冲区

System.Text. 引用命名空间

StringBuilder  表示可变字符字符串。 此类不能被继承。常用于执行大量字符串操作的例程

实例化对象:StringBuilder s1= new StringBuilder("字符串");

StringBuilder s1= new StringBuilder("字符串",字符串容量int);

s1.Append      将信息追加到s1当前的末尾。

将StringBuilder对象转换为字符串String:

s1.ToString();

必须先将 StringBuilder 对象转换为 String 对象,然后才能将 StringBuilder 对象表示的字符串传递给包含 String 参数的方法,或在用户界面中显示它。

Convert

将一种数据类型转换为另一种特定的数据类型。可转换的数据类型有ToInt32 、 ToBoolean 和 ToString ,ToChar等

例:string s2=Convert.ToString(数据变量名)

yield return new WaitForSeconds(Time.deltaTime);  延时

OnApplicationQuit() 是一个方法API 在应用程序退出前,发送给所有游戏对象。在 Editor 中,当用户停止播放模式时,将调用该函数。

OnDisable() 是一个方法API 该函数在行为被禁用时调用,当对象销毁时也会调用该函数,它可用于任何清理代码。 当编译完成后重新加载脚本时,将调用 OnDisable,并在加载脚本后调用 OnEnable,不能作为协同程序使用。

Thread 类  创建和控制线程,设置其优先级并获取其状态。

Thread 变量名 = new Thread(new ThreadStart(方法))

变量名.Start();     //导致操作系统将当前实例的状态更改为Running,并选择提供包含线程执行的方法要使用的数据的对象。

Running的意思是  线程已启动且尚未停止。

放在Start方法中

数据接收线程,串口通信代码中放的是接收数据的方法

Thread.Sleep(毫秒数):将当前线程挂起指定的时间。在指定的时间内,将不会将线程计划为由操作系统执行。

Abort() 终止线程 方法已经过时,.net5.0不在用

List<T>

命名空间 System.Collections.Generic

List<byte> 变量名 = new List<byte>();    //创建泛型接口,和数组相似, byte 是变量类型

List<T>泛型接口

他可以存储任何类型的数据类型。

T代表了List列表中元素的类型如果是List<int> 那他的所有元素均为int类型的

举个例子,List<string > Liststr = new List<string>();

所有string类型的数据都可以添加到Liststr 中去 ,其他则不可以。遍历的时候同样用string遍历出来

List<T>.Count 属性:获取 List<T> 中包含的元素数

Queue<T> 类: 表示对象的先进先出集合。

例 创建具有默认容量字符串队列

Queue<string> q1 = new Queue<string>()

Enqueue 方法将五个字符串进行排队

q1. Enqueue(“字符串1”);

q1. Enqueue(“字符串2”);

q1. Enqueue(“字符串3”);

q1. Enqueue(“字符串4”);

q1. Enqueue(“字符串5”);

ToArray方法用于创建数组,并将队列元素复制到该数组,然后将数组传递给 Queue<T> | | 并将队列元素复制到该数组。

例:Queue<string> q1= new Queue<string>(numbers.ToArray());

Dequeue()方法 用于取消对第一个字符串的排队。

例 q1. Dequeue();

Peek() 方法用于查看队列中的下一项

q1.Peek();

q1.Count 属性 获取 Queue<T> 中包含的元素数。

问题

出现 using System.IO.Ports命名空间不存在问题解决办法

1.   首先检查Visual Studio 中System.IO.Ports程序包是否安装。

检查办法:工具→Nuget包管理器→管理解决方案的Nuget程序包→搜索Ports,或者System.IO.Ports →选择System.IO.Ports→看有没有安装,没有给他装上,不过一般情况下都是有的。

2.   将Api Compatibility Level*(Api兼容级别) 调成.NET 4.x

步骤:Fild(文件)→生成设置→玩家设置→Player→其他设置→Api兼容级别→.NET 4.x

新手第一次上传,有什么错误还请见谅。文章还会再日后的学习中不断的增删改查。

猜你喜欢

转载自blog.csdn.net/podaosanshiliu/article/details/118890566