2 仿真模塊的設計
在實際的工程項目中,數據采集模塊和控制模塊一般采用RS-485接口,因為這種接口只需要兩根連接線,施工方便,同時,傳輸距離可以達到1200米左右。一般計算機都配有RS -232接口,可以通過RS-232/RS-485轉換器進行轉換,從而實現計算機與RS-485接口的模塊進行通信。所以,仿真模塊采用RS-232接口。仿真模塊的主界面如圖1所示。
圖1 AI/DO-M 仿真模塊的主界面
圖1左部是硬件實物的抽象,工作狀態指示燈紅燈表示空閒,綠燈表示正在工作。 Power 指示燈為綠色表示本模塊已加電,Tx 指示燈為綠色表示本模塊正在發送數據,Rx指示燈為綠色表 示本模塊正在接收數據。下部是兩個溫度傳感器,數據范圍為00-0xFF,分別對應溫度0-100℃。上部的 兩個輸出開關由主控程序通過串行接口控制,如果 OUT0開關閉合,則形成一個環路,燈亮,對應的溫度 傳感器S1升溫,紅色箭頭朝上,數據遞增;否則,對應的傳感器溫度下降。圖1的右部主要是通信協議的 描述,通信協議是操作模塊的約定。通信協議制訂了三種,即讀(Read)協議、響應(Reply)協議和寫 (Write)協議。Read 協議用來讀取模塊中的數據,EOT 是前導字符,ID 是模塊的地址,RD 是讀標志 ,BCC 是校驗碼,EM 是結尾碼。 Reply 協議是對 Read 協議的響應,STX 是前導字符,DT1 和 DT2 是 傳感器的兩個溫度字節,DO 是輸出開關的狀態,OUT0 和 OUT1 使用一個字節的最低兩位,1表示開關閉 合,0表示開關打開。Write 協議的 WT 是寫標志。三條協議的下部是對協議中的字符的說明,如 EOT 表示字節 04,WT 用 0x57 來表示等等。
Receive 文本框中顯示收到的主控機發送的 Read 協議 或 Write 協議。Send 文本框中是仿真模塊發送給主控機的 Reply 協議。
Setup 按鈕顯示模塊參數設置窗體,如圖2所示。Port Setup 頁簽用來設置串口相關的參數,Protocols Setup 頁簽設置協議參數,包括協議的校驗碼與結尾碼。ID 文本框設置模塊的地址,Interval 文本框設置以 秒為單位的時間間隔,Step 表示步長,圖2所示,表示仿真模塊每過6秒,傳感器的數值上升(如果對應 的輸出開關閉合)或下降(如果對應的輸出開關打開)5。所設置的參數都通過 My.Settings 方法保存 ,下次打開程序,將恢復這些數據。
使用仿真模塊時,必須先點擊 Setup 按鈕設置參數,然後 ,點擊 Power 指示燈,使其變綠,這時,仿真模塊工作。通過1.4節的方法收到數據後進行處理,如果 是主控機發送的 Read 協議,則將模塊的當前數據組裝成 Reply 協議,調用 1.3 節中的 SendData 函 數發送出去。如果是Write 協議,則調用 1.1 節中的SetByteBit 和 ResetByteBit 函數進行置位或復 位,然後,調用 CheckByteBit 函數,來顯示輸出開關的狀態,如果對應的位為1,就顯示紅線,表示開 關閉合;如果對應的位為0,就隱藏紅線,表示開關打開。
主窗體中用 timer_Comm 定時器配合 數據的接收,用 timer_Signal 定時器來控制 Tx 與 Rx 指示燈的閃爍,用 timer_Step 定時器 (Interval 屬性由圖2設置)來調整傳感器的字節數據。
3 主控程序的設計
仿真模塊提 供了一個串行接口,用於教學強於實物模塊,因為是免費的,接口是真實的,可視化效果和方便程度遠 勝於實物模塊。可以用匯編語言、C語言和 Java 語言開發應用程序對該仿真模塊進行監控,使學生的學 習更有針對性,也能激發學生的學習興趣。這裡提供了一個用 Visual Basic 2008 開發的主控程序,其 主界面如圖3所示。
圖3 主控程序的主 界面
首先,點擊 Setup 按鈕,進行參數設置,出現類似圖2所示的界面,但是,Protocols Setup 頁簽的底部如圖4所示,其中,Interval 表示主控機查詢仿真模塊的時間間隔。根據采樣定律, 圖4的Interval 應該小於等於圖2的Interval 的一半。Up 是溫度的上限,Down 是溫度的下限。主控程 序的串口參數、校驗碼、結尾碼、地址碼應該與仿真模塊的一致,而且,應該有串行通信電纜連接(當 然,也可以使用虛擬串口),雙方才能通信,完成監控。
假如烘箱用燈泡加熱 ,每個烘箱中均有一個溫度傳感器。主控程序每過2秒查詢一次仿真模塊,即發送一次 Read 協議。對於 響應的數據,提取溫度字節,然後,轉換為0-100℃的數值,實時顯示,同時,繪制曲線。對於輸出開關 的狀態,用指示燈表示,綠燈表示閉合,紅燈表示打開。主控程序以手動(Manual)和自動(Automatic )兩種方式工作,如果在自動狀態,則溫度超過上限60將發送控制命令(Write 協議),使得相應的輸 出開關打開;如果溫度低於下限50,則發送控制命令,使得相應的輸出開關閉合加熱。自動狀態,控制 按鈕 On/Off 無效。手動狀態,可以直接通過 On/Off 按鈕控制輸出開關。
4 輔助工具的設計
RS-232/RS-232 轉換器管理兩個串行接口,因而,可以將兩個不同通信協議和不同波特率的主控 機或受控機連接起來。主控設備可與COM1相連,受控設備與COM2相連,協議轉換器將一個接口收到的數 據進行協議變換後發送到另一個接口。通過此協議轉換器,主控和受控設備之間的接口參數,如波特率 等可以不一樣,協議格式也可不一致,這對改造原裝設備具有重要意義,而且,在協議轉換過程中,可 以直接截取主控設備和受控設備之間的通信協議,並記錄接口引腳信號的變化情況,加上時間戳,便於 分析和處理。
RS-232/RJ-45協議轉換器軟件的主要功能是用軟件轉換器來實現硬件轉換器的功能 ,實現串口數據與網口數據的直接轉發,不涉及到通信協議的變換。串口只要進行常規的設置,與所連 接設備的串口參數一致。由於主控機與嵌入式模塊之間一般采用串口進行連接,另外,數據采集模塊也 大部分采用串口,因而,通過該協議轉換器,可以將此類串口設備連接到Internet,進行遠程處理。
圖5所示是一個遠程 串行通信協議截取模型,配備串口的主控機通過運行RS232/RJ45協議轉換器的現場PC將數據直接發送到 遠程PC,對方收到後,將數據通過RS232/RJ45轉換器發送到RS232/RS232轉換器,再通過RS232/RJ45轉換 器將數據發送到現場PC,該數據包又通過RS232/RJ45轉換器,轉換成RS232接口的數據包,發送到受控機 。至於遠程調試技術也類似,不過,都需要工程師與用戶進行遠程協作,如通報IP地址與端口地址,采 用服務器還是客戶機方式進行連接等。
RS232/RS232 協議轉換器采用第1節的技術即可處理, RS232/RJ45 涉及到關於 TCP 客戶機/服務器的編程,需要使用 .NET Framework 3.5 中的 TCPClient 和 TCPListener 類,還需要多線程編程技術。
5 通用串口設備測試工具的設計
通用串口 設備測試工具(TestPort)可以自動生成多種校驗碼及添加多種結尾碼,既可以充當主控機對受控機進 行測試,也可以充當受控機對主控機進行測試,並可以記錄測試結果和通信協議。為了便於工具的使用 ,采用 Access 充當數據庫,通信協議都保存在數據庫中。圖6所示是該工具的主窗體,打開該程序後, 必須先設置工作參數方可使用。Hex 和 Char 文本框中是以兩種方式顯示的當前收發的數據包,下面的 多行文本框顯示收發數據及引腳信號變化的詳細歷史數據,便於分析使用。
圖6 通用串口設備測試工具的主窗體
5.1 主要功能
TestPort 的工作模 式分為三種:Normal、Master 與 Slave,如圖7所示(圖6點擊Setup)。Normal 為標准模式,用於手工 發送數據,只要在圖6中的Hex 文本框中輸入16進制字符串或在Char 文本框中輸入字符串,點擊 Send 即可。圖7中的顯示模式(Display Mode)表示用字符形式還是16進制字符串顯示收發的數據,對於調制 解調器,顯然使用 Char 模式更直觀。Length 文本框中是協議的最大字節長度,根據該數據和波特率計 算數據包的時間間隔。Sound 選項表示收到數據是否用聲音提示。
Master 為自動主控機模式,即每隔 1000 毫秒(當前 Interval 設置),自動逐條讀取數據庫中的主控機協議 (Master)發送出去,如圖8所示(通過菜單項 Protocols 打開)。如果核選了 Error,則自動記錄受 控機的錯誤響應數據包(結尾碼 End Mark 與 數據包校驗碼 Group Parity 至少有一個不為 None), 並對數據進行統計分析,測試報告如圖9所示(通過菜單項的 Report 打開)。窗體標題顯示了測試的時 間段,上方的表格顯示錯誤的發生時,開機以來所經歷的毫秒數,以及當前時間,隨後是錯誤數據(校 驗碼或結尾碼或兩者都發生錯誤)。下方的表格顯示統計數據,即主控機共發送28條協議,正確21條, 錯誤2條,沒有響應5條,正確率為 75%. 統計數據以文本文件保存,點擊 Save 按鈕即可保存到文本中 。如果在圖7核選了 Protocols,則自動記錄受控機協議,存入圖8的協議庫中。
以Slave 方式工 作時,TestPort 將收到的協議去掉校驗碼和結尾碼後,與圖8中的 Master 協議逐條比較,如果相等, 並且,對應的 Slave 協議不為空,則自動發送該 Slave 協議作為對主控機協議的響應。如果在圖7中核 選了 Protocols,則對於數據庫中沒有的 Master 協議,將自動記錄。
另外, TestPort 還可用來通過調制解調器撥打電話,如圖10所示。Out 文本框中的9表示撥打外線電話需要先 撥9,Local length 文本框中的4表示內線電話號碼的長度為4。點擊第1條記錄,然後點擊 OK 按鈕,將 生成內線電話的一個 AT 命令“ATDT1234;”;點擊第2條記錄(市話),將生成AT命令 “ATDT9,12345678;”,自動添加了外線號碼9;點擊第3條記錄(長途),將生成AT命令 “ATDT9,17909,025-12345678;”,自動添加了 IP 號碼 17909。AT 命令生成後,在圖6中點 擊菜單項或快捷方式的 Dial,將自動向調制解調器發送 AT 命令,完成撥號,如果發現占線,重新點擊 Dial 即可,因為 Dial 先關閉串口片刻, 然後,再打開串口發送數據,有電話機的“閃斷 ”功能。
5.2 受控機協議的動 態生成技術
圖8的第1條受控機協議(Slave)中有6個“*”號,表示3個隨機字節,來 模擬動態的仿真模塊的 Reply 協議(見圖1)。帶“*”號的受控機協議作為 RandomPackage 函數的參數,最後返回將“*”號替換成隨機字節的16進制字符串。其中的 oString 是一個 自定義字符串處理類的對象,FeatureCount 函數(定義略)僅完成第一個字符串中包含的第二個子字符 串的個數;ReplaceSubString 函數將 strData 中第一次出現“**”的地方用 strTmp 替代 。
Public Function RandomPackage(ByVal strData As String) As String
Dim strTmp As String
Dim I As Integer = 0
Dim rnd As New Random
'計算隨機字節的個數
Dim nCount As Integer = oString.FeatureCount(strData, "**")
Dim ByteBuffer(nCount - 1) As Byte '定義數組存放隨機字節
rnd.NextBytes(ByteBuffer) '產生隨機字節放入數組
Do While nCount > 0
strTmp = ByteToTwoHexChars(ByteBuffer(I)) '字節轉換為16進制字符串
'2個 ** 用2個16進制字符替換
strData = oString.ReplaceSubString(strData, "**", strTmp)
I += 1
nCount = oString.FeatureCount(strData, "**")
Loop
Return strData
End Function
如圖8配置通信協議 ,將 TestPort 設置為自動受控機,配合第3節的主控程序,截取的Oven2 的溫度曲線如圖11所示,跟圖 3相比,顯然非常隨機。主控程序正常測試,不知道已經將仿真模塊替換成了 TestPort 工具。
5.3 數據庫與DataGridView的使用技巧
RS-232/RS-232 協議轉換器有協議截取功能, 截取的通信協議可以直接供 TestPort 使用。這些工作都離不開數據庫的操作。本文還設計了 ADO_NET_ACCESS 類,用來處理 Access 數據庫,首先根據數據庫(包括絕對路徑)獲取連接字符串 ConnectionString,然後,完成數據庫的初始化(New)。WriteData 方法用來更新數據庫。
GetAccessConnection 方法用來獲取 ConnectionString。首先聲明一個 OleDbConnectionStringBuilder 對象 csb,顯然,數據庫的類型是確定的,其 Provider 也隨之而定; DataSource 是包含數據庫的絕對路徑,如果不為空,即返回構造完畢的 ConnectionString。
Private Function GetAccessConnection(ByVal strDB As String) As String
Dim csb As OleDbConnectionStringBuilder = _
New OleDbConnectionStringBuilder()
csb.Provider = "Microsoft.Jet.OLEDB.4.0"
csb.DataSource = strDB
If strDB = "" Then
Return ""
Else
Return csb.ConnectionString
End If
End Function
ADO_NET_ACCESS 類的構造函數 New 有兩個參數,strDB 是數據庫名,strCommand 是 SQL 語句,用 來選擇一個表。調用 GetAccessConnection 方法獲得 ConnectionString 後,即可調用數據庫適配器 OleDbAdapter 的構造函數,得到初始化後的對象 _adapter(全局變量,定義略)。通過字符串操作, 在 _strCharSet 中找到表名,映射到 DataSet 中。最後,填充數據集 DataSet 對象 ds,數據表 DataTable 對象dt 和表的數目。如果有錯誤,則表的數目為0,錯誤提示保存到變量中。
Public Sub New(ByVal strDB As String, ByVal strCommand As String)
'permit only one select with primary key
_strConnection = GetAccessConnection(strDB)
_strCharSet = strCommand
_adapter = New OleDbDataAdapter(_strCharSet, _strConnection)
'以下代碼獲取表的名稱
Dim nLocation As Integer = InStr(_strCharSet, "From", CompareMethod.Text)
Dim strTmp As String = Mid(_strCharSet, nLocation + 5)
Dim J As Integer = 1
Dim strSub As String = Mid(strTmp, J, 1)
Do While strSub <> " " And strSub <> ";" And strSub <> ""
_strTableName &= strSub
J += 1
strSub = Mid(strTmp, J, 1)
Loop
'將表的名稱映射到 DataSet 中,以便使用
_adapter.TableMappings.Add("Table", _strTableName)
_ds = New DataSet
Try
_adapter.Fill(_ds)
_dt = _ds.Tables(0)
_nTables = 1
_strErrorAdapter = ""
Catch ex As Exception
_nTables = 0
_strErrorAdapter = ex.Message
End Try
End Sub
數據庫的更新是一個非常繁瑣的操作,WriteData巧妙地利用了OleDbCommandBuilder對象,可以 對Update、Delete 和 Insert 命令造成的數據庫變化進行統一的更新。如果更新成功,則返回0;否則 返回1,並保存錯誤提示信息。
Public Function WriteData() As Integer
Dim cmdBuilder As OleDbCommandBuilder = _
New OleDbCommandBuilder(_adapter)
_adapter.UpdateCommand = cmdBuilder.GetUpdateCommand
_adapter.DeleteCommand = cmdBuilder.GetDeleteCommand
_adapter.InsertCommand = cmdBuilder.GetInsertCommand
Try
_adapter.Update(_ds)
_strErrorWrite = ""
Return 0 'Success
Catch ex As Exception
_strErrorWrite = ex.Message
Return -1 'Error
End Try
End Function
ADO_NET_ACCESS 類提供的外部可見的只讀屬性如表1所示,這些屬性可以方便地用於數據庫操作以及 在 DataGridView 控件中使用。
在一個窗體中顯示數 據庫中的數據,只要在窗體上繪制一個 DataGridView 控件(對象名為 dgv)即可,不需要額外的輔助 控件。首先,在窗體類中定義如下變量,bDataChanged 變量表示 dgv 中的數據是否變化,如有變化, 則需要寫入數據庫。bs 對象是 dgv 與數據庫對象 myData 的紐帶。
Dim strCommand As String = "select * from Protocols order by [ID]"
Dim bDataChanged As Boolean = False
Dim myData As ADO_NET_ACCESS
Dim dt As DataTable
Dim WithEvents bs As BindingSource = New BindingSource
通過 RefreshData 函數,將數據庫中的數據填入 dgv 對象。myData 的 dt 對象,則可以直接用於 在後台對數據庫進行操作。RefreshData 函數一般放置在窗體的 Load 事件處理程序中。
Private Sub RefreshData()
myData = New ADO_NET_ACCESS(strDataPath, strCommand)
If myData.nTables = 0 Then
MessageBox.Show(myData.ErrorAdapter, Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End
End If
dt = myData.dt
bs.DataSource = myData.ds
bs.DataMember = myData.TableName
dgv.DataSource = bs
End Sub
在 bs 對象的ListChanged 事件處理程序中輸入如下代碼,標志數據的變化。
If myData.ds.HasChanges Then bDataChanged = True
在 dgv 的 RowValidated 和窗體的 FormClosed 事件處理程序中,調用 SaveChanges 子程序,即可保存數據變化到數據庫中。這樣,幾乎 用最簡捷的代碼,完成了 dgv 的前台顯示和數據庫的後台更新。
Private Sub SaveChanges()
If bDataChanged Then
Dim nRet As Integer = myData.WriteData()
If nRet = -1 Then
MessageBox.Show(myData.ErrorWrite, Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Me.bDataChanged = False
End If
End Sub
5.4 在遠程測試中的應用
TestPort 具有強大的功能,如果僅僅用於傳輸距離只有15米之內的 串行通信測試,顯然是個浪費。這個問題可以通過引入第4節的RS-232/RJ-45協議轉換器來解決,具體模 型如圖12所示。TestPort 和遠程受控機都通過 RS-232 接口與 RS-232/RJ-45 協議轉換器連接,從而都 具有了網絡通信功能。與受控機相連的協議轉換器工作在服務器模式,等待客戶機的連接請求。與 TestPort 相連的協議轉換器工作在客戶機模式,連接到服務器,從而建立了 TCP 通信管道。這樣, TestPort 就可以通過 Internet 對遠程受控機進行透明測試。
6 結論
計算 機監控系統廣泛應用於眾多領域。本文設計了計算機監控系統中常用的仿真模塊及其通信協議,開發了 輔助工具及通用串口設備測試工具,並給出了相應的應用模型和實例。在計算機監控的通用數據處理技 術以及串行通信方面給出了核心代碼。數據庫操作及顯示通常是編程必不可少的環節,本文設計了 ADO_NET_ACCESS 類,並用簡捷的代碼實現了數據庫中數據的顯示與更新。利用本文的仿真模塊、輔助工 具及測試工具,可以在高校的計算機房零成本搭建多種形式的計算機監控系統的仿真開發平台。所有軟 件與實例系統均經過了嚴格的測試,可以廣泛地用於仿真開發與教學工作。
參考文獻
[1] 馬玉春. 計算機監控技術與系統開發[M]. 北京: 清華大學出版社, 2007.1