注意:訪問本站需要Cookie和JavaScript支持!請設置您的瀏覽器! • 打開購物車 • 查看留言 • 付款方式 • 聯系我們 |
![]() |
首頁 | 電子入門 | 學單片機 | 免費資源 | 下載中心 | 商品列表 | 象棋在線 | 在線繪圖 | 加盟五一 | 加入收藏 | 設為首頁 |
選擇分類:當前分類——電腦編程 相關聯或者相類似的文章: 國產OS?中文CPU?(1213) JAVA教程 第一講 Java語言概述(2)(796) JAVA教程 第三講 Java語言中的面向對象特性(1)(785) vb的10個小技巧 (772) 學編程的人不能不看的好文章 (745) JAVASCRIPT簡介 (736) 絕對不知道你的瀏覽器還有這個功能!(722) JAVA對象入門第1章 對象入門(719) 給初學編程者的忠告 (702) JavaScript 對象與數組參考大全(650) JAVA教程 第三講 Java語言中的面向對象特性(2)(631) JAVA教程 第三講 Java語言中的面向對象特性(3)(587) VB開發Windows環境下的串行通信程序(560) SQL轉ACCESS解決自動編號問題(531) JAVA教程 Java語言基礎知識(452) JAVA教程 第二講 Java語言基礎知識(1)(364) DHTML參考手冊(一)(210) [精]5分鐘編寫一個ASP論壇(99) Cookies常用命令簡介(99) RegExp正則表達示用法(3) 首頁 前頁 后頁 尾頁 本站推薦: | VB開發Windows環境下的串行通信程序 VB開發Windows環境下的串行通信程序 發布時間:2004-7-14 隨著Windows在國內的普及,特別是Windows95的推出,越來越多的微機用戶轉向了Windows操作系統。不過Windows應用軟件的開發對于一般工程技術領域的技術人員來說并非易事,不但Windows的消息循環機制不易理解,而且要開發一個功能強、界面美觀的應用軟件,其編程和調試的工作量是非常大的。許多并非搞軟件出身的工程技術人員對Windows編程望而生畏。然而使用微軟的VisualBasic來開發這些方面的Windows應用軟件就十分方便,一般工程技術人員易于掌握,設計軟件界面非常方便,編程工作量相對較小,只需進行主要應用功能的編程和少量界面控制的編程。本文介紹了筆者使用VB在串行通信編程方面的一些收獲,由于在報刊雜志上對Windows下串行通信編程的介紹多為用MicrosoftC++或BorlandC++,故筆者愿意就VB在該方面的應用與大家探討。對于采用了RS-232接口進行串行通信的計算機測控系統軟件的開發,具有一定的參考價值。 在該系統中使用了80C31單片機作為下位機采集慣性敏感部件的測量數據,經過一定的預處理后通過RS-232串行口將數據傳送給上位PC機。在PC機上Windows環境下運行檢測軟件,接受串行口傳來的數據,進行數據處理、顯示、存盤等。數據處理結果以表格形式打印輸出。 在VB3.0中,有許多專業廠商提供用戶定制的控件(Customcontrol),這些控件以.VBX為后綴,其中MSCOMM.VBX即是用于串行通信的控件。對于VB3.0,啟動后該控件就包含于控件工具箱(toolbox)內,否則可以通過File|AddFile將該控件加入控件工具箱。然后就可以利用該控件進行串行通信的程序設計! 下面舉一個簡單的例子,說明了如何進行串行通信的程序設計,該程序在Windows95環境下,使用VB3.0已經實現: 1.先建立一個項目文件,其控件如下表所示: 2.代碼如下: SubForm_Load() comm1.CommPort=1‘使用串行口1 ’波特率9600,偶校驗,8個數據位,1個停止位。 comm1.Settings=“9600,E,8,1” 當使用Comm1.Input時,每次從接收緩沖區取一個字節。 comm1.InputLen=1 timer1.interval=20‘定時器的中斷間隔為20ms,用于更新顯示時間。 EndSub SubcmdComm_Click() Dimechoch%‘命令變量 Staticmaxf01&,maxf02&,minf01&,minf02&‘最大值,最小值 OnErrorResumeNext‘簡單的錯誤處理 maxf01&=maxf02&=0‘初始化變量 minf01&=32767 minf02&=32767 label2.Caption=comm1.Settings‘顯示串行口的設置。 Ifcmdcomm.Caption=“通信”Then‘若當前命令按扭的提示為“通信”則開始發送和 cmdcomm.Caption=“停止”‘接受數據,并將命令按扭提示改為“停止”,以 cmdexit.Enabled=False‘允許停止通信。使退出命令在通信中失效。 IfNotcomm1.PortOpenThen‘若串行口沒有打開,則打開串行口 comm1.PortOpen=True EndIf Ifcomm1.PortOpenThen Ifecho.Text<>“”Then‘若命令輸入框不空,則將其轉換為十六進制數值 echoch%=Val(“&H”+echo.Text) Else echoch%=&HF0‘否則確省命令為F0H EndIf comm1.Output=Chr(echoch%)‘向串行口寫入一字節命令,由WINDOWS自 EndIf‘動將命令發出 label3.Caption=Hex(echoch%)‘顯示剛發出的命令 DoWhilecomm1.PortOpen Ifcomm1.InBufferCount>0Then‘若comm1.InBufferCount>0表示接受緩沖 ch$=comm1.Input‘區有數據,并讀出一個字符, IfAsc(ch$)=echoch%Then‘若與發出的命令相同,則退出當前循環 ExitDo‘進入下一循環 EndIf Else comm1.Output=Chr(echoch%)‘否則繼續向下位機發命令,通知下位機 EndIf‘送數據 dummy=DoEvents()‘讓系統處理其他消息 Loop ‘下位機接受到正確的命令,并回發命令正確時,進入下面循環 i=1 DoWhilecomm1.PortOpen Ifcomm1.InBufferCount>5Then ch$=comm1.Input DoWhileAsc(ch$)<>echoch%‘以命令字節同步測試數據 ch$=comm1.Input Loop ch1$=comm1.Input‘從WINDOWS串行數據接受緩沖區讀測試數據 ch2$=comm1.Input ch3$=comm1.Input ch4$=comm1.Input newf01&=CLng(CLng(Asc(ch2$))*16*16+Asc(ch1$))‘合并為一個整數 newf02&=CLng(CLng(Asc(ch4$))*16*16+Asc(ch3$)) ifnewf01&>maxf01&Then‘判斷最大值,最小值 maxf01&=newf01& EndIf Ifnewf01& minf01&=newf01& EndIf Ifnewf02&>maxf02&Then maxf02&=newf02& EndIf Ifnewf02& minf02&=newf02& EndIf labf01.Caption=Str(newf01&)‘顯示數據 labf02.Caption=Str(newf02&) labmaxf01.Caption=Str(maxf01&) labminf01.Caption=Str(minf01&) labmaxf02.Caption=Str(maxf02&) labminf02.Caption=Str(minf02&) Else comm1.Output=Chr(echoch%) EndIf dummy=DoEvents() Loop Else‘在通訊過程中,按下cmdCOMM按鈕則停止通信,發出停止測試 cmdcomm.Caption=“通信”‘命令,關閉串行口,使退出按鈕有效。 comm1.Output=Chr(&H5F) comm1.PortOpen=False cmdexit.Enabled=True EndIf EndSub SubcmdExit_Click() Ifcomm1.PortOpenThen‘確認關閉串行口 comm1.PortOpen=False EndIf End‘終止整個程序 EndSub SubTimer1_Timer()‘更新顯示時間 Iflabtime.Caption<>Time&Then labtime.Caption=Time$ EndIf EndSub 3.程序說明: a.上述程序的通信協議為:波特率9600,偶校驗,8個數據位,1個停止位。由上位機發送開始測試命令,下位機接收到命令后每隔500ms向上位機發送檢測到的數據。每次發送5個字節,第一個字節為下位機接受到的命令,第二三字節為16Byte的值,第四五字節為16Byte的值。上位機循環接受并處理和顯示數據; b.由于在控制軟件中,串行通訊發送和接受的數據多為十六進制,故在命令輸入時為十六進制數,在程序中通過echoch%=Val(“&H”+echo.Text)將輸入的echo.Text轉換為十六進制數,并賦給變量echoch%。而在通過串行口發送時comm1.Output要求接受字符型變量,故通過語句comm1.Output=Chr(echoch%)實現; c.接受數據時,每次要判斷第一個字節是否為發出的命令,只有是后面4個字節才為正確的數據,否則查看下一字節。通過設置COMM1.InputLen=1來實現每次從接受緩沖區內讀取一個字節; d.當退出程序時,一定要關閉串行口,通過comm1.PortOpen=False完成; e.如果需要上位機定時查詢下位機,可以將串行通訊在定時器Timer1-Timer事件中進行; f.要實現完善的功能,必須進一步改善程序,甚至要用到WindowsAPI、OLE等,上述程序只是一個簡單的例子; 上面介紹了筆者在使用VB開發Windows環境下測控軟件的一點收獲,筆者使用上述原理開發了一個界面友好、功能全面、使用方便的衛星控制系統慣性敏感部件檢測軟件,實際使用效果良好,提高了工作效率,甚至實現了測試和數據處理的自動化! WIN95 Visual Basic5.0( 以 下 簡 稱VB) 以 其 簡 單 易 學、32 位 面 向 對 象 的 程 序 設 計 等 特 點, 倍 受 廣 大 計 算 機 開 發 者 的 青 睞, 已 廣 泛 地 應 用 于 各 個 領 域; 在 實 時 監 測 系 統 中 串 行 端 口 通 信 是 一 項 基 礎 功 能, 因 此 我 們 使 用VB5 編 寫 了 實 時 水 庫 水 文 自 動 監 測 系 統 的 后 臺 機 軟 件。 本 文 就Windows 95 環 境 中 采 用VB5 設 計 串 行 端 口 通 信 程 序 進 行 討 論 并 給 出 實 例。 一 般 用VB 開 發 串 行 通 信 程 序 有 兩 種 方 法: 一 是 利 用Windows 的 通 信API 函 數; 另 一 種 是 采 用VB 標 準 控 件Mscomm 來 實 現。 Windows 95 的 通 信API Windows 95 中 的 串 口 通 信API 函 數 不 同 于Windows3.x 中 的OpenComm、CloseComm、ReadComm、WriteComm, 而 是 采 用 硬 件 與 文 件 通 用 的 函 數CreateFile、ReadFile、WriteFile、CloseHandle, 該 類 函 數 更 具 有 一 般 性, 并 且 可 以 用EscapeCommFunction 函 數 實 現 底 層 硬 件 操 作, 比 如:SETXOFF、 CLRDTR 等。 利 用API 編 寫 串 口 通 信 程 序 較 為 復 雜, 需 要 掌 握 大 量 通 信 知 識, 其 優 點 是 可 實 現 的 功 能 更 豐 富、 應 用 面 更 廣 泛, 更 適 合 于 編 寫 較 為 復 雜 的 低 層 次 通 信 程 序。 采 用 這 種 方 法 編 寫 串 行 端 口 通 信 程 序 一 般 可 分 為 以 下 幾 個 過 程: 1. 初 始 化 串 行 端 口 首 先 用CreateFile 函 數 打 開 指 定 串 口, 置 參 數 中 訪 問 類 型 為GENERIC_READ |GENERIC_WRITE、 共 享 模 式 為0、 創 建 標 志 為OPEN_EXISTING、 模 板 句 柄 為NULL。 2. 配 置 串 口 Windows 95 的 串 口 配 置 比Windows 3.x 較 為 復 雜, 但 其 功 能 更 強 大, 對 一 般 程 序 可 使 用CommConfigDialog 函 數 以 對 話 框 方 式 設 置 波 特 率、 數 據 位、 奇 偶 校 驗、 停 止 位 和 流 控 制 方 式, 并 且 可 以 恢 復 缺 省 值。 3. 超 時 控 制 為 了 防 止 意 外 情 況 使 串 口 讀 寫 無 休 止 地 等 待,Windows 95 提 供 了 超 時 設 置, 這 是 由COMMTIMEOUTS 結 構 定 義 的, 通 過 調 用GetCcommTimeOuts 函 數 獲 得 當 前 的 設 置, 用SetCommTimeOuts 函 數 來 完 成 設 置。 4. 數 據 傳 輸 讀 寫 串 行 端 口 與 讀 寫 文 件 采 用 的 函 數 相 同, 即ReadFile、WriteFile, 讀 寫 操 作 可 分 四 種 方 式: 查 詢 方 式、 同 步I/O、 異 步( 后 臺)I/O 和 事 件 驅 動I/O。 5. 關 閉 串 口 程 序 的 終 止 可 以 自 動 關 閉 串 口, 也 可 用 函 數CloseHandle(), 以 便 釋 放 所 獨 占 資 源。 VB 通 信 控 件Mscomm Mscomm 控 件 提 供 了 功 能 完 善 的 串 口 數 據 的 發 送 和 接 收 功 能,Mscomm 控 件 具 有 兩 種 處 理 方 式: 1 事 件 驅 動 方 式: 由Mscomm 控 件 的OnComm 事 件 捕 獲 并 處 理 通 信 錯 誤 及 事 件;2 查 詢 方 式: 通 過 檢 查CommEvent 屬 性 的 值 來 判 斷 事 件 和 錯 誤。 Mscomm 控 件 的 通 信 功 能 實 現, 實 際 上 是 調 用 了API 函 數, 而API 函 數 是 由Comm.drv 解 釋 并 傳 給 設 備 驅 動 程 序 執 行 的, 對 于VB 程 序 開 發 者 只 需 知 道Mscomm 控 件 的 屬 性 和 事 件 的 用 法 即 可 以 實 現 串 口 的 操 作。 以 下 是Mscomm 控 件 的 主 要 屬 性 和 方 法: 1)CommPort: 設 置 或 返 回 串 行 端 口 號, 其 取 值 范 圍 為1 ~99, 缺 省 為1。 2) Setting 設 置 或 返 回 串 行 端 口 的 波 特 率、 奇 偶 校 驗 位、 數 據 位 數、 停 止 位。 如:Mscomm.Setting=“9600,N,8,1”。 3)PortOpen: 打 開 或 關 閉 串 行 端 口, 格 式 為:Mscomm.PortOpen={TRUE|FALSE}。 4) InBufferSize: 設 置 或 返 回 接 收 緩 沖 區 的 大 小, 缺 省 為1024 字 節。 5) InBufferCount: 返 回 接 收 緩 沖 區 內 的 等 待 讀 取 的 字 節 個 數, 可 通 過 設 置 該 屬 性 為0 來 清 除 接 收 緩 沖 區。 6) RThreshold: 該 屬 性 為 一 閥 值, 它 確 定 當 接 收 緩 沖 區 內 字 節 個 數 達 到 或 超 過 該 值 后 就 產 生 代 碼 為MSCOMM_EV_RECEIVE 的OnComm 事 件。 7) InputLen: 設 置 或 返 回 接 收 緩 沖 區 內 用Input 讀 入 的 個 數。 若 取0, 則INPUT 讀 取 整 個 緩 沖 區 的 內 容。 8) Input: 該 屬 性 表 示 從 接 收 緩 沖 區 移 走 一 串 字 符。 9) OutBufferSize: 設 置 或 返 回 發 送 緩 沖 區, 缺 省 為512 字 節。 10) OutBufferCounter: 返 回 發 送 緩 沖 區 內 等 待 發 送 的 字 符 數, 可 用 來 清 空 緩 沖 區。 11) Output: 向 發 送 緩 沖 區 傳 送 一 字 符 串。 12) EOFEnable: 若 置TRUE, 則 當 輸 入 中 出 現EOF, 就 停 止 輸 入 并 產 生OnComm 事 件。 如 果 在 通 信 過 程 中 發 生 錯 誤 或 事 件, 就 會 引 發OnComm 事 件 并 且 改 變 屬 性 值, 由CommEvent 屬 性 代 碼 反 映 錯 誤 類 型, 在 通 信 程 序 的 設 計 中 可 根 據 該 屬 性 值 來 執 行 不 同 的 操 作, 以 下 是 部 分 屬 性 常 數 值 及 其 含 義: 1)ComEvSend: 其 值 為1, 發 送 緩 沖 區 的 內 容 少 于SThreshold 指 定 的 值。 2) ComEvReceive: 其 值 為2, 接 收 緩 沖 區 內 字 符 數 達 到 RThreshold 值, 該 事 件 在 緩 沖 區 中 數 據 被 移 走 前 將 持 續 產 生。 3) ComEventFrame: 其 值 為1004, 硬 件 檢 測 到 幀 錯 誤。 4) ComEventRxOver: 其 值 為1008, 接 收 緩 沖 區 溢 出。 5) ComEventTxFull: 其 值 為1010, 發 送 緩 沖 區 溢 出。 6) ComEventRxParity: 其 值 為1009, 奇 偶 校 驗。 7) ComEvEOF: 其 值 為7, 接 收 數 據 中 出 現 文 件 結 束(ASCII 碼 為 26) 字 符。 程 序 樣 例 采 用Mscomm 控 件 實 現 串 口 通 信 時, 首 先 添 加 一Mscomm 控 件 到 窗 體 中, 該 控 件 一 般 不 在 通 用 工 具 窗 口 中, 而 是 需 通 過 菜 單 項“ 工 程(P) → 部 件(O)” 進 入 選 擇 窗 口, 在 控 件tab 頁 中 選 取Microsoft Comm Control 5.0 , 此 時 工 具 窗 口 中 出 現Mscomm 圖 標, 即 可 被 使 用。 以 下 是 事 件 驅 動 方 式 的 接 收 程 序 的 主 要 部 分: Private Sub getdatafromserial_Click() CommonDialog1.InitDir = “c:\temp" CommonDialog1.ShowSave mainfrm.MSComm1.CommPort=1 hfile = FreeFile ’ 打 開 存 儲 接 收 數 據 的 文 件 Open CommonDialog1.filename For Output As #hfile ’ 設 接 收 緩 沖 區 的 大 小, 可 按 量 確 定 mainfrm.MSComm1.InBufferSize = 4096 If Not mainfrm.MSComm1.PortOpen Then ’ 打 開 串 口 -- mainfrm.MSComm1.PortOpen = True End If If Err Then MsgBox “Communcation port cannot be opened!!" ’ 清 接 收 緩 沖 區 mainfrm.MSComm1.InBufferCount = 0 ’ 設 一 次 讀 入 的 長 度, 可 根 據 數 據 格 式 設 置 mainfrm.MSComm1.InputLen = 77 ’ 設 置 接 收 事 件 觸 發 的 閥 值 mainfrm.MSComm1.RThreshold = 77 counter = Timer + 10 Do If Timer > counter Then mainfrm.Label1.Caption = “ 正 在 通 信......" mainfrm.Label1.Refresh counter = Timer + 10 End If DoEvents Loop End Sub 以 下 為 事 件 處 理 子 程 序,flag 為 一 靜 態 變 量 記 錄 讀 取 次 數, 以 便 改 變 接 收 數 據 的 長 度, 讀 者 可 根 據 實 際 需 要 添 加 其 它 處 理 內 容: Private Sub MSComm1_OnComm() Select Case MSComm1.CommEvent Case comEvReceive If flag > 246 Then MSComm1.InputLen = 0: MSComm1.RThreshold = 32 End If buffer = MSComm1.Input temp = buffer Print #hfile, temp counter = Timer + 10 Do While Timer > counter Do Events Loop flag = flag + 1 Case comEvEOF EVMsg $ = “ 檢 測 到 文 件 結 尾!!!" Case comFrame ERMsg $ = “ 幀 出 錯!!!" Case comRxParity ERMsg $ = “ 奇 偶 錯!!!" End Select If Len(EVMsg $) Then Text1.Text = “Status: " & EVMsg $ ElseIf Len(ERMsg $) Then Text1.Text = “Status: " & ERMsg $ Beep Ret = MsgBox(ERMsg $, 1, “Click Cancel to quit, OK to ignore.") MSComm1.PortOpen = False End If End Sub vb開發通信軟件 一、PC串行通信程序機制 常用的PC串行通信程序大多利用BIOSINT14H中斷,以查詢I/O方式完成異步串行通信。 Windows系統提供中斷方式驅動的串行通信驅動程序COMM.DRV。通信程序無需直接對串行端口進行操作,而是通過驅動程序這一編程接口進行間接操作。 Windows操作系統中,串行通信采用“事件通知”方式,支持數據按塊傳送。進行通信時,Windows開辟一個用戶定義的輸入輸出緩沖區,每接收一個字符就產生一個低級硬件中斷,串行驅動程序立即取得控制權,并將字符放入輸入數據緩沖區,然后將控制權返還正在運行的應用程序。如果輸入數據緩沖區滿了,驅動程序用當前定義的流控制機制通知發送方停止發送數據。發送數據也采用類似的處理方式,應用程序將需要發送的數據放入輸出數據緩沖區,串口每發送一個字符就產生一個低級硬件中斷。 二、PC串行口遠程通信的硬件配置 串行通信數據鏈中,計算機一端稱為DTE,即數據終端設備;調制解調器一端稱為DCE,即數據通信設備。PC串行通信的硬件連接方式分為零Modem連接和Modem連接。 零Modem連接即直接用調制解調器電纜將兩臺設備連接起來,Modem連接則通過DCE(Modem)將兩臺PC連接起來。 零Modem連接用于距離15m內兩臺DTE或DCE設備之間的連接。而Modem連接則通過電話網或專線用于長距離的通信。 TXD和RXD信號線用于計算機和Modem間傳輸數據信息;RTS從計算機端發送信號到Modem,表示希望把數據傳給Modem,若Modem能接收這個數據,它將發送CTS信號給計算機;DTR從計算機端發送信號到Modem,表示計算機已作好通信準備,Modem將DTR信號作為初始化自己的信號,然后給計算機回送數據設置就緒信號DSR;當本地Modem接收到遠地Modem的呼叫,則發送RING信號給計算機;Modem應答呼叫后,發送數據載波檢測DCD信號到計算機,表示已建立連接。 Modem的工作狀態分為命令狀態和在線狀態。處于命令狀態時,Modem對串口發送的信息進行解釋,可通過PC串口向Modem發送AT命令對其進行初始化、設置和操作。 例如,初始化命令為:“ATQOV1WOSOΚ1&C1&D2&YO&WO”,其含義為: QO:返回結果碼; V1:以字符形式顯示結果碼; WO:不返回協商進程結果碼; SOΚ1:振鈴一次,即應答; &C1:追蹤數據載波信號CD; &D2當DTR從開到關時,Modem掛機進入命令狀態; &YO:Modem上電時重新調出用戶方案; &WO:將以上設置存為動態設置用戶方案0; 一旦本地Modem與遠地Modem建立連接,Modem即處于在線狀態,可進行數據傳輸。此時,Modem不響應AT命令,直接傳送所收到的數據。 三、Modem連接遠程通信軟件的編制 通信過程中大部分的工作由串行通信驅動軟件承擔。 本文軟件的運行環境為AST+4/66d,Hayes公司的ACCURA144+FAX144Modem,Windows3.2,VB3.0專業版。VB3.0專業版中提供了一個MSCOMM.VBX通信控件。它使用戶能很方便地通過對控件屬性的設置、檢測,訪問串行通信驅動程序的大多數特性,而不必考慮其實現細節。該控件為“事件驅動”,只響應“OnComm”事件,該事件可對已發生的事件或錯誤進行處理,與CommEvent屬性緊密相關。 通信軟件、通信驅動軟件和Modem之間的通信關系 以下程序實現了通信的基本過程。包括初始化串口和Modem,上位機撥號呼叫下位機,下位機應答并開始定時傳輸數據,掛機停止傳輸等功能。 VB3.0編制的通信軟件清單如下: 上位機控件清單: 控件名稱 屬性 Form1Form1Caption ″上位機通信″ MsComm comm1 CommandButton1CallCaption ″撥號″ CommandButton2hangCaption ″掛機″ CommandButton3ExitCaption ″退出″ 下位機控件清單 控件名稱 屬性 Form1Form1Caption ″下位機通信″ MsComm comm1 CommandButton1hangCaption ″掛機″ CommandButton2ExitCaption ″退出″ Timer1Timer1Interval 3000 Text(i)Text(i) 1.串口初始化、設置程序 在程序初始化時,先對串口初始化。因為使用RTS/CTS握手信號的硬件設備只有RTS信號置為高才能接收數據,所以需將MSCOMM通信控件的RTSenable屬性設為TRUE。由于Modem在處于命令狀態時,通過串口發送的命令以及命令結果均會回顯在輸入緩沖區中,因此在進入在線狀態前,禁止產生EV-RECEIVE事件,避免數據誤處理。 由于Windows是多任務系統,在進行數據收發循環處理時,應調用DOEVENTS事件,將控制權交還系統,允許Windows執行其他任務。但應注意,在處理OnComm事件時小心使用DOEVENTS,避免系統又產生OnComm事件,造成嵌套,出現堆棧溢出錯誤。 Sub Form-Load() comm1.CommportΚ1′COM1口通信 comm1.SettingsΚ″9600,N,8,1″′波特率9600,無校驗,8位數據位1位停止位 comm1.OutBufferSizeΚOUTPACK′設置輸出緩沖區大小 comm1.InBufferSizeΚINPACK′設置輸入緩沖區大小 comm1.InputLenΚ1′每次從輸入緩沖區中取一個字符 comm1.RTSenableΚ-1′RTS信號為高 comm1.RthresholdΚ0′不產生MSCOMM-EV-RECEIVE事件 comm1.PortOpenΚ-1′打開串口 cdΚcomm1.CDHolding′取載波檢測信號線原始狀態 comm1.outputΚ″ATQOV1WOSOΚ1&C1&D2&YOWO″′初始化Modem Do DoEventsLoopUntilcomm1.OutBufferCountΚ0 End Sub 2.上位機撥號呼叫下位機 SubCallcom-Click() Comm1.OutPutΚ″ATDT″&Phonnum$&chr$(13)′向Modem發撥號命令 Do DoEventsLoopUntilcomm1.OutBufferCountΚ0 End Sub 3.下位機Modem應答,連通后開始定時傳輸數據 下位機檢測CD,判斷是否連通: Sub Comm1-OnComm() Select Casecomm1.CommEvent Case5 ′MSCOMM-EV-CD Timer1.EnabledΚ-1′啟動定時器 End Select End Sub VB傳送定長字符串,數據接收處理相對簡單。但在發送實時數據時,若將數據轉換成定長字符串,這樣會大大降低傳輸效率。在接收端,通知程序從輸入緩沖區中取字符有兩種方法:一是用輪詢方法循環判斷InBufferCount是否為0;另外就是利用Rthreshold屬性觸發“OnComm”事件及“CommEvent”屬性中EV-RECEIVE事件。當Rthreshold的值不為0時,允許產生EV-RECEIVE事件。該屬性設置和返回在通信控件設定CommEvent特性為接收和產生OnComm事件之前要接收的字符數。VB傳送變長字符串時,接收端的Rthreshold值要作相應的改變,以確保接收數據及時準確。 下位機定時發送字符串“strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$”。strin1$為當前字符串,strin2$為上一字符串。上位機根據接收strin3$中Len(strin1$),相應改變RthresholdΚLen(strin1$)+4。這樣,通過提前發送字符串長度,改變Rthreshold值可實現發送變長數據。 Windows串行通信驅動程序的事件驅動特性仍有不穩定的缺陷。如InputLenΚ0時,有可能取出不完整的數據。為保證可靠,采取降低處理速率的方法,保證下位機發送的數據流完整地進入輸入緩沖區。設InputLenΚ1,即每次從緩沖區中取一個字符。也可采用輪詢方法,定時檢測輸入緩沖區。下位機定時發送數據: Sub Timer1-Timer() If comm1.CDHoldingΙΛcdThen str1$-text1(i).Text strin2$Κstrin1$′上一字符串 strin1$Κstr1$′當前字符串 strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$ ′傳送當前字符串長度,以及上一字符串內容 com m1.OutPutΚstrin3$ Do DoEventsLoopUntilcomm1.OutBufferCountΚ0 Else Timer1.EnabledΚ0 End If End Sub 上位機檢測CD狀態,判斷是否連通、并接收處理數據。 Sub Comm1-OnComm() Select Case comm1.CommEvent Case5 ′MSCOMM-EV-CD檢測CD狀態,判斷是否連通 comm1.InBufferCountΚ0′清輸入緩沖區 comm1.RThresholdΚ4′當輸入緩沖區中有五個字符, Case2′MSCOMM-EV-RECEIVE產生EV-RECEIVE事件,接收處理數據 Do DoEvents Ifcomm1.InBufferCountThen′循環從緩沖區中取數據 str1$Κstr1$+comm1.Input Else Exit Do End If Loop len2Κ1en1′當前字符串長度 len1ΚVa1(Left$(str1$,5))′即將發送的字符串長度 comm1.RThresholdΚlen1+4 strin$ΚRight$(str1$,len2)′數據處理 …… End Select str1$Κ″″ End Sub 4.根據設置的AT命令“&D2”,當置DTR信號為低時,Modem掛機進入命令狀態。也可通過串口輸出““+++ATH”+chr$(13)”字符串掛機。 Sub Hang-click() If comm1.CDHoldingΙΛcdThen′檢測CD,判斷是否掛機 comm1.DTRenableΚ0 comm1.DTRenableΚ-1′置DTR信號為高,為下一次通信準備 End If End Sub 5.退出程序時,一定要關閉串口 Sub Exitcomm() comm1.PortOpenΚfalse End End Sub 四、Windows通信機制和VB3.0通信控件潛在缺陷 在通信軟件編制過程中,我們發現Windows下通信機制采用的“事件驅動”在實際運行中不穩定。如在文件傳輸過程中,誤碼和數據丟失的情況時有發生;若串口波特率過高,會產生無法通信或在通信過程中隨機掛機的情況。這主要是由于Windows本身通信機制和通信線路介質及質量的影響。為保證數據傳輸穩定可靠,可采用通信協議如XModem-CRC或YModem。在MSCOMM.VBX通信控件中,Rthreshold屬性值大小與輸入緩沖區InBufferSize大小有關,當Rthreshold值較接近InBufferSize值時,有可能不產生EV-RECEIVE事件,為保證產生該事件,可將InBufferSize值取得較大 使用VB開發Windows環境下的串行通信程序 隨著Windows在國內的普及,特別是Windows95的推出,越來越多的微機用戶轉向了Windows操作系統。不過Windows應用軟件的開發對于一般工程技術領域的技術人員來說并非易事,不但Windows的消息循環機制不易理解,而且要開發一個功能強、界面美觀的應用軟件,其編程和調試的工作量是非常大的。許多并非搞軟件出身的工程技術人員對Windows編程望而生畏。然而使用微軟的VisualBasic來開發這些方面的Windows應用軟件就十分方便,一般工程技術人員易于掌握,設計軟件界面非常方便,編程工作量相對較小,只需進行主要應用功能的編程和少量界面控制的編程。本文介紹了筆者使用VB在串行通信編程方面的一些收獲,由于在報刊雜志上對Windows下串行通信編程的介紹多為用MicrosoftC++或BorlandC++,故筆者愿意就VB在該方面的應用與大家探討。對于采用了RS-232接口進行串行通信的計算機測控系統軟件的開發,具有一定的參考價值。 在該系統中使用了80C31單片機作為下位機采集慣性敏感部件的測量數據,經過一定的預處理后通過RS-232串行口將數據傳送給上位PC機。在PC機上Windows環境下運行檢測軟件,接受串行口傳來的數據,進行數據處理、顯示、存盤等。數據處理結果以表格形式打印輸出。 在VB3.0中,有許多專業廠商提供用戶定制的控件(Customcontrol),這些控件以.VBX為后綴,其中MSCOMM.VBX即是用于串行通信的控件。對于VB3.0,啟動后該控件就包含于控件工具箱(toolbox)內,否則可以通過File|AddFile將該控件加入控件工具箱。然后就可以利用該控件進行串行通信的程序設計。 下面舉一個簡單的例子,說明了如何進行串行通信的程序設計,該程序在Windows95環境下,使用VB3.0已經實現: 1.先建立一個項目文件,其控件如下表所示: 2.代碼如下: SubForm_Load() comm1.CommPort=1‘使用串行口1 "波特率9600,偶校驗,8個數據位,1個停止位。 comm1.Settings=“9600,E,8,1” 當使用Comm1.Input時,每次從接收緩沖區取一個字節。 comm1.InputLen=1 timer1.interval=20‘定時器的中斷間隔為20ms,用于更新顯示時間。 EndSub SubcmdComm_Click() Dimechoch%‘命令變量 Staticmaxf01&,maxf02&,minf01&,minf02&‘最大值,最小值 OnErrorResumeNext‘簡單的錯誤處理 maxf01&=maxf02&=0‘初始化變量 minf01&=32767 minf02&=32767 label2.Caption=comm1.Settings‘顯示串行口的設置。 Ifcmdcomm.Caption=“通信”Then‘若當前命令按扭的提示為“通信”則開始發送和 cmdcomm.Caption=“停止”‘接受數據,并將命令按扭提示改為“停止”,以 cmdexit.Enabled=False‘允許停止通信。使退出命令在通信中失效。 IfNotcomm1.PortOpenThen‘若串行口沒有打開,則打開串行口 comm1.PortOpen=True EndIf Ifcomm1.PortOpenThen Ifecho.Text<>“”Then‘若命令輸入框不空,則將其轉換為十六進制數值 echoch%=Val(“&H”+echo.Text) Else echoch%=&HF0‘否則確省命令為F0H EndIf comm1.Output=Chr(echoch%)‘向串行口寫入一字節命令,由WINDOWS自 EndIf‘動將命令發出 label3.Caption=Hex(echoch%)‘顯示剛發出的命令 DoWhilecomm1.PortOpen Ifcomm1.InBufferCount>0Then‘若comm1.InBufferCount>0表示接受緩沖 ch$=comm1.Input‘區有數據,并讀出一個字符, IfAsc(ch$)=echoch%Then‘若與發出的命令相同,則退出當前循環 ExitDo‘進入下一循環 EndIf Else comm1.Output=Chr(echoch%)‘否則繼續向下位機發命令,通知下位機 EndIf‘送數據 dummy=DoEvents()‘讓系統處理其他消息 Loop ‘下位機接受到正確的命令,并回發命令正確時,進入下面循環 i=1 DoWhilecomm1.PortOpen Ifcomm1.InBufferCount>5Then ch$=comm1.Input DoWhileAsc(ch$)<>echoch%‘以命令字節同步測試數據 ch$=comm1.Input Loop ch1$=comm1.Input‘從WINDOWS串行數據接受緩沖區讀測試數據 ch2$=comm1.Input ch3$=comm1.Input ch4$=comm1.Input newf01&=CLng(CLng(Asc(ch2$))*16*16+Asc(ch1$))‘合并為一個整數 newf02&=CLng(CLng(Asc(ch4$))*16*16+Asc(ch3$)) ifnewf01&>maxf01&Then‘判斷最大值,最小值 maxf01&=newf01& EndIf Ifnewf01& minf01&=newf01& EndIf Ifnewf02&>maxf02&Then maxf02&=newf02& EndIf Ifnewf02& minf02&=newf02& EndIf labf01.Caption=Str(newf01&)‘顯示數據 labf02.Caption=Str(newf02&) labmaxf01.Caption=Str(maxf01&) labminf01.Caption=Str(minf01&) labmaxf02.Caption=Str(maxf02&) labminf02.Caption=Str(minf02&) Else comm1.Output=Chr(echoch%) EndIf dummy=DoEvents() Loop Else‘在通訊過程中,按下cmdCOMM按鈕則停止通信,發出停止測試 cmdcomm.Caption=“通信”‘命令,關閉串行口,使退出按鈕有效。 comm1.Output=Chr(&H5F) comm1.PortOpen=False cmdexit.Enabled=True EndIf EndSub SubcmdExit_Click() Ifcomm1.PortOpenThen‘確認關閉串行口 comm1.PortOpen=False EndIf End‘終止整個程序 EndSub SubTimer1_Timer()‘更新顯示時間 Iflabtime.Caption<>Time&Then labtime.Caption=Time$ EndIf EndSub 3.程序說明: a.上述程序的通信協議為:波特率9600,偶校驗,8個數據位,1個停止位。由上位機發送開始測試命令,下位機接收到命令后每隔500ms向上位機發送檢測到的數據。每次發送5個字節,第一個字節為下位機接受到的命令,第二三字節為16Byte的值,第四五字節為16Byte的值。上位機循環接受并處理和顯示數據; b.由于在控制軟件中,串行通訊發送和接受的數據多為十六進制,故在命令輸入時為十六進制數,在程序中通過echoch%=Val(“&H”+echo.Text)將輸入的echo.Text轉換為十六進制數,并賦給變量echoch%。而在通過串行口發送時comm1.Output要求接受字符型變量,故通過語句comm1.Output=Chr(echoch%)實現; c.接受數據時,每次要判斷第一個字節是否為發出的命令,只有是后面4個字節才為正確的數據,否則查看下一字節。通過設置COMM1.InputLen=1來實現每次從接受緩沖區內讀取一個字節; d.當退出程序時,一定要關閉串行口,通過comm1.PortOpen=False完成; e.如果需要上位機定時查詢下位機,可以將串行通訊在定時器Timer1-Timer事件中進行; f.要實現完善的功能,必須進一步改善程序,甚至要用到WindowsAPI、OLE等,上述程序只是一個簡單的例子; 上面介紹了筆者在使用VB開發Windows環境下測控軟件的一點收獲,筆者使用上述原理開發了一個界面友好、功能全面、使用方便的衛星控制系統慣性敏感部件檢測軟件,實際使用效果良好,提高了工作效率,甚至實現了測試和數據處理的自動化。 1、 本站不保證以上觀點正確,就算是本站原創作品,本站也不保證內容正確。 2、如果您擁有本文版權,并且不想在本站轉載,請書面通知本站立即刪除并且向您公開道歉! |
本站協議。
版權信息。
關于我們。
本站地圖。
營業執照。
發票說明。
付款方式。
聯系方式
深圳市寶安區西鄉五壹電子商行——粵ICP備16073394號-1;地址:深圳西鄉河西四坊183號;郵編:518102 E-mail:51dz$163.com($改為@);Tel:(0755)27947428 工作時間:9:30-12:00和13:30-17:30和18:30-20:30,無人接聽時可以再打手機13537585389 |