明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

在VB下完成無線通信的方法

[摘要]一、 VB串行通信  利用VB開發(fā)通信程序主要的方法有兩種:一是利用VB本身提供的控件(CONTRALS);另一種方法是利用Windows API應(yīng)用程序接口。Windows API 主要提供了三個動態(tài)連接庫(KERNEL.EXE、USER.EXE、GDI.EXE)供開發(fā)人員調(diào)用,其中KERNEL...
一、 VB串行通信

  利用VB開發(fā)通信程序主要的方法有兩種:一是利用VB本身提供的控件(CONTRALS);另一種方法是利用Windows API應(yīng)用程序接口。Windows API 主要提供了三個動態(tài)連接庫(KERNEL.EXE、USER.EXE、GDI.EXE)供開發(fā)人員調(diào)用,其中KERNEL.EXE 主要包括一些底層操作函數(shù),完成一些資源管理、任務(wù)、內(nèi)存等操作;USER.EXE包含了一些與Windows管理有關(guān)的函數(shù),如通信、菜單、消息、光標(biāo)、插入符、計時器以及絕大多數(shù)非顯示函數(shù);GDI.EXE圖形設(shè)備接口庫,主要內(nèi)容為與設(shè)備輸出有關(guān)的函數(shù)。和串口通信有關(guān)系的函數(shù)BuilidCommDCB、ClearCommBreak、SetCommBreak、FlushComm、GetCommError、GetCommState、WriteComm、ReadComm、SetCommState、CloseComm等均在 \Windows\system 子目錄下的USER.EXE動態(tài)連接庫中,在VB調(diào)用之前應(yīng)該先在全局變量定義處聲明API通信函數(shù)、定義常量。

  在VB的控件工具箱中,提供了一個使用非常方便的串行通信控件MSComm,它提供了一個事件OnComm,該事件可以截取串口的任何消息,轉(zhuǎn)入事件處理程序。OnComm事件是唯一的,OnComm可以捕獲通信時發(fā)生的串口事件和錯誤信息,當(dāng)有串口事件或錯誤發(fā)生時,VB會立刻觸發(fā)一個OnComm事件,程序就會自動轉(zhuǎn)入OnComm事件處理程序中。CommEvent屬性是OnComm事件的指示器,該屬性在設(shè)計時不能使用,在程序運行時為只讀,CommEvent 屬性存有最近的事件或錯誤的數(shù)值代碼,可以在程序中隨時讀取CommEvent 屬性值來了解通信的狀況,OnComm事件是和CommEvent屬性密切相關(guān)、一起使用,當(dāng)任何一個OnComm 事件或錯誤發(fā)生時,都會使得CommEvent屬性值改變,在OnComm事件處理過程中,可以通過判斷CommEvent屬性值,對于不同的屬性值轉(zhuǎn)入不同的事件處理過程,一般采用的辦法是SELECT CASE.......END SELECT。由于在無線通信中沒有使用有線Modem,CommEvent 屬性涉及到的有線Modem的屬性數(shù)值代碼和本項目無關(guān)。

  二、無線傳輸接口和協(xié)議

  用Intel 586/120的PC機為上位機,通信程序用VB開發(fā),用8031單片機作CPU、 AD574作數(shù)據(jù)采集的下位機,上位機作數(shù)據(jù)接收和數(shù)據(jù)處理中心站,下位機實時采集數(shù)據(jù)之后,進行簡單的數(shù)據(jù)平均計算,當(dāng)收到上位機發(fā)來的發(fā)送指令之后,開始向上位機發(fā)送數(shù)據(jù)。

  上位機無線通信接口使用的是一塊插在ISA擴展槽中的無線Modem ZX-02,無線Modem與Kenwood公司的TK-378無線對講機相連,數(shù)字信號通過無線Modem調(diào)制成為音頻信號之后,送到TK-378無線對講機上的MIC口。
