免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
基于Unity串口通信的解決方案

一、簡(jiǎn)介

1、幾個(gè)月前我發(fā)布過一篇關(guān)于Unity的串口通信問題,只是闡述了問題,但是沒有什么好的解決方案。經(jīng)過我?guī)讉€(gè)對(duì)串口相關(guān)的Unity項(xiàng)目開發(fā),也發(fā)現(xiàn)了幾種解決方案。開發(fā)中遇到的一些問題都詳細(xì)的描述出來。
2、在上一篇文章我曾提過Unity因?yàn)椴捎玫氖荕ono .NET 2.0。這個(gè)版本對(duì)COM支持不是很好,所以導(dǎo)致Unity在串口通信方面有些問題。不過最近發(fā)布了Mono .NET4.6版本的Unity 5.5測(cè)試版,該問題可能會(huì)解決掉,不過可能需要等到2017年了。
3、言歸正傳,我們首先要知道C#接收串口的主要幾種方式:接收字節(jié)byte,接收字節(jié)數(shù)據(jù)byte[],接收字符串string。在Unity中往串口中發(fā)送數(shù)據(jù)是為沒有問題的,主要是接收數(shù)據(jù)會(huì)存在問題,下面圖片我總結(jié)了一下,這結(jié)果是我經(jīng)過不下于100次測(cè)試而來的,可能每個(gè)人的測(cè)試結(jié)果都不一樣或我的測(cè)試還有一些局限,如果看到此文章的朋友也有不同的結(jié)果,可以加我QQ或者發(fā)我郵件(1158078383@qq.com)共同探討。本人在此感謝。


還有其他的串口讀取方法,但是我就沒有測(cè)試了,因?yàn)槲覍?shí)際項(xiàng)目中就需要這幾種,所以其他的我就不好意思說。

二、Unity與Winform(WPF)串口通信的幾種解決方案

我開發(fā)過三個(gè)項(xiàng)目采用收發(fā)字符串(Unity接收字符串,發(fā)送字符串)、收發(fā)單個(gè)字節(jié)(Unity接收單字節(jié),發(fā)送字節(jié)數(shù)組)、收發(fā)字節(jié)數(shù)組。三個(gè)項(xiàng)目都是Unity通過串口與Winform程序(或WPF程序)進(jìn)行串口通信。

  • 項(xiàng)目一
    1、該項(xiàng)目有兩種串口接收方式,一種是收發(fā)字符串(Unity接收字符串,發(fā)送字符串),另一個(gè)是收單個(gè)字節(jié),然后對(duì)每個(gè)字節(jié)進(jìn)行組裝解析,在發(fā)送字節(jié)數(shù)組。
    2、經(jīng)過項(xiàng)目的開發(fā)和測(cè)試,我發(fā)現(xiàn)收發(fā)字符串是沒有問題的,但是在我自己寫的測(cè)試程序中卻出現(xiàn)異常,出現(xiàn)數(shù)據(jù)錯(cuò)誤,數(shù)據(jù)丟失以及接收不到數(shù)據(jù)等隨機(jī)性錯(cuò)誤第一篇關(guān)于串口文章)。不過經(jīng)過我發(fā)現(xiàn)實(shí)際項(xiàng)目中的串口收發(fā)格式是有標(biāo)記位和校驗(yàn)位,但是當(dāng)我自己寫程序去測(cè)試時(shí),卻發(fā)現(xiàn)了異常。針對(duì)這個(gè)問題我到時(shí)候后期會(huì)在進(jìn)行仔細(xì)研究下,因?yàn)槲椰F(xiàn)在也沒找到合適的理由去說服自己以及讀者,所以我不會(huì)去做詳細(xì)的介紹只是提醒讀者,后期如果解決了我會(huì)在博客上寫出來。

  • 項(xiàng)目二
    1、該項(xiàng)目是接收字符串?dāng)?shù)組和發(fā)送字符串?dāng)?shù)組,在實(shí)際開發(fā)項(xiàng)目中卻出現(xiàn)了Unity接收數(shù)據(jù)錯(cuò)誤的問題,針對(duì)該問題加上項(xiàng)目時(shí)間緊急,不可在此問題耗費(fèi)我太大心力,所以無意中想到用中間件程序來做Unity與winform程序通信的一個(gè)橋梁。
    2、我寫一個(gè)中間件程序,讓Winform程序與我的中間件程序進(jìn)行串口通信,中間件程序與Unity程序Socket通信
    3、首先啟動(dòng)我的中間件程序,然后中間件程序啟動(dòng)我的Unity程序。中間件程序隱藏起來并與Unity程序互相監(jiān)聽,當(dāng)Unity程序關(guān)閉時(shí),中間件程序也關(guān)閉。這樣從表面上看起來就只是Unity一個(gè)程序在工作,實(shí)際上中間還有一個(gè)中間件程序在做幕后工作。從而巧妙的完成了所謂的Unity與Winform程序之間的串口通信。但是這終究不是一個(gè)很好的解決方案。

  • 項(xiàng)目三
    1、這個(gè)項(xiàng)目三就是我們的重頭戲了,這也是我最新研究的一種解決方案,而且經(jīng)過測(cè)試和實(shí)際項(xiàng)目開發(fā),也是沒什么很大問題的,不過有個(gè)項(xiàng)目會(huì)有一些小問題,但是被我很簡(jiǎn)單的解決掉了。后面我都會(huì)詳細(xì)的講解這個(gè)解決方案,如果有朋友與我闡述的不符,那么可以參考項(xiàng)目二的解決方案給您一點(diǎn)小思路。
    2、該項(xiàng)目采用的是什么呢,首先Winform程序往Unity中發(fā)送字節(jié)數(shù)組,從Unity中讀取字節(jié)數(shù)組數(shù)據(jù)。按照正常的邏輯上我們的Unity也應(yīng)該從串口中讀取字節(jié)數(shù)組和發(fā)送字節(jié)數(shù)組。但是在這一塊出現(xiàn)了問題,上面圖片我闡述過,Unity從串口接收字節(jié)數(shù)組時(shí)會(huì)出現(xiàn)需要兩次才能接收完,第一次接收一個(gè)字節(jié)第二次接收剩下的。數(shù)據(jù)倒不會(huì)出現(xiàn)異常,但是這對(duì)我們的數(shù)據(jù)處理顯然是不好的。針對(duì)此問題,我下面一大章節(jié)來結(jié)合實(shí)際項(xiàng)目來解釋。

