LabVIEW串口通信

LabVIEW串口通信

1.串口擴展的問題:

先說一下串口的擴展問題,一般的臺式機或工控機上都至少有二個串口,一般都是夠用的,但是現在市場上已經很難找到帶串口的筆記本了,而有時候在外出調試時需要在筆記本中使用到串口的,這時一般是使用USB-RS232的轉接線,價格從十幾到一百多都有,很多朋友反應在使用價格低的轉接線時會出現亂七八糟的問題,而貴一點的線就很少聽說有其它問題的,所以大家在使用便宜的USB-RS232轉接線時要特別注意線的質量,遇到一些奇怪的問題時先考慮換一根好一點的線。PCI-RS232擴展卡也同理,便宜的卡也容易出問題,儘量買好一點的,以免因小失大。PCI-RS232一般至少能擴展2個串口,有些BT一點的可以擴展到8-16個,一堆線和接頭。轉接線和擴展卡一般是要裝驅動的。

2.串口功能的確認:

在使用串口之前,最好先確認一下串口是否正常,特別是使用轉換接或擴展卡的。檢查的方法很簡單,就是將串口的2、3腳短接起來,3腳是發送數據,2腳接收數據,就是這個串口自發自收。電腦上的串口軟件一般是用串口調試助手,很出名的,也好用。如下圖所示: 圖1 串口調試助手

打開軟件,選擇已經短接好的串口號,點擊"手動發送",如果串口是好的,2、3腳又短接起來了,馬上就可以在上面的接收框裡看到接 收的數據就是發送的數據。稍微要注意一下的是有些電腦的COM1和COM2的位置是反過來的,所以要確定好串口調試助手左上角的串口上擇的是已經短接的那一個,如果COM1沒接收到,可以再先COM2再發一次看一下。

3.串口線的檢查:

檢查好串口後,一般也要注意一下使用的串口線,標準的串口線是9根線都是用上的,但有一些是隻使用了三根線的:2、3、5。第3個腳管是發送,第2個管腳接收,另一個5是地線,這裡叫它簡化的串口線,簡化的串口線能用上的地方,標準的串口線也肯定能用上,因為標準線的9根線已經包括了簡化串口線中的3根線,但標準串口線能用上的地方,簡化串口線就不一定能用上,所以在使用串口線之間一定要確定好串口線的類型,一般買的串口線都是標準線,但自制的串口線因為應用場合不同就要先確定一下。

G串口線還有一個地方需要注意一下的,就是2、3腳的接法,標準接法中是2、3腳交叉的,即這邊的2接另一邊的3,這邊的3接另一邊的2,扭了一下,所以叫交叉線,因為正常使用時,這邊第二腳是發送數據,另一邊第三腳是接收數據,所以要將這二個管腳連接起來,這樣才能正常使用。但是有些情況下,2、3是直連的,即這邊的第2腳連接另一邊的第2腳,第3腳連接第3腳,這種叫直連線,這種線一般是用於延長串口的,比如需要將工控機的串口接頭引到機櫃表面上時,就使用這種線,這樣機櫃表面的串口線的定義還是跟電腦接出來的一樣,外面的那一根串口線再使用交叉線。從電腦主板上將串口引到主機後面板上的線就是這樣的直連線。購買串口線的時候一般也會問你買直連的還是交叉的,要區別對待。

串口線還有一個要稍微注意一下的就是DB頭,因為電腦上接出來的一般是公頭(針),要跟電腦接的話要母頭(孔),一般儀器的串口也是公頭,所以二邊都是母頭的串口線比較常見。串口的接頭一般是DB9的,也有DB25的,但比較少用,有些比較BT的儀器廠家居然用RJ11(水晶頭那種)作為串口頭,讓人不爽!

總之,使用串口前一定要先確定好硬件沒問題,不然很浪費時間的。

4.串口參數設置:

在LabVIEW中使用串口時,有幾個參數比較重要,需要先說明一下的。一個是串口初始化這個節點的"終止符"和"禁用終止符?"這二個輸入端,這二個輸入端是相互作用的,"終止符"默認值為10,它的十六進制是"0x0A",這是一個ASCII碼,是一個換行符,可以從LabVIEW中的字符串的不同顯示形式看出來,如下圖:

