久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8095|回復: 0
打印 上一主題 下一主題
收起左側

excel vba 獲取rs232數據

[復制鏈接]
跳轉到指定樓層
樓主
ID:104835 發表于 2016-2-4 03:52 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本文介紹VB6.0利用MSComm通信控件,開發微機通過串口對工業儀表進行實時數據采集的編程技術。給出的程序代碼具有通用性,并有詳細的注釋,可以直接或稍加改動后用于其他數據采集或實時控制程序中。

----一臺工業專用實時檢測儀表,接高精度位移傳感器,用于測量微小形變或微量位移,儀表測量精度為0.01毫米,測量范圍最大值為50毫米。該儀表帶有一個9針的RS-232C 串口,能與微機進行串口數據通信,實時傳送檢測數據,通過微機軟件處理可實現工業實時監控。

----該儀表的串口數據通信協議是:數據傳輸速率為 9600bps,1位開始位,8位數據位,1位停止位,無奇偶校驗位。儀表每秒發送50幀檢測數據,每幀數據由4個字節組成。第一個字節定義為二進制常數0F0H,是每幀數據開始的標志字節;后面連續2個字節為數據字節,采用壓縮的BCD碼編碼方式,高位在前,低位在后,即一個字節表示兩位十進制數,則兩個字節表示四位十進制數,小數點采用固定形式,定義在兩字節中間;第四個字節為符號字節,該字節第八位為1,即:
1xxxxxxx


----則為負數;第八位為0,即:
0xxxxxxx


----則為正數。

----例如:0F0H 26H 87H 80H 0F0H 34H 62H 00H 表示 -26.87 34.62。

----通信傳輸速率為9600bps,則最快速度1.04ms發送一個字節,儀表每秒發送50幀數據,每幀數據有4個字節,即每秒發送200個字節,平均5.0ms 發送一個字節,連續讀取串口數據時要在程序中添加循環等待程序。

----為了實現實時監測功能,接收數據的讀取要盡可能的快速,則設置MSComm1的屬性如下:
RThreshold = 1
接收緩沖區收到一個字節產生OnComm事件
InputLen = 1 每次讀取一個字節

----儀表每秒發送50幀數據,微機收到一幀完整數據至少需要20 ms時間,然后再進行數據處理。如果微機在下一幀數據接收前即20ms內能將數據計算處理完畢,則接收緩沖區內只會保存有一幀數據,不會存有兩幀以上數據,接收緩沖區的大小不會影響實時監測效果(接收緩沖區>4字節),這時完全可以實現實時監測或實時控制;如果微機在20ms內不能將數據計算處理完畢,接收緩沖區設置得又很大,在數據計算處理完畢前,接收緩沖區內就會保存有兩幀以上數據,而且一次工作時間越長,緩沖區內滯留數據幀就越多,數據采集和數據處理之間產生逐漸增大的額外時間差,當接收緩沖區充滿后,時間差不再增大,固定在某一值,部分數據因不能及時采集到接收緩沖區中,數據產生丟失現象,真實工作情況就會和微機處理結果產生較大的時間差,對實時監測和實時控制很不利,這種情況下接收緩沖區的大小就會影響實時監測效果,所以接收緩沖區設置不能過大,以保證數據處理的實時性。

----設置接收數據模式采用二進制形式,即 InputMode=comInputModeBinary,但用Input屬性讀取數據時,不能直接賦值給 Byte 類型變量,只能通過先賦值給一個 Variant 類型變量,返回一個二進制數據的數組,再轉換保存到Byte類型數變量中。

----VB中有Byte類型變量,但沒有字節的位處理語句,符號字節的位處理要判斷符號字節的值是否大于 127,大于127則為負數;壓縮的BCD碼存入 Byte類型變量,VB系統只按十進制數處理,這要通過一個簡單算法換算,解壓BCD碼才能還原成十進制表示數值。假如a是Byte類型變量,D是Single類型變量,將一個壓縮的BCD 碼存入a中,則算法是:
D=(a\16)*10 + a-(a\16)*16
則D=a-(a\16)*6

----程序清單:

----在通用聲明中定義程序所用變量:
Dim ab(4) As Byte
‘字節數據類型數組,用來存儲接收到的一組字節數據
Dim av As Variant ‘用來從接收緩沖區讀取數據
Dim i As Integer
Dim j As Integer
Dim w As Integer ‘接收數據個數計數器
Dim b1 As Single
Dim b2 As Single
Dim WW As Single ‘十進制檢測值
Dim MaxW As Single ‘最大值
Dim MinW As Single ‘最小值

----在窗體中添加名為Command1的[開始]按鈕和名為 MSComm1的MSComm控件。

