- Part1 中講了幾個比較棘手的問題,這部分給出一些解決思路,這種思路肯定不是最優(yōu)解,但至少解決了現(xiàn)有問題,而且成功避開了一些麻煩,如果各位看官又更好的思路,還希望留言討論
- 因為Unity中沒有 SerialDataReceivedEventHandler,所以我果斷選擇了用C#控制臺來接收和發(fā)送數(shù)據(jù),這樣更加方便,而且開多個線程也不會造成莫名其妙的無響應(yīng)。
- 至于怎么將數(shù)據(jù)傳給Unity?各位看官肯定有思路??!所以我選擇socket!各位看官又更好的思路歡迎討論……
Tip:SerialDataReceivedEventHandler 是一個委托,當(dāng)COM設(shè)備向控制臺發(fā)送數(shù)據(jù)時,該委托掛載的方法便會執(zhí)行
- OK,接下來上代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Net.Sockets;
using System.Net;
using System.Threading;
//向COM端發(fā)送數(shù)據(jù) DD,其實是byte的221
//COM端接收到正確的數(shù)據(jù)后,會向控制臺發(fā)送回數(shù)據(jù)
//數(shù)據(jù)格式類似于 255 255 171 0 34 136 42 12 171
//前兩位,即使255,255 無實際作用,表示數(shù)據(jù)開始
//中間兩位,表示實際數(shù)據(jù)部分,具體處理方法見 ProcessingData
//最后4位,CRC32驗證,驗證前面4位是否正確(該功能未完成)
namespace COM_Socket_Server
{
class Program
{
//COM端口的各類設(shè)置
//COM口
private static SerialPort ComDevice = new SerialPort();
//用于存儲8個BYTE
static List<byte> AllDatas = new List<byte>();
//公共參數(shù)部分
//存儲COM設(shè)備返回并處理完成的角度值,用于傳遞給unity
private static string toClientMessage = null;
static void Main(string[] args)
{
//COM端口初始化
COM_Init();
//單獨開啟一個線程檢測COM狀態(tài)
Thread COMThread = new Thread(SendMsgToCOM);
COMThread.Start();
}
//COM初始化方法
private static void COM_Init()
{
//定義串口初始化參數(shù)
ComDevice.PortName = "COM3"; //COM口名稱
ComDevice.BaudRate = 9600; //波特率
//開打串口
ComDevice.Open();
//串口打開后掛載回調(diào)事件
if (ComDevice.IsOpen)
{
ComDevice.DataReceived += new SerialDataReceivedEventHandler(ComDevice_DataReceived);
Console.WriteLine("COM端口已經(jīng)打開");
}
else
{
Console.WriteLine("error");
}
}
//循環(huán)向COM設(shè)備發(fā)送信息
private static void SendMsgToCOM()
{
while (true)
{
//向COM設(shè)備發(fā)送221,其實是字符串“DD”
//發(fā)送后COM設(shè)備會被觸發(fā)
byte[] byt = new byte[1];
byt[0] = 221;
ComDevice.Write(byt,0,1);
這里將Sleep的值設(shè)置的略長,為了能在第二次“DD”發(fā)送之前,分好幾次完全接收了COM設(shè)備發(fā)送的信息
Thread.Sleep(500);
}
}
//回調(diào)方法,在收到COM設(shè)備發(fā)送的消息后調(diào)用
private static void ComDevice_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//聲明一個 byte數(shù)組 用來存儲接收到的數(shù)據(jù)
byte[] ReDatas = new byte[ComDevice.BytesToRead];
//讀取數(shù)據(jù)
ComDevice.Read(ReDatas, 0, ReDatas.Length);
//由于COM設(shè)備的特性,8個byte并不是一次全部傳輸過來,而是分多次
//所以將多次接收的結(jié)果先都存儲在一個list中
foreach (var item in ReDatas)
{
AllDatas.Add(item);
}
//驗證list的長度
//如果長度為8,則開始用后4位的CRC32驗證前面4位的正確性(缺少此步驟)
if (AllDatas.Count == 8)
{
//Console.WriteLine("數(shù)據(jù)長度正確,長度為8");
ProcessingData(AllDatas[2], AllDatas[3]);
//所又步驟完成后清空list,下次接收時所有又從0開始
AllDatas.Clear();
//此處還應(yīng)該用最后2位做CRC校驗
}
else
{
Console.WriteLine("數(shù)據(jù)長度出錯!");
//此處并不能只單純的驗證list的長度,而應(yīng)該先驗證整個list的開頭是否位兩個255,然后再看實際數(shù)據(jù)位是否完整
//AllDatas.Clear();
}
}
//處理數(shù)據(jù)位
private static void ProcessingData(byte b1, byte b2)
{
//將數(shù)據(jù)放入一個byte數(shù)組中,轉(zhuǎn)換成int16格式
byte[] bb = new byte[2];
bb[0] = b1;
bb[1] = b2;
Int16 i16 = BitConverter.ToInt16(bb, 0);
//這里將轉(zhuǎn)換出來的數(shù)值進行一次運算才能變?yōu)樾枰慕嵌戎? int i2 = Convert.ToInt32(i16);
float angel = 360 * (i2 * 1.0f / 1023.0f);
Console.WriteLine(angel.ToString());
toClientMessage = angel.ToString();
}
}
}