Unity シリアル通信を習得するための 3 つのステップ
転職したばかりなので、新しい仕事はシリアルポートに関するものですが、ここ数日でいくつかのプロジェクトを実行しましたが、この期間中、インターネット上で明確な記事を見たことがありません。
そこで今日は、シリアル ポートについて知る 必要がある . シリアル ポートとは何ですか? 、 シリアル通信を行うには? .
1.シリアルポートの紹介
シリアルインターフェース(シリアルポート)は通常、シリアル通信を利用した拡張インターフェースであるCOMインターフェースを指します。シリアル ポートはバイトをビット単位で送受信します。バイト単位のパラレル通信よりは低速ですが、シリアル ポートは一方のワイヤでデータを送信し、もう一方のワイヤでデータを受信できます。特に長距離通信に適しています。
シリアル ポートを表示します。[マイ コンピュータ] - [管理] - [デバイス マネージャ] - [ポート] を右クリックして
ポートを選択し、ダブルクリックしてプロパティを表示します。
ここで、シリアル ポートのプロパティを通じて、次のデータを知ることができます。
ボー レート: これは、シンボルの伝送速度を測定するためのパラメータです。
データ ビット: これは、通信における実際のデータ ビットの尺度です。
ストップ ビット: 1 つのパケットの最後のビットを示すために使用されます。
パリティチェック:シリアル通信における簡易なエラー検出方法。
2 つのポートが通信するには、これらのパラメーターが一致している必要があります。
3.シリアルポート通信の原理:
シリアル インターフェイスは、組み込みシステムにおける重要なデータ通信インターフェイスであり、その重要な機能は、CPU とシリアル デバイス間のコード コンバーターとして機能します。データ送信時はシリアルポートを介してCPUからデータを変換し、バイトデータをシリアルビットに変換し、データ受信時はシリアルビットをバイトデータに変換します。
4. 一般的に使用されるプロトコル:
RS-232: 標準シリアルポート、最も一般的に使用されるシリアル通信インターフェイスは、ポイントツーポイント通信用に設計された、いわゆるシングルエンド通信である不平衡伝送モードを採用しています。
RS-422: ポイント対多の双方向通信をサポートします。送信チャネルと受信チャネルが別々に使用されるため、データの方向を制御する必要はなく、デバイス間の必要な信号交換は、ソフトウェア (XON/XOFF ハンドシェイク) またはハードウェア (別々のツイストペア ワイヤのペア) によって実現できます。
RS-485: RS-422 に基づいて開発された RS-485 は、2 線式と 4 線式を使用できます.2 線式システムは、真のマルチポイント双方向通信を実現できます.それは、ポイントツーマルチを実現できます通信ですが、RS-422 よりも優れており、4 線式または 2 線式の接続モードに関係なく、さらに 32 台のデバイスをバスに接続できます。
シリアルポートインターフェース標準仕様 9ピンシリアルポート:
ピン機能:
1.データキャリア検出(DCD)
2.シリアルポート受信データ(RXD)
3.シリアルポート送信データ(TXD)
4.データ端末レディ(DTR)
5.信号接地 (GND)
6. データ送信準備完了 (DSR)
7. データ送信要求 (RTS)
8. 送信可 (CTS)
9. リング インジケータ (RI)
現在、送信にCH340チップを使用しています
2. シリアル ポート プログラミングに C# と Unity を使用する
シリアル ポートをプログラミングするときは、シリアル ポートにコマンドを送信する必要があります。次に、シリアル ポートから返されたコマンドを分析します。.NET Framework 2.0 以降、C# はシリアル ポート制御用の SerialPort クラスを提供します。名前空間: System.IO.Ports。詳細については、(MSDN の技術文書) を参照してください。
1. 一般的に使用されるフィールド:
PortName: 通信ポートを取得または設定します
BaudRate: シリアル ボー レートを取得または設定します
DataBits: 各バイトの標準データ ビット長を取得または設定します
Parity: Getまたは パリティ チェック プロトコルを設定します
StopBits: 各バイトの標準ストップ ビットを取得または設定します
2. 一般的な方法:
Close: ポート接続を閉じ、IsOpen プロパティを false に設定し、内部 Stream オブジェクトを解放します
GetPortNames: のシリアル ポートを取得します現在のコンピュータ Name array
Open: 新しいシリアル ポート接続を開く
Read: SerialPort 入力バッファから読み取る
Write: シリアル ポート出力バッファにデータを書き込む
3. 共通イベント:
DataReceived: SerialPort オブジェクトのデータ受信イベントが実行されることを示します。処理されたメソッドDisPosed: Dispose
メソッドは、(Component から継承された) 呼び出しによってコンポーネントが解放されるときに発生します。次に、ポート接続を開いてデータを送信し、データを受信して、最後にポート接続手順を閉じます。
3. プログラミングで遭遇する問題
1. Unity3D の API プラットフォームが .NET2.0 に切り替えられていない場合、Unity は SerialPort クラスの書き込み時にエラーを報告します。
解決策: Unity3D の API プラットフォームを .NET2.0 に切り替えます。切り替え方法は、「編集->プロジェクト設定->プレーヤー->その他の設定->Api 互換性レベル」です。ここで、".NET2.0 Subset" を ".NET2.0" に切り替えます
。 2. Unity のターゲット プラットフォームが Windows プラットフォームに切り替えられていない場合、名前空間が SystemIO をサポートしていないというメッセージが表示され、ツールを切り替えるように求められます。
解決策: ターゲット プラットフォームを Windows プラットフォームに切り替えます。そうしないと、他のプラットフォームでエラーが報告されます。
3. シリアル ポートから送信された情報を正常に解析できない
解決策: シリアル ポートから送信されたメッセージをバイト ストリームに変換します。(文字ストリーム変換)
4. シリアルポートで受信した情報が欠落している
(1) 受信文字列 (string): port.ReadLine()
データが正しく受信されない、データが失われる、データが受信できない
(2) 受信バイト配列(byte[ ]): port.Read()
はデータフォルトを受信し、完全なデータを 2 回受信します
(3) 1 バイト (byte) を受信: port.ReadByte() は受信
したデータを結合します
、データの末尾が失われることがよくあります(有名なボスで要約され、記事の下部に@大少になります)たとえば、送信:64 64 80 89最初に受信したものは64 80 89 0である可能性があり
ます
解決:
//40405059 暂停
if (paramByte[0] == (byte)64 && paramByte[1] == (byte)64 && paramByte[2] == (byte)80 && paramByte[3] == (byte)89)
{
Debug.Log("AA");
}
else if (paramByte[0] == (byte)64 && paramByte[1] == (byte)80 && paramByte[2] == (byte)89)
{
Debug.Log("AA");
}
上記のコードにより、このピットは完全に回避でき、2 回目は正常になります。
4. ソースコードの共有
次のコードをコピーして貼り付けた後、新しい空のオブジェクトを作成し、それをスクリプトでハングして、シリアル ポート アシスタントで使用します。
using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
public class PortControl : MonoBehaviour
{
#region 定义串口属性
public GUIText gui;
//public GUIText Test;
//定义基本信息
public string portName = "COM3";//串口名
public int baudRate = 9600;//波特率
public Parity parity = Parity.None;//效验位
public int dataBits = 8;//数据位
public StopBits stopBits = StopBits.One;//停止位
SerialPort sp = null;
Thread dataReceiveThread;
//发送的消息
string message = "";
public List<byte> listReceive = new List<byte>();
char[] strchar = new char[100];//接收的字符信息转换为字符数组信息
string str;
#endregion
void Start()
{
OpenPort();
dataReceiveThread = new Thread(new ThreadStart(DataReceiveFunction));
dataReceiveThread.Start();
}
void Update()
{
}
#region 创建串口,并打开串口
public void OpenPort()
{
//创建串口
sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
sp.ReadTimeout = 400;
try
{
sp.Open();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
#region 程序退出时关闭串口
void OnApplicationQuit()
{
ClosePort();
}
public void ClosePort()
{
try
{
sp.Close();
dataReceiveThread.Abort();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
#endregion
/// <summary>
/// 打印接收的信息
/// </summary>
void PrintData()
{
for (int i = 0; i < listReceive.Count; i++)
{
strchar[i] = (char)(listReceive[i]);
str = new string(strchar);
}
Debug.Log(str);
}
#region 接收数据
void DataReceiveFunction()
{
#region 按单个字节发送处理信息,不能接收中文
//while (sp != null && sp.IsOpen)
//{
// Thread.Sleep(1);
// try
// {
// byte addr = Convert.ToByte(sp.ReadByte());
// sp.DiscardInBuffer();
// listReceive.Add(addr);
// PrintData();
// }
// catch
// {
// //listReceive.Clear();
// }
//}
#endregion
#region 按字节数组发送处理信息,信息缺失
byte[] buffer = new byte[1024];
int bytes = 0;
while (true)
{
if (sp != null && sp.IsOpen)
{
try
{
bytes = sp.Read(buffer, 0, buffer.Length);//接收字节
if (bytes == 0)
{
continue;
}
else
{
string strbytes = Encoding.Default.GetString(buffer);
Debug.Log(strbytes);
}
}
catch (Exception ex)
{
if (ex.GetType() != typeof(ThreadAbortException))
{
}
}
}
Thread.Sleep(10);
}
#endregion
}
#endregion
#region 发送数据
public void WriteData(string dataStr)
{
if (sp.IsOpen)
{
sp.Write(dataStr);
}
}
void OnGUI()
{
message = GUILayout.TextField(message);
if (GUILayout.Button("Send Input"))
{
WriteData(message);
}
string test = "AA BB 01 12345 01AB 0@ab 发送";//测试字符串
if (GUILayout.Button("Send Test"))
{
WriteData(test);
}
}
#endregion
}
5. その他の問題
各パソコンのシリアルポートは異なりますが、例えばパソコンAから差し込むと、デバイスマネージャーでCOM2と表示され、プログラムでCOM2が定義されているので、通信が実現できます。
コンピュータ B を変更しても、コンピュータ B のシリアル ポートが COM10 であり、コードがまだ COM2 である場合、通信を完了する方法はありません。
解決策 1: TXT ファイルを読み取って COM ポートを設定します。
public static string portName = "";//串口名称
void Start()
{
string path = Application.streamingAssetsPath + "/config.txt";
string[] strs = File.ReadAllLines(path);
if (strs.Length > 0) portName = strs[0];
Debug.Log(strs.Length);
}
解決策 2: コンピュータのレジストリを読み取って、COM ポートを動的に設定します。
public string getPortName = "";//串口名称
void Start()
{
List<string> protReg = GetPortFromReg();
if (protReg.Count > 0)
{
getPortName = protReg[2];//0是默认第一接口.
}
else
{
Debug.Log("获取不到端口");
}
Debug.Log("当前COM口配置为:"+getPortName);
}
この方法で COM ポートを動的に取得できますが、この方法にはまだ限界があります. 正確にしたい場合は、解決策を使用する必要があります (TXT テキスト構成を介して)。
さて、この記事はここまでです。良い提案や質問があれば、メッセージを残してください!
お世話になります@静純小魔龙https://blog.csdn.net/q764424567