---- [開始]按鈕的Click事件處理程序主要是對MSComm1控制的參數初始化設置,程序中大部分參數在設計時可在MSComm1控制的屬性窗口中設置:
Private Sub Command1_Click()
‘開始按鈕
With MSComm1
.CommPort=2 ‘使用COM2
.Setting=“9600,N,8,1" ‘設置通信口參數
.InBufferSize=40
‘設置MSComm1接收緩沖區為40字節
.OutBufferSize=2
‘設置MSComm1發送緩沖區為2字節
.InputMode = comInputModeBinary
‘設置接收數據模式為二進制形式
.InputLen = 1
‘設置Input 一次從接收緩沖讀取字節數為1
.SThreshold = 1
‘設置Output 一次從發送緩沖讀取字節數為1
.InBufferCount = 0 ‘清除接收緩沖區
.OutBufferCount = 0 ‘清除發送緩沖區
MaxW = -99
‘最大值賦初值
MinW = 99 ‘最小值賦初值
w = 0
‘數據個數計數器清零
.RThreshold = 1
‘設置接收一個字節產生OnComm事件
If .PortOpen = False Then
‘判斷通信口是否打開
.PortOpen = True ‘打開通信口
If Err Then ‘錯誤處理
MsgBox “串口通信無效"
Exit Sub
End If
End If
End With
End Sub

----為了達到實時數據采集目的,實時數據采集處理程序采用MSComm事件驅動方式。

----MSComm1_OnComm的事件處理程序只處理 comEvReceive事件,首先判斷幀數據的開始字節,關閉OnComm接收事件,然后接收數據字節,將壓縮BCD進行還原轉換,再接收符號字節,判斷數據符號,判斷數據最大最小值,最后打開OnComm接收事件,等待下一次OnComm事件產生:
Private Sub MSComm1_OnComm()
With MSComm1
Select Case .CommEvent
‘判斷MSComm1通信事件
Case comEvReceive
‘收到Rthreshold個字節產生的接收事件
av = .Input
‘讀取一個接收字節
ab(1) = av(0)
‘轉換保存到字節數據類型數組
If ab(1) = &HF0 Then
‘判斷是否為數據開始標志
RThreshold = 0
‘關閉OnComm事件接收
Do
DoEvents
Loop Until .InBufferCount >= 3
‘循環等待MSComm1接收緩沖區>=3個字節
w = w + 1 ‘計數器累加計數
av = .Input
‘讀取第二個數據字節(BCD碼高位字節)
ab(2) = av(0)
‘轉換保存到字節數據類型數組
av = .Input
‘讀取第三個數據字節(BCD碼低位字節)
ab(3) = av(0)
‘轉換保存到字節數據類型數組
av = .Input
‘讀取第四個數據字節(符號位字節)
ab(4) = av(0)
‘轉換保存到字節數據類型數組
b1 = ab(2) - 6 * (ab(2)\16)
‘高位字節壓縮BCD碼轉換為實數
b2 = ab(3) - 6 * (ab(3)\16)
‘低位字節壓縮BCD碼轉換為實數
WW = b1 + b2 / 100
‘數值組合,標定小數點
If ab(4) > 127 Then WW=?WW
‘判斷數據符號位
Label1(0) = Format(WW, “0.00")
‘顯示毫米單位數值,2位小數
Label1(1) =Format(WW /25.4, “0.000")
‘顯示英寸單位數值,3位小數
If WW > MaxW And WW < 51 Then

----‘判斷最大值,儀表在剛開始工作時有干擾,會傳導一些亂碼,位移傳感器有參數偏差,最大值一般都略大于50毫米,所以取51為極限最大值,取-51為極限最小值。
MaxW = WW
Label1(2) = Format(MaxW, “0.00")
‘顯示毫米單位最大值,2位小數
Label1(3) = Format(MaxW/25.4,“0.000")
‘顯示英寸單位最大值,3位小數
End If
If WW < MinW And WW > -51 Then
‘判斷最小值
MinW = WW
Label1(4) = Format(MinW, “0.00")
‘顯示毫米單位最小值,2位小數
Label1(5) = Format(MinW/25.4,“0.000")
   ‘顯示英寸單位最小值,3位小數
End If
.RThreshold = 1
‘打開MSComm1事件接收
End If
Case Else
End Select
End With
End Sub

1992年Crescent Software Inc.公司專為VB設計了MSCOMM.VBX用戶通信控件,它提供了通過串口發送和接收數據的串行通信能力,不但包括了全部Windows API中關于串行通信的16個函數所完成的功能,而且開拓了更多的使用戶設計方便的對象屬性來滿足不同用戶不同業務的需求。目前國內眾多的VB資料中很少涉及該通信控件的介紹,本文將詳細介紹MSCOMM.VBX通信控件及編程方法,并結合工作中的一個實例給出基本通信程序。

1 MSCOMM.VBX通信控件描述

MSCOMM.VBX通信控件可直接從VB的ToolBox中加入窗體Form,即可用其進行通信。若ToolBox中無此控件,則用Tools的Custom Controls 將MSCOMM.VBX從Windows的System子目錄中加入VB的ToolBox中。

1.1 通信方式

MSCOMM.VBX有2種不同的方式來處理和解決各類通信軟件的開發和設計問題

1、事件驅動。它與C/C++寫Windows 軟件時的窗口回調函數類似,是1種功能強大的處理問題的方法。在實際工作中,往往要處理許多通信中的相關事件,例如:當線路數據到達本端或CD線和RTS信號線狀態發生變化時,要求我們使用相應的事件來跟蹤和處理,該控件是使用OnComm事件來實現的,它也包括檢測和處理通信錯誤等方面的問題,CommEvent 值返回最近的通信事件或錯誤的數字代碼。通信控件詳細的錯誤和事件舉例有:

MSCOMM-ER-BREAK 收到1個Break Signal

MSCOMM-ER-CDTO CD 信號超時

……

MSCOMM-EV-CD CD信號改變

……

2、查詢方式。由程序設計者負責讀取CommEvent的值并處理所發生的錯誤或事件。通常簡單的應用程序設計可采用這種辦法。

1.2 通信控件的屬性

利用通信控件編制通信程序,關鍵是準確理解設置通信控件的屬性。MSCOMM.VBX提供了27個關于通信控件方面的屬性,例如:

CommPort:設置或返回通信口編號。

Settings:設置或返回以字符串形式出現的數據通信格式:波特率、校驗、數據位和停 止位。

PortOpen:設置或返回通信口狀態(包括打開和關閉1個通信口)

……

3、 實例

本程序應用背景為DCC95型靜電除塵器自動監控系統軟件,解決1個PC工控機(主站)與32個單片機(子站)之間的通信問題。主站與子站之間這總線式網絡結構,采用RS-485通信標準,以問答方式進行數據通信。由于32個子站與主站發送通信命令(下行命令),主站在接收子站發回的相應回答命令(上行命令)后繼續發送下行命令的通信形式。根據系統功能的要求,主站需發送2種類型的命令:(1)同期命令,它由定時器觸發引起,每隔ls周期發送1次;(2)非周期性命令,它由操作者按動相應命令按鈕引起,非周期性發送。自動監控系統軟件安裝在主站上,而通信程序作為自動監控系統軟件的一部分也安裝在主站上。

本文僅列出調試通信程序時進行試驗用的基本演示程序清單。試驗時,用1臺PC機作為主站,另一臺PC機模擬32個子站的工作,兩臺PC機之間采用RS232c串口通信。往主站的通信演示程序窗體(form)中加入1個通信控件、2個定時器控件和1個命令按鈕控件,通信控件(Mscomm1)用于訪問串口,發送和接收數據;Periodic定時器控件(Periodic)用于控制每秒由主站向各子站發送周期性命令;命令按鈕控件(NonPeriodic-Command)與NonPeriodic定時器控件(NonPeriodic)用于發送非周期性命令。數據傳送采用事件驅動的通信方式,根據不同的發送命令設置RTreshlod屬性,從而引起OnComm事件以接收數據。

2.1 窗體各控件初始化程序

設置通信串口工作參數,設置Periodic定時器的在斷間隔為ls, NonPeriodic定時器的中斷間隔為0.5s。

Sub Form-Load ()

Mscomm1.CommPort=2 ’選用COM2串行口

Mscomm1.Settings="9600,N8,1" ’波特率9600,無奇偶校驗位,8位數據位1位停止位

Mscomm1.InputLen=0 ’Input將讀取接收緩沖區的全部內容

Mscomm1.InBufferSize=1024 ’設置接收緩沖區的字節長度

Mscomm1.PortOpen=True ’打開通信口

Mscomm1.InBufferCount=0 ’清除發送緩沖區數據

Mscomm1.OutBufferCount=0 ’清除接收緩沖區數據

Periodic.inteval=100 ’設置ls定時間隔,使遙測命令每隔ls發送1次

NonPeriodic.inteval=500 ’設置0.5s定時間隔,查詢命令按鈕是否處于激活狀態以確定是否發送周期性命令

Command-Pressed=False ’命令按鈕為未激活狀態

During- Periodic=False ’周期性命令數據傳輸尚未開始

During- NonPeriodic=False ’非周期性命令數據傳輸尚未開始

End Sub

2.2 非周期性命令發送程序

根據命令按鈕狀態及周期性命令數據傳輸狀態,在NonPeriodic定時器的中斷程序中發送非周期性命令。

Sub NonPeriodic-Command-Click ()

Command-Pressed=True ’命令按鈕激活

End Sub

Sub NonPeriodic-Timer ()

if During- Periodic=True OR Command-Pressed=False

Then Exit Sub ’若周期性命令數據傳輸尚未結束或命令按鈕處于激活狀態,則退出發送非周期性命令程序。

Command-Pressed=False ’命令按鈕恢復為未激活狀態

Call SendData (NONPERIODIC-COMMAND) ’發送非周期性命令

Mscomm1.RThreshold=R-NONPERIODIC-BYTE’發送非周期性命令后,設置Rthreshold屬性,使主站接收所設定的字節數后引發OnComm事件

End Sub

2.3 Periodic定時器程序

在Periodic定時器的中斷程序中發送周期性命令:

Sub Periodic-Timer ()

if During- NonPeriodic=True Then Exit Sub ’若非周期性命令數據傳輸尚未結束,則退出發送非周期性命令程序。

During-Periodic=True ’設置周期性命令數據傳輸狀態為正在進行中

Call SendData (PERIODIC-COMMAND) ’發送周期性命令

Mscomm1.RThreshold=R-PERIODIC-BYTE ’發送周期性命令后,主站接收R-REMOT- EDATA-BYTE個字節,可引發OnComm 事件

End Sub

2.4 OnComm事件程序

根據RThreshold屬性設置值,當接收緩存區內接收到相應字節的字符時,引發OnComm事件,在中斷程序中接收數據。

Sub Mscomm1-OnComm ()

Select Case Mscomm1.CommEvent ’在此可插入處理各種不同錯誤或事件的代碼

Case MSCOMM-EV-RECEIVE

ReceiveString$=Mscomm1.Input

Select Case Mscomm1.RThreshold

Case R-PERIODIC-BYTE ’周期性命令的應答數據

Call DisposeData(PERIODIC-COMMAND) ’處理接收數據

During Periodic=False ’設置周期性命令數據傳輸狀態為結束

Case R-NONPERIODIC-BYTE ’非周期性命令的應答數據

Call DisposeData(NONPERIODIC-COMMAND) ’處理接收數據

During-Nonperiodic=False ’設置非周期性命令數據傳輸狀態為結束

End Select

End Select

End Sub

------------------------------------------------------------------------

隨著VB版本的不斷升級,VB將成為最快速、易用、強勁的應用開發工具,是企業級客戶/服務器應用軟件開發的首選工具之一。

VB有一個例子在Samples\CompTool\Mscomm中。你可以利用這個例子來學習串口編程。
     打開串口先設置CommPort屬性(端口號),使用PortOpen=True就可以了。
     串口數據保存在MSComm的Input屬性中。你可以使用下面的代碼:
     Dim v As Variant
     v = MSComm1.Input
     For i = 0 To MSComm1.InBufferCount - 1
      Debug.Print v(i)
     Next
  
現有電子秤一臺,使用串口與計算機進行通訊。編寫VB程序來訪問串口,達到讀取電子秤上顯示的數據。該電子秤為BE01型儀表,輸出為RS-232C標準接口,波特率為300-9600、偶校驗、7個數據位、2個停止位。所有字符均發送11位ASCII碼,一個起始位。在VB中與串口通訊需要引入控件MSComm串口通訊控件(在Microsoft Comm Control 6.0中)。具體程序如下:控件簡稱:MSC

Dim Out(12) As Byte '接收var中的值
Dim var As Variant '接收MSC.input中的數值
Dim nRece As Integer '計算MSC.inputbuffer的個數
Dim i As Integer, j As Integer '隨即變量,計算循環

****************************************************************************

Private Sub Form_Load()
 ClearText
 With MSC
  .CommPort = 1 '設置Com1為通信端口
  .Settings = "9600,E,7,2" '設置通信端口參數 9600赫茲、偶校驗、7個數據位、1個停止位.(這里需要進一步說明的是:.Setting=”BBBB,P,D,S”。
  含義是:B:Baud Rate(波特率);P:Parity(奇偶);D:Data Bit;S:Stop Bit)

  .InBufferSize = 40 '設置緩沖區接收數據為40字節
  .InputLen = 1 '設置Input一次從接收緩沖讀取字節數為1
  .RThreshold = 1 '設置接收一個字節就產生OnComm事件

 End With

End Sub

****************************************************************************

Private Sub ClearText()
 Text3.Text = ""
 Text2.Text = "5"
 Text1.Text = ""
End Sub

Private Sub Command1_Click()
 ClearText
 ' nRece = 0 '計數器清零
 With MSC
  .InputMode = comInputModeBinary '設置數據接收模式為二進制形式
  .InBufferCount = 0 '清除接收緩沖區
  If Not .PortOpen Then
   .PortOpen = True '打開通信端口
  End If
 End With
End Sub

Private Sub MSC_OnComm()
 DelayTime ‘用來延續時間
 ClearText
 With MSC
  Select Case .CommEvent '判斷通信事件
  Case comEvReceive: '收到Rthreshold個字節產生的接收事件
   SwichVar 1
   If Out(1) = 2 Then '判斷是否為數據的開始標志
    .RThreshold = 0 '關閉OnComm事件接收
   End If
   Do
    DoEvents
   Loop Until .InBufferCount >= 3 '循環等待接收緩沖區>=3個字節
   ' nRece = nRece + 1
   For i = 2 To 12
    SwichVar i
    Text1.Text = Text1.Text & Chr(Out(i))
   Next
   Text1.Text = LTrim(Text1.Text)
   Text2.Text = Text2.Text & CStr(nRece)
   .RThreshold = 1 '打開MSComm事件接收
  Case Else
   ' .PortOpen = False
  End Select
 End With

End Sub

****************************************************************************

Private Sub DelayTime()

 Dim bDT As Boolean
 Dim sPrevious As Single, sLast As Single

 bDT = True

 sPrevious = Timer (Timer可以計算從子夜到現在所經過的秒數,在Microsoft Windows中,Timer函數可以返回一秒的小數部分)

 Do While bDT
  If Timer - sPrevious >= 0.3 Then bDT = False
 Loop
 bDT = True

End Sub

(通信傳輸速率為9600bps,則最快速度1.04ms發送一個字節,儀表每秒發送50幀數據,每幀數據有4個字節,即每秒發送200個字節,平均5.0ms 發送一個字節,連續讀取串口數據時要在程序中添加循環等待程序)

Private Sub SwichVar(ByVal nNum As Integer)

 DelayTime
 var = Null
 var = MSC.Input
 Out(nNum) = var(0)

End Sub

(設置接收數據模式采用二進制形式,即 InputMode=comInputModeBinary,但用Input屬性讀取數據時,不能直接賦值給 Byte 類型變量,只能通過先賦值給一個 Variant 類型變量,返回一個二進制數據的數組,再轉換保存到Byte類型數變量中。)

Private Sub Text1_Change()

 Text3.Text = CText(Text1.Text) - CText(Text2.Text)

End Sub

****************************************************************************

Private Function CText(ByVal str As String) As Currency

 If str <> "" Then
  CText = CCur(Val(str))
 Else
  CText = 0
 End If

End Function

  (儀表每秒發送50幀數據,微機收到一幀完整數據至少需要20 ms時間,然后再進行數據處理。如果微機在下一幀數據接收前即20ms內能將數據計算處理完畢,則接收緩沖區內只會保存有一幀數據,不會存有兩幀以上數據,接收緩沖區的大小不會影響實時監測效果(接收緩沖區>4字節),這時完全可以實現實時監測或實時控制;如果微機在20ms內不能將數據計算處理完畢,接收緩沖區設置得又很大,在數據計算處理完畢前,接收緩沖區內就會保存有兩幀以上數據,而且一次工作時間越長,緩沖區內滯留數據幀就越多,數據采集和數據處理之間產生逐漸增大的額外時間差,當接收緩沖區充滿后,時間差不再增大,固定在某一值,部分數據因不能及時采集到接收緩沖區中,數據產生丟失現象,真實工作情況就會和微機處理結果產生較大的時間差,對實時監測和實時控制很不利,這種情況下接收緩沖區的大小就會影響實時監測效果,所以接收緩沖區設置不能過大,以保證數據處理的實時性。) 小結:本文所用的儀表為梅特勒公司出產的BE01型電子秤,其輸出的每個編碼均為標準的ASCII碼。其他的儀表存在發射的編碼中含有BCD壓縮碼,而且分為高低位,需要接收后對其進行解碼換算,之后還要將高位和低位數字進行相加,即可以將其BCD碼換算成實數。另還存在誤差的可能:判斷最大值,儀表在剛開始工作時有干擾,會傳導一些亂碼,位移傳感器有參數偏差,最大值一般都略大于50毫米,所以取51為極限最大值,取-51為極限最小值。暫時先寫這些,當然其他的情況可以依此類推!

串口數據接收方式
如何處理不定長數據的接收
用字符方式收發碼值大于127的字符數據
串口通訊問答2


串口數據接收方式

1、 在OnComm 事件中接收數據:
這種方式能充分MSCOMM控件的特性。OnComm 事件還可以檢查和處理通訊錯誤;可以通過檢查 CommEvent 屬性的值來查詢事件和錯誤;對于不定長數據以及對數據進行處理比較復雜的情況,此法不是很方便。

Private Sub MSComm_OnComm ()
Select Case MSComm1.CommEvent

' 錯誤
Case comEventBreak ' 收到 Break。
Case comEventCDTO ' CD (RLSD) 超時。
Case comEventCTSTO ' CTS Timeout。
Case comEventDSRTO ' DSR Timeout。
Case comEventFrame ' Framing Error
Case comEventOverrun '數據丟失。
Case comEventRxOver'接收緩沖區溢出。
Case comEventRxParity' Parity 錯誤。
Case comEventTxFull '傳輸緩沖區已滿。
Case comEventDCB '獲取 DCB] 時意外錯誤

' 事件
Case comEvCD ' CD 線狀態變化。
Case comEvCTS ' CTS 線狀態變化。
Case comEvDSR ' DSR 線狀態變化。
Case comEvRing ' Ring Indicator 變化。
Case comEvReceive ' 收到 RThreshold # of chars.
Case comEvSend ' 傳輸緩沖區有 Sthreshold 個字符 '
Case comEvEof ' 輸入數據流中發現 EOF 字符

End Select
End Sub

2.輪循法采集數據:
A、定時器輪循法
對于數據包方式收發數據以及不需即時響應情況,用輪循法更好些。實際上輪循法最大的好處在于集中處理數據而且不太占用CPU。輪循法要注意定時采集的時間片段大小;這里用二進制收發模式;使屬性RThreshold、SThreshold為0,屏蔽ONCOMM事件。

InputMode = comInputModeBinary
RThreshold = 0
SThreshold = 0

Private Sub TmrComm_Timer()
'采用輪循法采集數據
Dim Rx_buff() As Byte
Dim okstring As String
Dim ReceivedLen As Integer

On Error GoTo ErrorHandler
TmrComm.Enabled = False '關閉定時器
If commport.InBufferCount > 0 Then
ReceivedLen = commport.InBufferCount
Rx_buff = commport.Input
okstring = StrConv(tempbyte, vbUnicode)
If ReceivedLen = 6 Then
If Chr(tempbyte(0)) = ":" And tempbyte(3) = &h0a Then
....
End If
If Instr(okstring ,":@END*",vbBinaryCompare) Then
....
End If
End If
TmrComm.Enabled = True '打開定時器
End Sub

B、直接輪循法
此法用于接收少量控制命令字;
' 保存輸入子串的緩沖區
Dim Instring As String
' 使用 COM1。
MSComm1.CommPort = 1
' 9600 波特,無奇偶校驗,8 位數據,一個停止位。
MSComm1.Settings = "9600,N,8,1"
' 當輸入占用時,
' 告訴控件讀入整個緩沖區。
MSComm1.InputLen = 0
' 打開端口。
MSComm1.PortOpen = True
' 將 attention 命令送到調制解調器。
MSComm1.Output = "ATV1Q0" & Chr$(13)
' 確保
' 調制解調器以"OK"響應。
' 等待數據返回到串行端口。
Do
DoEvents
Buffer$ = Buffer$ & MSComm1.Input
Loop Until InStr(Buffer$, "OK" & vbCRLF)
' 從串行端口讀 "OK" 響應。
' 關閉串行端口。
MSComm1.PortOpen = False



如何處理不定長數據的接收

在處理串口通訊時,經常會遇到不定長數據的接收。由于通訊任務不同及編程要求的差異所以采用的方法也有所不同。本文就此問題進行探討。不定長數據從數據格式上分,可分為有格式和無格式。

一、無格式不定長數據的接收
這種格式在實際串口通訊中用得不多,一般只用傳送字符串數據。問題在于怎么判斷接收結束。一般用時間延遲的方法解決。
A、對于非握手式通訊,可用一個定時器定時輪循接收,并假定每個輪循接收完成。用ONCOMM事件接收也可,只是不如定時器定時輪循接收簡便。
B、對于握手方式通訊,可用直接輪循法提高接收的準確性。下面是實現此法的函數:

Function sComm(sCommand As String, comReceive As MSComm) As String
Dim nReceiveCount As Integer
If comReceive.PortOpen = False Then
comReceive.PortOpen = True
End If

comReceive.Output = sCommand

Do
nReceiveCount = comReceive.InBufferCount
sleep (2) 'API 函數,掛起當前進程一段時間
Loop Until comReceive.InBufferCount = nReceiveCount
If comReceive.PortOpen = True Then
sComm = comReceive.Input
End If
End Function
注:此函數參照了xth一文。
此法一般是能確保數據接收的正確,但由于WINDOWS是多任務操作系統,當有耗時的進程運行時會丟失數據。如果系統會出現這種情況,可增大函數sleep()的參數值。

二、不定長格式數據的接收
對于不定長數據接收最好的方法是制定通訊協議,比如定義開始字符和結束字符。由于單片機系統通訊一般不太復雜,沒必要去制定一套象通用計算機間通訊的協議,而根據單片機系統的大小和性能要求制定通訊協議。實際上為便于交流、維護以及一致性,可制定一套可伸縮的通訊協議。定義了開始字符和結束字符就容易實現不定長格式數據通訊,但在實際通訊編程還是容易出現一些比較隱蔽的通訊錯誤。下面就常用方法分別進行分析。
A、定時器輪循法。
假定每個輪循期數據接收完畢,并在每個輪循期處理數據,由于有開始字符和結束字符很容易確定接收數據的完整性。好象合理設定輪循時間值就萬無一失了,但被動接收數據時無論如何也找不合適的輪循時間值,因為啟動定時器和數據到來基本不同步,這就會出現一次發送的數據被分在兩個輪循期接收,所以被動接收數據時不能假定每個輪循期數據接收完畢。在接收到結束字符后才確定一次數據接收完畢就可解決此問題。
B、OnComm事件法。
方法和定時器輪循法基本相同,因為每次OnCommg事件也只能接收到一部分數據。在VB的在線幫助中這樣注解“設置 Rthreshold 為 1,接收緩沖區收到每一個字符都會使 MSComm 控件產生 OnComm 事件。”。但實際上OnComm事件并不是每收到一個字符便觸發一次 OnComm 事件。OnComm事件是在緩沖區收到幾個甚至幾十個字節數據后才被觸發的。版主認為這是WINDOWS多任務使操作系統不能實時響應造成的。如果要在每次OnComm事件接收一個字符似乎可設INPUTLEN屬性為1,但實際行不通。VB在線幫助中“有該屬性在從輸出格式為定長數據的機器讀取數據時非常有用”的注解,好象在說對定長字符有效,但版主發現INPUTLEN設為16,接收16個字符定長數據時卻被當作兩次接收了,一次12個,一次4個。建議在OnComm事件中接收數據要定義通訊協議并檢測數據的完整性。 對于不定長格式數據的接收程序員更喜歡定時器輪循法,也許OnComm事件不好控制吧。
對于不定長數據的接收,最佳方法可能是在OnComm事件中啟動定時器輪循接收,并同時停止OnComm事件的觸發,接收完畢后或超時開啟OnComm事件。


用字符方式收發碼值大于127的字符數據

VB的通訊控件友好、功能強大,編程速度快是眾人皆知的。加上VB的易學、易用,快速開發等特點,數據通訊量不是很大時,在單片機通訊領域廣泛地使用VB開發PC上層通訊軟件。實際開發時會有不少問題,這里就用字符方式收發碼值大127的字符數據進行討論。
在實際開發中經常遇到通訊只是用來發送一些控制字符命令和少量數據。在VB的中文在線幫助中有“若數據只用 ANSI 字符集,則用 comInputModeText”的表述。 ANSI字符集是0-127這容易使人誤解為&h88也可用“INPUTMIDE=comInputModeText”方式收發。我剛開始用VB編通訊模塊時就為此迷惑過,網上不少網友也時常問及這種問題。實際上在VB中0-127是可以正常收發的,大于127即&H7F的只有&H80和&HFF能夠收發,其余ANSI字符都被過濾為0。由于串口通訊是以字節收發的,數據如以comInputModeText模式收發則非字符串數據會被過濾。在VB中用“INPUTMIDE = comInputModeBinary” 就可以解決這個問題,只是收發都必須用動態數組來完成。用comInputModeBinary模式編程稍有點復雜,調試也不直觀,對于初學者不易掌握。另外軟件完成后,在實際應用時會增加工程維護難度,因為對于二進制代碼不是易于理解的。比如下端機發送現場統計數據233,comInputModeBinary模式下串口監測到“:A &H233;",它代表A探針的溫度。一般串口監測軟件要么用ASCII方式顯示,要么用二進制方式顯示。用ASCII方式則不能看到&H233,而二進制方式則示不好理解,如果顯示58 65 233 59,我想沒有人喜歡這種方式(如果有更好的方式的話)。但如果顯示“:A 2 3 3 ;”不就解決問題了!用comInputModeText方式就可完成任務了,只是多了一段數據分離程序。對于一般通訊要求這種方法不為是一種好方法。由于通訊任務是多種多樣的,有時候這種方法就有點力不從心了,如傳送較多的的數據時,這會顯著地增加通訊量,通訊變得復雜了,對于單片機系統就不太合適了;還有一些特殊要求,如數據包的識別符也不適此法,但能確定傳送數據碼值范圍也可用此法。下面介紹另一種方法,此法適用比較廣,傳送二進制數據通訊量增加也不大。
這種方法實際上很簡單,實際運用中有不少采用此法。原理是一碼分為二碼。如設7E為臨界字符,對于7E則分為7E和0兩個ASCII碼,依此類推,8F分為7E和11。接收合并時遇到7E則將7E和后一個ASCII碼相加為下字符。下面給出C語言函數,VB轉換一下便可。
由于C語言不能返回兩個參數,所以用數組指針。


void Filt(char code[],char c)
{
if(c=='F')
{
if(code[0]>=0X7E)
{
code[1]=code[0]-0X7E;
code[0]=0X7E;
}
else
{
code[1]=0XFF; /*0XFF作為標記code[1]不可能產生0XFF*/
}
}
else if(c=='H')
{
if(code[0]!=0X7E)
{
code[1]=0xFE; /*轉換完成標記*/
}
else
{
if(code[1]==0XFE)
{
code[1]=0XFF; /*接收下一個碼的標記*/
}
else
{
code[0]=code[0]+code[1];
code[1]=0XFE;
}
}
}
發送時:
char SendChar[2]; /*存儲發送的值*/
....
SendChar[0]=c; /*c為待發ASCII碼*/
Filt(SendChar,'F');
if(SendChar(1)==0XFF)
{
..... /*發送SendChar[0]*/
}
else
{
...... /*發送SendChar[0],SendChar[1]*/
}
接收時:
char ReceiveChar[2]; /*存儲接收的值*/
.....
ReceiveChar[0]=c0; /*c0接收的ASCII碼*/
Filt(ReceiveChar,'H');
if(ReceiveChar[1]==0xFF)
{
ReceiveChar[1]=c1; /*c1為下一個*/
Filt(ReceiveChar,'H);
}
else if(ReceiveChar[1]==0xFE)
{
...... /*存儲轉換后的ReceiveChar[0]*/
}
以上代碼僅提供一種思路,實際情況視編程需要而定。


串口通訊問答錄
1、Q:各位vb高手:我有一個問題想請教一下。我從COM口用BIN方式接收到數據(一串漢字),存入一BYTE數組,但無法還原為一串漢字,我認為是ANSI和UNICODE的轉換,請問如何轉換。
例:字符串“我”,按BIN方式接收成一BYTE數組,其值為“206,210”,如用“CHR(206)+CHR(210)”卻無法得到“我”,實際上“我”=CHR(-12860)請問如何能實現BYTE數組(206,210)與字符串“我”之間的轉換?萬分感謝!!!

JY
1999.10
A:經CHR(206)+CHR(210)轉換后實際上變成了兩個UNICODE字符,四個字節了。漢字的收發必須用BINARY方式。下面的程序能實現漢字收發。
發:
Dim ytemp() As Byte
Dim stemp As String
stemp = "你好!"
ytemp = StrConv(stemp, vbFromUnicode)
Debug.Print UBound(ytemp)
MSComm1.Output = ytemp
收:
Private Sub mscTest_OnComm()
'中文收發
Dim yTemp() As Byte
Dim stemp As String
Dim i As Integer
If mscTest.InBufferCount > 0 Then
i = mscTest.InBufferCount
yTemp = mscTest.Input
stemp = StrConv(yTemp, vbUnicode)
txtTest1.Text = stemp
End If
End Sub


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美激情视频一区二区三区免费 | 国产精品久久亚洲 | 亚洲精品乱码久久久久久蜜桃91 | 天天影视网天天综合色在线播放 | 欧美精品一区二区三区四区五区 | 国产一区二区在线视频 | 狠狠久久| 91精品一区| 天天干干 | 丝袜 亚洲 欧美 日韩 综合 | 九九在线视频 | 色视频在线免费观看 | 欧美成人视屏 | 国产成人免费视频 | 日本精品一区二区三区在线观看视频 | 人和拘一级毛片c | 日韩在线欧美 | 淫片一级国产 | 欧美黄在线观看 | 99精品国产在热久久 | 国内精品久久久久久影视8 最新黄色在线观看 | 亚洲毛片在线观看 | 天堂在线www | 欧美男人天堂 | 国产综合网址 | 成人在线免费观看 | 99精品国自产在线 | 精品国产乱码久久久久久老虎 | 国精产品一区一区三区免费完 | 久久久久久国产一区二区三区 | 中文在线视频 | 国产一区二区三区视频 | 女女爱爱视频 | 国产精品亚洲第一区在线暖暖韩国 | 日韩亚洲一区二区 | 亚洲毛片| 欧美日韩视频在线第一区 | 日韩在线视频一区 | av黄色免费在线观看 | 久久99精品久久久97夜夜嗨 | 久久出精品 |