コードは単純な文字列の送受信操作のみを実装しており、シリアル ポートは閉じられています.コードには詳細なコメントがあり、シリアル ポート通信の学習に使用されるメソッド ノートがあります。
エラー: シリアル ポートが閉じられると、シリアル ポートが異常に読み取られるというプロンプトが表示されます。初心者であり、理由がわかりません。
コードを添付
スクリプトは「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でボタンボタンを作成し、クリックイベントにイベントを作成し、a1をイベントにドラッグし、スクリプトでWriteData()メソッドを参照します。
3. 仮想シリアル ポート vspdconfig をダウンロードしてインストールし、ソフトウェアで仮想シリアル ポート COM3 および COM4 を作成します。
4. シリアル ポート デバッグ アシスタント、XCOM または XTC-ISP などをインストールします。私は XCOM を使用します。
5. シリアル ポート アシスタントを開き、シリアル ポートとして COM4 を選択し、シリアル ポートを開きます。
6. Unity を入力し、[実行] をクリックすると、コンソールにシリアル ポートを開くように求められた後、コンピューター上の文字列シリアル ポート通信が実現され、2 つの当事者間の通信中に ASCII コードが送信されます。
以下は、シリアル通信の学習に使用されるメソッドとクラスです。
注: メソッドとクラスのより優れた詳細な紹介については、VS の .NET ドキュメントを参照してください。
Unity シリアル通信
チュートリアル
名前空間の参照: System.IO.Ports
シリアルポート クラス
プロセスは、通信ポート番号、ボーレート、データ ビット、ストップ ビット、およびパリティ ビットを設定し、ポート接続を開き、データを送信し、データを受信し、最後にポート接続ステップを閉じることです。
使用される名前空間
System.IO.Portsを使用します。
System.IOの使用;
System.Threadingの使用;
システムを使用する;
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.Reference名前空間
Encodingクラスは文字エンコーディングを表します
Encoding.Defaultプロパティを使用して、この .NET 実装の既定のエンコーディングを取得します。Encoding.UTF8属性を使用することをお勧めします。効果は同じかそれ以上であり、データを失うことは容易ではありません。
Encoding. ASCII ASCII (7 ビット) 文字セットのエンコードを取得します。
Encoding.ASCII.GetBytes ( String ) 派生クラスでオーバーライドされると、一連の文字を一連のバイトとしてエンコードします。
Encoding.UTF8.GetString ( Byte[ ] ) : 派生クラスでオーバーライドされると、一連のバイトを文字列にデコードします。
Write() : シリアルポートの出力バッファにデータを書き込みます
WriteLine() : 指定された文字列をシリアル ポートの出力バッファに書き込みます
System.Text.Reference名前空間
StringBuilderクラスは、 変更可能な文字列を表します。このクラスは継承できません。広範な文字列操作を実行するために一般的に使用されるルーチン
オブジェクトをインスタンス化します: StringBuilder s1 = new StringBuilder (" String");
またはStringBuilder s1 = new StringBuilder (" String", String capacity int);
s1.Append は、情報をs1 の現在の末尾に追加します。
StringBuilder オブジェクトを文字列 String に変換します。
s1。ToString ();
StringBuilder オブジェクトによって表される文字列を String パラメータを含むメソッドに渡す前、またはユーザー インターフェイスに表示する前に、StringBuilder オブジェクトを String オブジェクトに変換する必要があります。
クラスを変換
あるデータ型を別の特定のデータ型に変換します。変換可能なデータ型には、ToInt32 、 ToBoolean 、 ToString 、 ToChar などがあります。
例: string s2= Convert . ToString (データ変数名)
yield return new WaitForSeconds(Time.deltaTime); 遅延
OnApplicationQuit() は、 アプリケーションが終了する前にすべてのゲーム オブジェクトに送信されるメソッド API です。エディターでは、ユーザーが再生モードを停止すると、この関数が呼び出されます。
OnDisable()は、動作が無効になったときに呼び出されるメソッド API であり、オブジェクトが破棄されたときにも呼び出され、任意のクリーンアップ コードで使用できます。OnDisable はコンパイル後にスクリプトが再ロードされたときに呼び出され、OnEnable はスクリプトがロードされた後に呼び出され、コルーチンとして使用することはできません。
Threadクラスは、スレッドの作成と制御、優先度の設定、ステータスの取得を行います。
スレッド変数名= new Thread(new ThreadStart ( method ))
variablename.Start ( ); //オペレーティングシステムが現在のインスタンスの状態をRunningに変更し、スレッドによって実行されるメソッドによって使用されるデータを含むオブジェクトを提供することを選択します。
実行中とは、スレッドが開始され、停止していないことを意味します 。
Startメソッドに入れる
データ受信スレッド、データの受信方法はシリアル通信コードに配置
Thread.Sleep (ミリ秒): 現在のスレッドを指定された時間中断します。指定された時間の間、オペレーティング システムはスレッドの実行をスケジュールしません。
スレッドを終了するAbort() メソッドは廃止され、.net5.0 では使用されません。
List<T>クラス
名前空間System.Collections.Generic
List <byte> variable name = new List <byte>(); //配列に似たジェネリック インターフェイスを作成します。byteは 変数型です
List<T>ジェネリック インターフェイス
彼はあらゆるタイプのデータ型を格納できます。
T はList リスト内の要素の型を表します. List<int> の場合, その要素はすべて int 型です.
たとえば、List<string> Liststr = new List<string>();
文字列型のすべてのデータは Liststr に追加できますが、その他のデータはできません。トラバースするときは、文字列でもトラバースされます
List<T> .Count プロパティ: List<T> に含まれる要素の数を取得します。
Queue<T> クラス: オブジェクトの先入れ先出しコレクションを表します。
デフォルトの容量で文字列キューを作成する例
キュー<文字列> q1 = 新しいキュー<文字列>()
Enqueue メソッドは 5 つの文字列をキューに入れます
q1 . Enqueue (" String 1");
q1 . Enqueue (" String 2");
q1 . Enqueue (" String 3");
q1 . Enqueue (" String 4");
q1 . Enqueue (" String 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. まず、System.IO.Ports パッケージが Visual Studio にインストールされているかどうかを確認します。
確認方法:ツール→Nuget Package Manager→ソリューションのNugetパッケージの管理→ポートの検索、またはSystem.IO.Ports→System.IO.Portsの選択→インストールされているかどうかを確認し、彼にはインストールされていませんが、一般的にそれらのすべてがあります。
2. Api Compatibility Level* (Api Compatibility Level) を .NET 4.x に設定します。
手順: フィールド(ファイル)→生成設定→プレーヤー設定→プレーヤー→その他の設定→Api互換性レベル→.NET 4.x
初心者の初投稿です、間違い等ありましたらご容赦ください。この記事は、今後の調査で引き続き追加、削除、修正、およびチェックされます。