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 }

 

 

 

最后為我微信公眾號引個流,歡迎大家關注我的微信公眾號,大家一起學習一起進步

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM