• <rp id="wfxtb"><acronym id="wfxtb"></acronym></rp><em id="wfxtb"></em><dd id="wfxtb"><big id="wfxtb"><video id="wfxtb"></video></big></dd>
  • <rp id="wfxtb"></rp>

    <mark id="wfxtb"><center id="wfxtb"></center></mark>

      <rp id="wfxtb"><span id="wfxtb"><u id="wfxtb"></u></span></rp>

      <rp id="wfxtb"><object id="wfxtb"></object></rp>

      注意:訪問本站需要Cookie和JavaScript支持!請設置您的瀏覽器! 打開購物車 查看留言付款方式聯系我們
      初中電子 單片機教材一 單片機教材二
      搜索上次看見的商品或文章:
      商品名、介紹 文章名、內容
      首頁 電子入門 學單片機 免費資源 下載中心 商品列表 象棋在線 在線繪圖 加盟五一 加入收藏 設為首頁
      本站推薦:
      VB開發Windows環境下的串行通信程序
      文章長度[20996] 加入時間[2006/7/1] 更新時間[2025/5/5 16:48:34] 級別[3] [評論] [收藏]
      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
      91嫩草黄片动漫版