LabVIEW串口通信

圖2 串口消息終止符

左邊是字符串的正常顯示,中間是十六進制顯示,右邊是"\代碼顯示",這三個字符串的值都是一樣的。終止符是10,表示在接收數據時,遇到ASCII碼為10的字符(即換行符)時就停止接收數據,後面會有例子進行說明。

而"禁用終止符?"的默認值是FALSE,即啟用終止符,啟用終止符會有什麼效果呢?終止符的意思就是當程序接收到這個字符時,就認為已經到了所有數據的未端了,從而停止接收,不管後面還有沒有數據。終止符是10,表示在接收數據時,遇到ASCII碼為10的字符(即換行符)時就停止接收數據。

可以做一個很簡單的試驗,先短接串口2、3腳,然後將終止符設置為"0x33",0x33是字符"3"的ASCII碼,然後發送字符串可以看到接收回來的數據中只有"12",即"3"被認為是字符串的未端了,它後面的數據就不再接收了。很多朋友就是因為這裡設置錯誤,導致接收數據時有時候只收到一半就沒有了,特別是在連續接收數據時,但又不是每次都只能收到一半,有時候也能接收齊全的,就是因為發送的數據中可能包含了終止符而使串口認為到了最後一個字符了。一般是將這個終止符禁用掉,即將"啟用終止符?(Enable terminator?)"這一端輸入為False即可。

另外還有一個比較重要的設置,就是VISA READ的"讀取字節數"這個輸入,由於在串口通信中,如果指定讀取100個串口緩衝區的字節數,如果當前緩衝區的數據量不足100個時,程序會一直停在VISA READ這個節點上,如果在超時的時間(默認是10秒)內還沒有湊足100個數據的話,程序就會報"Time out"的錯誤,如果超時時間設置得太長,有可能導致程序很長時間停止在VISA READ這個節點上。解決的辦法是使用"Bytes at Port"這個串口的屬性節點,在VISA>>Serial>>advance下,也可以在VISA資源線上右鍵>>創建>>屬性節點>>串口設置>>Bytes at Port,如下圖:

圖 3 Bytes at Port

這個屬性節點讀取當前串口緩衝區有字節數,然後將它的輸出連接到VISA READ的"讀取字節數"這個輸入端上即可,這樣當前緩衝區中有多少個字節就讀回多少個,不會有任何等待。

圖 4 使用Bytes at Port

5.在LabVIEW中使用串口

目前串口的應用一般有二種類型的(以我接觸到的來分類,不嚴格),一種是儀器控制類型的,一般是上位機發送一個指令,然後下位機作出響應,返回數據給上位機,上位機再讀取出來,完成一次通信,即一問一答;另一類是被動接收形的,即下位機會一直髮送數據上來。這二種類型的串口通信在處理上會不太一樣。

5.1 儀器控制類型

由於在儀器控制時一般都是這種一問一答的方式,所以叫它儀器控制類型。以儀器控制為例來說一下需要注意的事項。

首先是要確認儀器選擇的通信模式是串口通信模式。現在的儀器一般都至少有二種通信模式,一種是RS232,一種是GPIB,如果儀器是設置為GPIB通信的話,RS232是不可能通信上的,所以要先確認一下,方法一般是在儀器面板上選擇設置>>遠程控制>>GPIB/RS232,各個儀器稍微不同,可以查儀器手冊看一下。

然後就是確認串口的通信參數的配置,包括波特率、數據長度、校驗方法等,有些儀器的某些參數是固定的,比如校驗方法固定為奇校驗,不能修改,只能在電腦上跟儀器設置為一樣的。波特率一般是可以修改的。這些參數的配置一定要根據儀器手冊上的來設置。如果參數設置不正確,也能收到一些數據,但一般是亂碼,如果收到的數據都是亂碼的話,就要先檢查一下串口參數設置是否正確了。只有電腦和儀器邊的串口參數完全一致時才能收到正確的數據。

接著是要注意發送指令和讀回數據之間要有一定的延時,即VISA WRITE和VISA READ之間要有一定的延時,一般200毫秒即可,因為串口是底層硬件,數據從軟件到串口上要一點點時間,然後儀器對指令作出響應也要一點點時間,這些時間加起來肯定比軟件運行二個節點的時間要短,所以延時是一定要加的。在調試時如果發現正常運行時不能收到數據,但高亮運行就能收到數據,就很有可能是沒有加延時的原因!

