zoukankan      html  css  js  c++  java
  • Unity串口通信

    一、串口简介

     串行接口(串口)通常指COM接口,是采用串行通信方式的扩展接口。串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。特别适用于远距离通信。

    1、查看串口:右键 我的电脑-管理-设备管理器-端口,选择一个端口,双击查看属性。

    2、 串口属性:从上图中可以看到串口属性,串口通信最重要的属性参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

    (1)波特率:这是一个衡量符号传输速率的参数。指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数,如每秒钟传送960个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为960Bd,比特率为10位*960个/秒=9600bps。

    (2)数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。

    (3)停止位:用于表示单个包的最后几位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。

    (4)校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。

    3、串口通信原理:

    串行接口在嵌入式系统中是一种重要的数据通信接口,其本质功能是作为CPU和串行设备间的编码转换器。在发送数据时,数据从CPU经串行端口,字节数据转换为串行的位;在接收数据时,串行的位转换为字节数据。

    4、常用的协议:

    RS-232: 标准串口,最常用的一种串行通讯接口采取不平衡传输方式,即所谓单端通讯, 是为点对点通讯而设计的。

    RS-422: 支持点对多的双向通信。采用单独的发送和接收通道,因此不必控制数据方向,各装置之间任何必须的信号交换均可以按软件方式(XON/XOFF握手)或硬件方式(一对单独的双绞线)实现。

    RS-485: 从RS-422基础上发展而来的, RS-485可以采用二线与四线方式,二线制可实现真正的多点双向通信,而采用四线连接时,与RS-422一样只能实现点对多的通信,但它比RS-422有改进,无论四线还是二线连接方式总线上可多接到32个设备。

    串口的接口标准规范9针串口:

    针脚功能:

    1、数据载波检测(DCD)      

    2、串口接收数据(RXD)   

    3、串口发出数据(TXD)

    4、数据终端就绪(DTR)

    5、信号地线(GND)

    6、数据发送就绪(DSR)

    7、发送数据请求(RTS)

    8、清除发送(CTS)

    9、铃声指示(RI)

    二、使用C#和Unity进行串口编程

    在对串口进行编程时候,我们要向串口发送指令,然后我们解析串口返回的指令。从.NET Framework 2.0开始,C#提供了SerialPort类用于实现串口控制。命名空间:System.IO.Ports。详细信息可以参看(MSDN技术文档

    1、 常用的字段:

    PortName:获取或设置通信端口

    BaudRate:获取或设置串行波特率

    DataBits:获取或设置每个字节的标准数据位长度

    Parity:获取或设置奇偶效验检查协议

    StopBits:获取或设置每个字节的标准停止位数

    2、 常用方法:

    Close:关闭端口连接,将IsOpen属性设置false,并释放内部Stream对象

    GetPortNames:获取当前计算机的串行端口名称数组

    Open:打开一个新的串行端口连接

    Read:从SerialPort输入缓冲区中读取

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

    3、常用事件:

    DataReceived:表示将处理SerialPort对象的数据接收事件的方法

    DisPosed:通过调用释放组件时发生Dispose方法(继承自Component)

    4、SerialPort 控件使用流程

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

     三、编程遇到的问题

    1、没有将Unity3D的API平台切换成.NET2.0,这时Unity编写SerialPort类会报错。

    解决方法:将Unity3D的API平台切换成.NET2.0,切换方法: “Edit–>project Setting–>Player–>Other Setting –>Api Compatibility level”。在这里将“.NET2.0 Subset”切换为“.NET2.0”

    2、Unity的目标平台没有切换为Windows平台,会提示该命名空间不支持SystemIO,提示你切换工具。

    解决方法:把目标平台切换为Windows平台,否则是其他平台会报错误。

    3、串口发送的信息不能正常解析

    解决方法:把串口发送的消息使用字节流进行转换。(字符流转换)

    4、串口接收信息的缺失问题

    (1)接收字符串(string):port.ReadLine()

    数据接收可能错误,数据丢失,数据接收不到

    (2)接收字节数组(byte[]):port.Read()

    接收数据断层,会分两次接收完整数据

    (3)接收单个字节(byte):port.ReadByte()

    将接收到的数据进行组合

    代码可以直接使用,测试有效,直接复制到Unity脚本中和串口调试助手配合使用即可。

      1 using UnityEngine;
      2 using System.Collections;
      3 using System.IO.Ports;
      4 using System;
      5 using System.Collections.Generic;
      6 using System.Threading;
      7 using System.Text;
      8 
      9 public class PortControl : MonoBehaviour
     10 {
     11     #region 定义串口属性
     12     public GUIText gui;
     13     //public GUIText Test;
     14     //定义基本信息
     15     public string portName = "COM3";//串口名
     16     public int baudRate = 9600;//波特率
     17     public Parity parity = Parity.None;//效验位
     18     public int dataBits = 8;//数据位
     19     public StopBits stopBits = StopBits.One;//停止位
     20     SerialPort sp = null;
     21     Thread dataReceiveThread;
     22     //发送的消息
     23     string message = "";
     24     public List<byte> listReceive = new List<byte>();
     25     char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
     26     string str;
     27     #endregion
     28     void Start()
     29     {
     30         OpenPort();
     31         dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
     32         dataReceiveThread.Start();
     33     }
     34     void Update()
     35     {
     36 
     37     }
     38 
     39     #region 创建串口,并打开串口
     40     public void OpenPort()
     41     {
     42         //创建串口
     43         sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
     44         sp.ReadTimeout = 400;
     45         try
     46         {
     47             sp.Open();
     48         }
     49         catch (Exception ex)
     50         {
     51             Debug.Log(ex.Message);
     52         }
     53     }
     54     #endregion
     55 
     56 
     57 
     58     #region 程序退出时关闭串口
     59     void OnApplicationQuit()
     60     {
     61         ClosePort();
     62     }
     63     public void ClosePort()
     64     {
     65         try
     66         {
     67             sp.Close();
     68             dataReceiveThread.Abort();
     69         }
     70         catch (Exception ex)
     71         {
     72             Debug.Log(ex.Message);
     73         }
     74     }
     75     #endregion
     76 
     77 
     78     /// <summary>
     79     /// 打印接收的信息
     80     /// </summary>
     81     void PrintData()
     82     {
     83         for (int i = 0; i < listReceive.Count; i++)
     84         {
     85             strchar[i] = (char)(listReceive[i]);
     86             str = new string(strchar);
     87         }
     88         Debug.Log(str);
     89     }
     90 
     91     #region 接收数据
     92     void DataReceiveFunction()
     93     {
     94         #region 按单个字节发送处理信息,不能接收中文
     95         //while (sp != null && sp.IsOpen)
     96         //{
     97         //    Thread.Sleep(1);
     98         //    try
     99         //    {
    100         //        byte addr = Convert.ToByte(sp.ReadByte());
    101         //        sp.DiscardInBuffer();
    102         //        listReceive.Add(addr);
    103         //        PrintData();
    104         //    }
    105         //    catch
    106         //    {
    107         //        //listReceive.Clear();
    108         //    }
    109         //} 
    110         #endregion
    111 
    112 
    113         #region 按字节数组发送处理信息,信息缺失
    114         byte[] buffer = new byte[1024];
    115         int bytes = 0;
    116         while (true)
    117         {
    118             if (sp != null && sp.IsOpen)
    119             {
    120                 try
    121                 {
    122                     bytes = sp.Read(buffer, 0, buffer.Length);//接收字节
    123                     if (bytes == 0)
    124                     {
    125                         continue;
    126                     }
    127                     else
    128                     {
    129                         string strbytes = Encoding.Default.GetString(buffer);
    130                         Debug.Log(strbytes);
    131                     }
    132                 }
    133                 catch (Exception ex)
    134                 {
    135                     if (ex.GetType() != typeof(ThreadAbortException))
    136                     {
    137                     }
    138                 }
    139             }
    140             Thread.Sleep(10);
    141         }
    142         #endregion
    143     }
    144     #endregion
    145 
    146 
    147 
    148     #region 发送数据
    149     public void WriteData(string dataStr)
    150     {
    151         if (sp.IsOpen)
    152         {
    153             sp.Write(dataStr);
    154         }
    155     }
    156     void OnGUI()
    157     {
    158         message = GUILayout.TextField(message);
    159         if (GUILayout.Button("Send Input"))
    160         {
    161             WriteData(message);
    162         }
    163         string test = "AA BB 01 12345 01AB 0@ab 发送";//测试字符串
    164         if (GUILayout.Button("Send Test"))
    165         {
    166             WriteData(test);
    167         }
    168     }
    169     #endregion
    170 }

    最后为我微信公众号引个流,欢迎大家关注我的微信公众号,大家一起学习一起进步

  • 相关阅读:
    TRichView文档结构2
    Qtablewidget 复杂表头
    Qwt 使用mingw编译安装过程(windows):
    [转]为什么有的人工作多年还是老样子?
    软件公司书籍推荐——按角色划分
    Qt error: one or more PCH files were found, but they were invalid
    qt5.5程序打包发布以及依赖【转】
    Qt5.5.1编译出来的程序出现libgcc_s_dw2-1.dll的解决方案
    值得推荐的C/C++框架和库
    开发资源汇总
  • 原文地址:https://www.cnblogs.com/damonHead/p/9243130.html
Copyright © 2011-2022 走看看