三、Unity解析串口數(shù)據(jù),得到完整數(shù)據(jù)

結(jié)合我實(shí)際項(xiàng)目,來講解!以項(xiàng)目三方式為例。
在項(xiàng)目三中說過,Unity中接收單個(gè)字節(jié),并且進(jìn)行組裝,在解析。
1、定義存儲(chǔ)串口數(shù)據(jù)變量

[NonSerialized]private List<byte> listReceive = new List<byte>();//定義一個(gè)泛型,暫時(shí)存儲(chǔ)接收到的串口數(shù)據(jù)。這個(gè)泛型的特性不用理會(huì)。
  • 1
  • 2
  • 3

2、打開串口

 public bool OpenPort(string portName) {    if (this.port != null && this.port.IsOpen == false)    {        try        {            this.port = new SerialPort("\\\\?\\" + portName, 9600);            this.port.ReadTimeout = 500;            this.port.WriteTimeout = 500;            this.port.Open();            this.tPort = new Thread(new ThreadStart(PortReceive));            this.tPort.IsBackground = true;            this.tPort.Start();            return true;        }        catch (Exception err)        {            throw err;        }    }    else    {        throw new System.Exception("串口已經(jīng)打開");    }} /* 代碼解釋: 1)在串口號(hào)前加"\\\\?\\"是因?yàn)槲业拇谔?hào)大于10了,這是因?yàn)槲也捎玫氖翘摂M串口號(hào),為什么要加這個(gè)是因?yàn)?NET2.0的原因,詳細(xì)的可看(http://blog.csdn.net/iothua/article/details/51657106)。 2)代碼中有個(gè)線程,線程有個(gè)方法PortReceive()該方法是讀取串口數(shù)據(jù)的 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

3、打印串口數(shù)據(jù)
這個(gè)打印串口數(shù)據(jù)是一個(gè)方法,就是在Unity中打印接收到的串口數(shù)據(jù),怕讀者看代碼是有點(diǎn)不懂這方法是干嘛的,所以我貼出來。

void PrintData(){    string str = string.Empty;    for(int i = 0; i < listReceive.Count; i++) {        str += listReceive[i].ToString("X2");    }    UnityEngine.Debug.Log("協(xié)調(diào)器打?。? + str+"  字節(jié)長(zhǎng)度:"+listReceive.Count);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4、讀取串口數(shù)據(jù)

 private void PortReceive(){    while (this.port!=null && this.port.IsOpen)    {        Thread.Sleep(1);        try {            byte addr = Convert.ToByte(port.ReadByte());            this.port.DiscardInBuffer();            listReceive.Add(addr);            PrintData();            if(this.PropertyChanged_Coordinator != null) {                this.PropertyChanged_Coordinator.Invoke(this, new PropertyChangedEventArgs("Receive"));                Thread.Sleep(10);                this.PropertyChanged_Coordinator.Invoke(this, new PropertyChangedEventArgs("Send"));            }            //MessageAddReceive(addr.ToString("X2"));            if(EventPortRead != null) {                EventPortRead(new byte[] { addr });            }        }        catch {            //listReceive.Clear();            }    }} /* 解析: 1)byte addr = Convert.ToByte(port.ReadByte());從串口中接收單個(gè)字節(jié),然后轉(zhuǎn)化為byte類型的,默認(rèn)是int類型的。 2)this.port.DiscardInBuffer();清除串口緩存數(shù)據(jù),不過暫時(shí)我沒發(fā)現(xiàn)這個(gè)方法有什么很明顯的用戶。不過先寫著吧。 3)listReceive.Add(addr);添加到泛型中 4)PrintData();打印接收到的數(shù)據(jù) 5)在這里catch下面的代碼最好為空,因?yàn)槲覀兪怯镁€程來接收串口數(shù)據(jù),當(dāng)unity沒有接收到數(shù)據(jù)時(shí),就會(huì)報(bào)異常,所以我們需要在catch下不要寫代碼,本來是有個(gè)屬性可以用的,不過在Unity中存在問題,詳細(xì)的可看我第一篇文章。 6)其他的就不用理會(huì)了,那是我后期的一些處理,跟我們所講沒關(guān)系,之所以全部展示出來也是在實(shí)際項(xiàng)目中的一些處理。 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

從winform程序中發(fā)送數(shù)據(jù)過去


Unity接收到的數(shù)據(jù)情況,發(fā)送數(shù)據(jù)經(jīng)過我們組合后是沒有問題的。

但是當(dāng)我Unity中發(fā)送給上位機(jī)數(shù)據(jù)時(shí),突然unity串口中接收到一個(gè)00數(shù)據(jù),該測(cè)試不是從我寫的測(cè)試程序測(cè)試的,而是從實(shí)際項(xiàng)目中測(cè)試的,但是我在自己寫的測(cè)試程序中又沒有這個(gè)問題。針對(duì)此結(jié)果加上一些數(shù)據(jù)規(guī)律,我后期自己進(jìn)行了改動(dòng)(后面會(huì)詳細(xì)介紹)。
經(jīng)過解析數(shù)據(jù),然后返回給Winform數(shù)據(jù),返回后突然又接到異常數(shù)據(jù)。

Winform接收到的數(shù)據(jù)

5、解析串口數(shù)據(jù)

private void ParseReceive(){    while (true)    {        Thread.Sleep(1);         if(listReceive.Count > 0) {            if(listReceive.Count >= 9) {                if(listReceive[0] == 0xA5 && listReceive[8] == 0x5A) {                    //UnityEngine.Debug.Log("****************************");                    //UnityEngine.Debug.Log("解析接收前******************");                    //PrintData();//打印當(dāng)前接收到的數(shù)據(jù)                    string temp = string.Empty;                    for(int i = 0; i < 9; i++) {                        temp += listReceive[i].ToString("X2");                    }                    listReceive.RemoveRange(0, 9);                    //UnityEngine.Debug.Log("解析接收后******************");                    //PrintData();                    //UnityEngine.Debug.Log("****************************");                    try {                        foreach(Sensor.SensorBase sensor in this.ListSensor) {                        ParameterizedThreadStart pts = new ParameterizedThreadStart(SensorSetData);                        Thread tSetData = new Thread(pts);                        object o = new object[] { sensor, temp };                        tSetData.Start(o);                        }                    }                    catch {                        listReceive.Clear();                    }                }                else if(listReceive[0] == 0x00 && listReceive[8] == 0x5A) {                    listReceive[0] = 0xA5;                }                else {                    int count = 0;                    for(int i = 0; i < listReceive.Count; i++) {                        //截取到泛型中的第一個(gè)5A就好,直接停止循環(huán)                        if(listReceive[i] == 0xA5) {                            count = i;                            break;                        }                    }                    listReceive.RemoveRange(0, count);                }            }        }    }} /* 解析: 1)這是我對(duì)首尾標(biāo)記的檢測(cè),從而截取到我想要的數(shù)據(jù),這個(gè)解析一般是應(yīng)自身項(xiàng)目需求。 //if(listReceive[0] == 0xA5 && listReceive[8] == 0x5A) 2)截取到我想要的數(shù)據(jù),從而轉(zhuǎn)化為字符串。并且從泛型中將這些數(shù)據(jù)移除掉。 string temp = string.Empty;for(int i = 0; i < 9; i++) {    temp += listReceive[i].ToString("X2");    }    listReceive.RemoveRange(0, 9);3)然后解析我得到的數(shù)據(jù),從而通過串口發(fā)送給Winform,這里應(yīng)自身項(xiàng)目需求,所以可不理會(huì)。try {    foreach(Sensor.SensorBase sensor in this.ListSensor) {    ParameterizedThreadStart pts = new ParameterizedThreadStart(SensorSetData);    Thread tSetData = new Thread(pts);    object o = new object[] { sensor, temp };    tSetData.Start(o);    }}catch {    listReceive.Clear();}4)之所以做這個(gè)處理原因是當(dāng)我給Winform程序發(fā)送數(shù)據(jù)時(shí),突然會(huì)接收到異常數(shù)據(jù)0x00,但是我的Winform沒有回?cái)?shù)據(jù),所以這數(shù)據(jù)怎么來的我也不清楚,后期我會(huì)在研究下是我的代碼問題還是其他原因,不過這是我的一個(gè)處理,所以也不需要理會(huì)。else if(listReceive[0] == 0x00 && listReceive[8] == 0x5A) {    listReceive[0] = 0xA5;}5)、當(dāng)數(shù)據(jù)異常時(shí),把異常數(shù)據(jù)處理掉,保證數(shù)據(jù)的正常。else {    int count = 0;    for(int i = 0; i < listReceive.Count; i++) {        //截取到泛型中的第一個(gè)5A就好,直接停止循環(huán)        if(listReceive[i] == 0xA5) {            count = i;            break;        }    }    listReceive.RemoveRange(0, count);}6)從3),4),5)開始都是我對(duì)接收到的串口數(shù)據(jù)一些處理,從而來保證接收數(shù)據(jù)正常,這也是實(shí)際項(xiàng)目中需要干的事情,可能在測(cè)試中不需要。*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

6、總結(jié)
1、上述可能會(huì)讓一些讀者覺得有比較多的漏洞,我后續(xù)如果發(fā)現(xiàn)更好的解決方案和問題,也會(huì)陸續(xù)更新。一方面是記錄下曾經(jīng)問題方便以后,另一方面也是讓Unity開發(fā)串口這邊的開發(fā)者一個(gè)思路和想法吧。因?yàn)槲疑罡写颂幍目印?
2、如果有讀者看到了,有一些好的解決方案、幫助等都可以聯(lián)系我,我們共同探討。我平時(shí)不看自己的博客,所以有需要詳細(xì)的我可以發(fā)郵件給我(1158078383@qq.com)。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
.NET 2.0中串口通訊類SerialPort用法整理
.NET 串口通訊 .
設(shè)計(jì)串口通訊程序
LabVIEW串口通信詳解
使用SerialPort類設(shè)計(jì)串口通訊程序
51串口通訊錯(cuò)誤的實(shí)例分析(數(shù)碼管顯示串口數(shù)據(jù))
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服