或者是發一個查詢指令,但返回的是上一條查詢指令的結果,也可能是因為沒有延時或延時不夠。

5.2被動接收類型

被動接收形的串口通信稍微麻煩一點,由於上位機是被動接收的,上位機不知道什麼時候開始下位機就已經有數據上來了,很有可能下位機發送到一半時,上位機剛好開始接收數據,這時只能接收到後面一半的數據了,所以對於這種通信,一般是採用數據幀的方式進行通信。

這種數據幀的通信方式至少由三部分數據組成:幀頭、數據、幀尾(如果數據是固定長度的話,似乎幀尾也可以省掉)。

幀頭是為了告訴上位機:從這以後的數據就是有用的數據了,相當於約定好的暗號,一般幀頭至少會用二個以上字節,如果只用一個字節的話,萬一數據中的數據跟這個幀頭一樣了就會誤以為這個數據是幀頭從而導致解析數據出錯,幀尾的作用也差不多,告訴上位機從這之前的數據才是有用的數據。但實際上一般的數據幀遠不止這幾個部分,還會加上一些校驗字節、時間信息、幀計數器之類的東東在上面。

其中校驗字節是為了檢查數據在傳輸過程中有沒有出錯的,跟串口的校驗位要區分清楚,校驗位也是檢查數據傳輸時有沒有出錯的,但由底層硬件來實現,校驗方法由標準規定好,但有幾種可以選擇,只有一個位(Bit,只能是0或1)。

校驗字節是由軟件層來實現的,至少有一個字節(Byte,有8個位),而且校驗方式由用戶定義,非常靈活。

由於被動方式中串口的緩衝區中一直會有數據在,為了保持數據的連續性,在讀取數據時跟第一種儀器控制類型不一樣。而是採取將讀取的所有的串口數據都保存在移位寄存器中,在軟件上處理完這些數據後再將它們從移位寄存器中刪除。

由於VISA READ的輸出是字符串,所以一般使用"連接字符串"這個函數將它們連接起來,然後接到循環結構中的移位寄存器中進行保存,當移位寄存器中的數據量達到一定時或滿足數據處理的條件時,才停止這個循環輸出讀取到的數據。一般如下圖所示:

圖 5 被動接收類型中的數據接收

在接收下位機發送的幀數據時,一定要先了解幀格式,這樣才能正確解析出幀裡面的數據來。

下面以例子來說明數據幀格式的通信。

設定通信數據幀每7個字節為一幀數據,其中以0xAC、0x96二個字節作為數據幀頭,第三、四個幀頭為幀計數器,最大值為0xFFFF,到達最大值後重新從0開始計數,第4、5、6三個字節是數據信息,分別代表數據的高中低位,第7位為狀態標誌字節,它的第一位為1時表示下位機出錯,為0時表示功能正常。

由於LabVIEW中接收到的數據都是以字符串的形式顯示出來的,所以需要將字符串轉換為ASCII碼,一般可以直接使用"轉換為U8數組"這個函數,如下圖所示:

圖 5 字符串轉換為U8字節

轉換為U8字節後,得到的是所傳輸字符的ASCII碼,我們就很容易進行數據幀的判斷了,現收到以下的字符串數據:,

©圖 6 實際接收到的字符串

上圖中下半部分顯示的數組是使用"字符串轉換為U8數組"的函數轉換之後得到的數組,一個是十六進制顯示,另一個為十進制顯示。對照定義的數據幀格式,就很容易得到我們需要的數據了。

首先是要看從哪裡開始才是完整的第一幀,從上面十六進制顯示的數組中我們可以看到,並不是第一個字節就是我們需要的幀頭,因為下位機是一直處於發送數據的狀態,很可能在串口發送一幀數據的過程中串口就被初始化或者被清空了一次緩衝區,那麼這一幀數據的前面部分數據可能就會丟失,只留下後面一部分數據。