下位機有一臺外置無線Modem ZX-01,單片機的數(shù)字信號經(jīng)過串口送入無線Modem,Modem對信號進行調(diào)制后送入Kenwood TK-378無線對講機上,接收數(shù)據(jù)的方式與上述相同,由TK-378收到信號后,經(jīng)無線Modem將音頻信號解調(diào)為數(shù)字信號進入計算機或單片機處理。

  由于在通信網(wǎng)絡(luò)中,并非點對點的通信,而是一點對多點的廣播式的通信方式,因此,我們在通信協(xié)議中增加站點識別碼,給下位機編碼可以保證網(wǎng)絡(luò)通信的有序性。

  由于無線通信可能會有空間的燥聲干擾,因此,采取了多項抗干擾措施,首先是包頭識別碼,在發(fā)送了傳輸命令之后,下位機開始以打包的形式傳輸數(shù)據(jù),每一包都有一個包頭和包尾識別碼,假如識別碼有誤,這一次的傳輸為不正常數(shù)據(jù)處理。打包發(fā)送另外一個原因是TK-270對講機連續(xù)發(fā)送數(shù)據(jù)的時間不能超過一分鐘,超過一分鐘就會自動中斷發(fā)送,因此,當(dāng)數(shù)據(jù)較多時不打包連續(xù)發(fā)送的時間就會超過一分鐘,發(fā)送數(shù)據(jù)中斷。

  在下位機中有32KB的NVRAM,可以保存32KB的數(shù)據(jù)。該數(shù)據(jù)可以由上位機發(fā)送清除命令的方法清除掉,當(dāng)32KB滿了以后,最早放入的數(shù)據(jù)就會丟掉,由于采樣速率不高,在慢采的情況下,兩天的時間才能存滿,這樣不論上位機或下位機出現(xiàn)斷電、死機等問題,數(shù)據(jù)不會丟失掉。

  由于使用的無線Modem所限,傳輸速率只能達到2400bps,而在我們的使用中1200bps、N Parity、8 DATA、1 STOP為較穩(wěn)定狀態(tài)。

  上位機向下位機發(fā)送的命令有校時命令、請求內(nèi)存命令、發(fā)送數(shù)據(jù)命令、快采命令和慢采命令等。發(fā)送命令有兩種發(fā)送方式,即手動方式和自動方式,自動方式是由定時器來完成的。


三、 應(yīng)用實例

  由于該項目的軟件源代碼較長,我們只拿出和串口通信有關(guān)的程序片段來供大家參考。在我們的工作中實踐了三種通信方式,即查詢方式、事件驅(qū)動方式、事件驅(qū)動轉(zhuǎn)查詢方式。這三種方式各有利弊,查詢方式方便可靠,可利用協(xié)議或設(shè)定時鐘進入和退出查詢狀態(tài),但不是資源的有效利用方式;事件觸發(fā)方式對于定長通信非常有效,但定長通信在有些場合不實用;事件驅(qū)動轉(zhuǎn)查詢方式既有事件驅(qū)動的特點又有轉(zhuǎn)查詢方式特點,可以說是集二者之長,有效利用資源。下面著重介紹事件驅(qū)動轉(zhuǎn)查詢方式。

  首先在公共模塊中定義和ONCOMM有關(guān)的參數(shù):

  Global Const MSCOMM_EV_RECEIVE = 2‘收到 Rthreshold 個字符。該事件將持續(xù)產(chǎn)生直到用 Input 屬性從接收緩沖區(qū)中刪除數(shù)據(jù)。

  Global Const MSCOMM_ER_RXOVER = 1008‘接受緩沖區(qū)溢出,接收緩沖區(qū)沒有空間。

  Global Const MSCOMM_ER_TXFULL = 1010 ‘傳輸緩沖區(qū)已滿。傳輸字符時傳輸緩沖區(qū)已滿。

  在啟動過程中對串口和輸入輸出緩沖區(qū)初始化:


Sub Form_Load ()
comm1.Settings = "1200,n,8,1" 設(shè)定波特率1200bps,無校驗,8位數(shù)據(jù)位,1位停止位
comm1.CommPort = 1 串口1
comm1.InputLen = 1 一次從輸入緩沖區(qū)中讀取一個字符
comm1.InBufferSize = 512 定義輸入緩沖區(qū)為512字節(jié)(bytes)
comm1.InBufferCount = 0 清空輸入緩沖區(qū)
comm1.OutBufferCount = 0 清空輸出緩沖區(qū)
comm1.PortOpen = True 啟動串口
End Sub


  下面是發(fā)送數(shù)傳命令的子過程,啟動該過程由一個定時器控制:


