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チップを使用しています
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

おすすめ

転載: blog.csdn.net/weixin_45375968/article/details/121760710