以上圖為例子,第一二個字節為0x32、0x22,顯示不是我們要的幀頭,我們要的幀頭是在第6、7個字節,以程序來實現的話就是先查找第一個幀頭,使用"搜索字符串",如果找到則判斷它下一個字節是否是第二個幀頭,如果是,表明已經找到幀頭,輸出幀頭的位置;如果它下一個字節不是第二個幀頭,說明這裡不是真正的幀頭,繼續查找下一個幀頭,直到找到幀頭或搜索完整個字符串都找不到幀頭。

這是一個程序的算法問題,具體實現的程序如下圖所示:

圖 7 幀頭查找程序

幀頭查找到以後,再找數據就容易了,根據之前的定義,第4、5、6個字節是才是我們要的數據,所以直接使用索引號進行索引輸出即可。

圖 8 獲取實際數據

一般情況下,如果是用三個字節表示一個數據的話,那麼這三個字節分別表示為一個數據的高中低字節,即高字節要乘以25536再加上中字節乘以256再加上低字節的,這樣定義後可表示的數據的範圍就會擴大很多,但這裡為了說明問題,直接認為三個字節的數據相加就是我們要的實際數據,在實際使用過程中應該根據幀格式的字義來解析這個數據。

另外幀格式中定義了最後一個字節為狀態標誌位,所以提取數據前還要檢查一下這個標誌位是否正常,不正常時要進行相應的處理,這裡不再詳細描述。

至此完成一次數據幀的提取。

如果是沒什麼特殊的要求的話,這裡應該也算到一段落了,有一些對測試時間有要求的地方,就會要求在最短的時間內得到最多的信息。圖6中我們可以看到,接收到的數據幀中,除了中間一個完整的幀之外,頭尾還有一些無用的數據,其實這些數據中也包含了有用的信息的!

比如我們可以從0xAC、0x96這二個幀的位置中推斷中它前面的0x22、0x2A、0x38這三個字節也是我們想要的數據字節,但是由於沒有接收到它的幀頭,所以程序沒能提取出來,但我們可以從後一幀的幀頭推算出前面那一幀的數據字節是哪些,即使沒收到前面那一幀的幀這裡只給出一個流程,不再給出具體的程序。

另外有可能接收的數據長度比較長,可能就不止包含了一幀的數據在裡面,所以在程序中也要判斷一下剩下的數據還夠不夠一幀的數據長度,如果夠則可以根據上一次查找的幀頭位置+數據幀長度來確定下一個數據幀的幀頭位置了,不需要使用搜索的方法。也可能存在處理完一幀數據後,剩下的數據不夠一個幀的,這時可以將這些剩下的數據保留起來,將它添加到下一次接收到的數據前面,組成新的數據再進行處理。去掉已經處理的數據可以使用"刪除數組元素"這個函數來實現。這裡也不再給出具體的程序。

6.串口數據類型的轉換

由於LabVIEW中VISA Read/Write這二個函數都是隻能讀取/寫入字符串類型的數據的,而有時候需要接收/寫入的數據類型不一定是字符串,導致在剛開始接觸的時候會有一點困惑。

在進行數據轉換時,只要記住計算機中所有數據都是以二進制保存這個原則就容易解決問題了。串口線上傳輸的也是高低,串口接收到的也是二進制數據,只是到LabVIEW後被轉換為字符串格式了。還是以例子進行解釋。

6.1LabVIEW從串口接收數據

①假設LabVIEW從串口接收到的數據為"1234"(正常顯示模式下),那麼這個數據在串口底層的時候其實是這樣的二進制數據:

00110001 00110010 00110011 00110100

只是在LabVIEW中,這些二進制數據是以字符串形式顯示出來的,它們的實質還是二進制數據,這幾個二進制數據轉換為十進制數據分別是"49,50,51,52",由於字符串都是以ASCII碼形式保存在計算機中的,那麼49,50,51,52這幾個數在ASCII表中就表示是字符串"1,2,3,4"。所以這幾個數據在LabVIEW中就顯示為字符串的1,2,3,4了。

如果明白這裡面的轉換關係,那麼要進行數據轉換時就很容易了,比如上面的例子中,如果LabVIEW中接收到的是字符串"1234",而原本下位機傳送的是數值型數據,只需要將"1234"字符串轉換為對應的ASCII值就是實際上下位機傳上來的數據了,就是"49,50,51,52"