Sub sample_data ()
comm1.RTSEnable = True 將Modem的PTT置高,同時打開對講機
Call time_delay 適當(dāng)延時
comm1.Output = "*TRNS" + Chr$(13) 發(fā)送命令
Do
該循環(huán)用來檢測命令是否全部發(fā)送完畢
Loop Until comm1.OutBufferCount = 0
Call time_delay
適當(dāng)延時
comm1.RTSEnable = False 將Modem的PTT置低,將對講機改為接受狀態(tài)
comm1.InBufferCount = 0 清空接收緩沖區(qū)
comm1.RThreshold = 1 設(shè)定RThreshold = 1,等待出發(fā)OnComm事件
End Sub


  在OnComm編寫接收和處理代碼:


Sub Comm1_OnComm ()
Select Case comm1.CommEvent
Case MSCOMM_ER_RXOVER 接收緩沖區(qū)溢出,可插入相應(yīng)的代碼
Case MSCOMM_ER_TXFULL 傳輸緩沖區(qū)已滿,可插入處理代碼
Case MSCOMM_ER_RECEIVE 收到1個字符,可進入以下處理過程
comm1.RThreshold = 0 不再響應(yīng)OnComm事件,轉(zhuǎn)入查尋方式接收
ii = 0
iii = 0: sinn = Chr$(42): sinn1 = Chr$(42)初始化變量
Do
duration = Timer + .2 設(shè)定超時退出的時間值
iii = iii + 1
sinn1 = sinn
Do 該循環(huán)判斷輸入緩沖區(qū)是否有數(shù)據(jù)或是否超時
'dummy% = DoEvents()
Loop Until comm1.InBufferCount >= 1 Or Timer >= duration
If Timer >= duration Then
iii = iii - 1
overtime = True 確定超時退出,并非正常退出
Exit Do
End If
sinn = comm1.Input 正常退出,取值付給sinn
If header_er = 0 Then
GoTo test_header
End If
If Asc(sinn) > 175 Or Asc(sinn) < 160 Then 判斷包頭是否正確
iii = 0
GoTo station_number_er 包頭不正確,丟掉該數(shù)據(jù)
End If
test_header:
header_er = 0 包頭正確,接受到包頭,header_er=0
ssin(iii) = sinn 'put date into string dimantion
station_number = Asc(ssin(1))
package_number = Asc(ssin(2))
sentence_number = Asc(ssin(3))
last_character = Asc(ssin(iii))
station_number_er: Loop Until sinn1 = Chr$(10) and
sinn = Chr$(13) 當(dāng)收到正確的包尾0A,0D后退出
If overtime = True Then 如果超時非正常退出
overtime = False
comm1.RThreshold = 1 重新啟動OnComm事件,等待接收下一包
timer6_wait.Enabled = True
GoTo endsub
End If


  以下是接收數(shù)據(jù)正確以后的數(shù)據(jù)處理程序,包括解碼和計算。


If package_number = 1 Then 如果接收數(shù)據(jù)正確,而且是最后一包
timer2_sample.Enabled = True 啟動控制數(shù)傳命令定時器
comm1.RTSEnable = True 置PTT為高
comm1.OutBufferCount = 0 清空輸出緩沖區(qū)
Call time_delay
適當(dāng)延時
comm1.Output = "*MACK" + Chr$(13)發(fā)送清內(nèi)存命令
Do
檢測是否發(fā)送完畢
Loop Until comm1.OutBufferCount = 0
Call time_delay 適當(dāng)延時
comm1.RTSEnable = False 置PTT為低
End If
If package_number > 1 Then 如果不是最后一包
comm1.RThreshold = 1
啟動OnComm準(zhǔn)備接收下一包
timer6_wait.Enabled = True
End If
endsub: header_er = 1: comm1.InBufferCount = 0
'empty inbuffer protect from bed data on the inbuffer
End Select
End Sub