LabVIEW中將字符串轉換為對應的ASCII值的函數是"字符串至字節數組轉換"這個函數:

圖 9 字符串轉換為字節數組

上面說的是下位機發送的是數值類型的數據的,使用"字符串至字節數組轉換"這個函數.

②如果是下位面發送的是字符串類型的數據,那麼LabVIEW已經直接轉換好了。

個人總結:無論下位機發送的是何種類型的數據,LABVIE從串口接收的時候,總是將每8位二進制數,作為字符的ASCII碼解讀。

6.2使用LabVIEW發送數據

還有一個問題是使用LabVIEW發送數據的問題

①如果下位機接收的是字符串數據類型的話,直接用VISA寫入對應的字符串就行了,現在的儀器一般都是接收字符串的,所以可以直接使用VISA發送而不需要轉換。

②如果下位機接收的是數值型數據的話,就需要轉換一下,其中數值型又是十進制和十六進制二種用得比較多,這二種數據間相互轉換一下就行了,其實是一樣的。

由於在LabVIEW中字符串直接有十六進制的顯示方式,所以發送十六進制的數據比較方便,比如要發送十六進制數值類型的"0xAF",那麼在VISA Write的寫入緩衝區字符串常量上右鍵>>十六進制顯示,如圖1,直接輸入"AF"即可,那麼下位機接收到的就是正確的數據(十六進制數值類型)了。

但實際使用過程中,一般都是需要將某個子VI輸出一個動態的字符串通過VISA Write發送到下位機的,這時候就需要對數據進行轉換一下,這個轉換過程描述起來就是:將字符串A轉換為字符串B,使得正常顯示的字符串A跟十六進制顯示的字符串B是一樣的。

由於轉換目標(十六進制顯示的字符串)的數據類型是十六進制,要想十六進制顯示的字符串跟正常顯示的字符串一樣,這個正常顯示的字符串必須都是十六進制的字符,即只能由0-9,A-F這十六個字母中的字母組合而成。否則就沒辦法使二種顯示方式的字符串一致了。

這個轉換過程首先將字符串轉換為十六進制數值型,然後再通過將這個十六進制數值創建為一個數組,最後再使用"字節數組至字符串轉換"這個函數轉換為字符串即可,實際上就是圖5字符串轉換為U8字節的反向操作,只不過是這個十六進制的值初始類型是十六進制,要先轉換為數值類型。具體程序如下圖所示。

圖 10 正常顯示字符串轉換為相同的十六進制顯示的字符串

由於十六進制數據由二個字節構成,而字符只有一個字符,所以每二個字符表示一個十六進制數據,如果字符多於二個的話要先進行截取,每二個字符轉換為一個十六進制數據。也可以用空格將正常顯示的字符串每二個字符用一個空格斷開,然後先將這個字符串以空格為分隔符轉換為一個字符串數組,再轉換為十六進制數值再轉換為字符串。

需要注意一下的是如果正常顯示的字符串並不是2的整數倍,那麼上圖的轉換程序就會少轉換一個字符,可以用程序動態判斷一下這個字符串的長度,如果是奇數的話在它最左邊補一個"0"再使用上面的程序就正常了。

7.串口問題彙總:

7.1串口資源被佔用:

這時候在LabVIEW會報錯,提示串口號存在,但當前不能對其進行操作,同時打開MAX時也可以在對應的串口號下看到同樣的錯誤,這表示這個串口已經被其它程序佔用了,比如有時候打開了串口調試助手來調試串口,然後又想在LabVIEW裡面試一下,這時就會報這個錯,因為串口已經被串口調試助手調用了, 它不能被二個程序同時使用。

解決的方法是關掉其它程序即可,串口調試助手裡也可以關閉這個串口。

還有一種情況是調試OK後生成EXE,運行EXE也出現這個問題,這時是因為串口被原來的LabVIEW程序打開,再用EXE打開時就會報錯,解決辦法是關掉原來的LabVIEW程序。最好是關掉LabVIEW.

在使用串口的過程中一定要關閉串口(使用VISA CLOSE),否則程序在退出的時候會報錯說數據丟失。


分享到:


相關文章: