㈠ 單片機與VB的通信
分有沒多點啊?
程序在這:
VERSION 5.00
Object = "{648A5603-2C6E-101B-82B6-000000000014}#1.1#0"; "MSCOMM32.OCX"
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 5235
ClientLeft = 60
ClientTop = 465
ClientWidth = 6990
Icon = "Form1.frx":0000
LinkTopic = "Form1"
ScaleHeight = 5235
ScaleWidth = 6990
StartUpPosition = 3 '窗口預設
Begin MSCommLib.MSComm MS
Left = 3840
Top = 4080
_ExtentX = 1005
_ExtentY = 1005
_Version = 393216
DTREnable = -1 'True
End
Begin VB.CommandButton Command5
Caption = "清除"
Height = 375
Left = 3600
TabIndex = 26
Top = 3240
Width = 615
End
Begin VB.CommandButton Command4
Caption = "清除"
Height = 375
Left = 3600
TabIndex = 25
Top = 2040
Width = 615
End
Begin VB.Frame Frame2
Height = 555
Left = 120
TabIndex = 14
Top = 0
Width = 6795
Begin VB.ComboBox Comset0
Height = 300
Index = 0
ItemData = "Form1.frx":0442
Left = 540
List = "Form1.frx":046A
Style = 2 'Dropdown List
TabIndex = 19
Top = 180
Width = 735
End
Begin VB.ComboBox Comset
Height = 300
Index = 1
ItemData = "Form1.frx":04B9
Left = 1920
List = "Form1.frx":04F0
Style = 2 'Dropdown List
TabIndex = 18
Top = 180
Width = 915
End
Begin VB.ComboBox Comset
Height = 300
Index = 2
ItemData = "Form1.frx":0561
Left = 3480
List = "Form1.frx":056E
Style = 2 'Dropdown List
TabIndex = 17
Top = 180
Width = 915
End
Begin VB.ComboBox Comset
Height = 300
Index = 3
ItemData = "Form1.frx":0589
Left = 4920
List = "Form1.frx":059C
Style = 2 'Dropdown List
TabIndex = 16
Top = 180
Width = 615
End
Begin VB.ComboBox Comset
Height = 300
Index = 4
ItemData = "Form1.frx":05AF
Left = 6120
List = "Form1.frx":05B9
Style = 2 'Dropdown List
TabIndex = 15
Top = 180
Width = 615
End
Begin VB.Label Label2
Caption = "串口"
Height = 195
Index = 5
Left = 120
TabIndex = 24
Top = 240
Width = 435
End
Begin VB.Label Label2
Caption = "波特率"
Height = 195
Index = 1
Left = 1380
TabIndex = 23
Top = 240
Width = 555
End
Begin VB.Label Label2
Caption = "數據位"
Height = 255
Index = 2
Left = 4380
TabIndex = 22
Top = 240
Width = 615
End
Begin VB.Label Label2
Caption = "奇偶位"
Height = 255
Index = 3
Left = 2880
TabIndex = 21
Top = 240
Width = 675
End
Begin VB.Label Label2
Caption = "停止位"
Height = 255
Index = 4
Left = 5580
TabIndex = 20
Top = 240
Width = 555
End
End
Begin VB.TextBox Text3
Height = 735
Left = 360
MultiLine = -1 'True
ScrollBars = 2 'Vertical
TabIndex = 12
Text = "Form1.frx":05C3
Top = 2040
Width = 3015
End
Begin VB.TextBox Text1
Height = 1215
Left = 360
MultiLine = -1 'True
TabIndex = 11
Text = "Form1.frx":05CA
Top = 720
Width = 1695
End
Begin VB.Timer Timer1
Interval = 500
Left = 4680
Top = 4440
End
Begin VB.CommandButton Command3
Caption = "DTR-ON"
Height = 375
Left = 5640
TabIndex = 6
Top = 4080
Width = 975
End
Begin VB.CommandButton Command2
Caption = "RTS-OFF"
Height = 375
Left = 5640
TabIndex = 5
Top = 3480
Width = 975
End
Begin VB.CommandButton Command1
Caption = "埠狀態"
Height = 375
Left = 4920
TabIndex = 3
Top = 2400
Visible = 0 'False
Width = 255
End
Begin VB.TextBox Text2
Height = 1455
Left = 360
MultiLine = -1 'True
ScrollBars = 2 'Vertical
TabIndex = 2
Top = 3240
Width = 3060
End
Begin VB.CommandButton Send
Caption = "發送"
Height = 615
Left = 5640
TabIndex = 1
Top = 2280
Width = 975
End
Begin VB.CommandButton Opencom
Caption = "打開串口"
Height = 615
Left = 5640
TabIndex = 0
Top = 960
Width = 975
End
Begin VB.PictureBox MS2
Height = 480
Left = 5400
ScaleHeight = 420
ScaleWidth = 1140
TabIndex = 27
Top = 4680
Width = 1200
End
Begin VB.Label Label6
Caption = "接收:"
Height = 375
Left = 360
TabIndex = 13
Top = 3000
Width = 495
End
Begin VB.Label Label5
Caption = "外設狀態:"
Height = 375
Left = 2160
TabIndex = 10
Top = 1320
Width = 855
End
Begin VB.Label Label4
Caption = "測試外設是否存在"
Height = 495
Left = 4680
TabIndex = 9
Top = 4080
Width = 855
End
Begin VB.Label Label3
Caption = "請求發送"
Height = 255
Left = 4680
TabIndex = 8
Top = 3600
Width = 855
End
Begin VB.Label Label2
Caption = "埠狀態"
Height = 375
Index = 0
Left = 2160
TabIndex = 7
Top = 720
Width = 735
End
Begin VB.Label Label1
Height = 375
Left = 3240
TabIndex = 4
Top = 1320
Width = 1815
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private CCount As Integer
Private Hexchange As Boolean
Private RTS As Boolean
Private Sendhexdata() As Byte
Private Nosend As Boolean
Private Sub Combo1_Click()
On Error GoTo Combo1_Error
If MS.PortOpen Then
If MS.CommPort <> (Combo1.ListIndex + 1) Then
If MsgBox("埠" & MS.CommPort & "正在使用,你要停止它並使用新的埠嗎?", vbYesNo + vbExclamation + vbDefaultButton2, "更改埠?") = vbYes Then
Call Opencom_Click
MS.CommPort = Combo1.ListIndex + 1
Label1 = " 埠更改為" & MS.CommPort
Else
Combo1.ListIndex = MS.CommPort - 1
Exit Sub
End If
End If
Else
MS.CommPort = Combo1.ListIndex + 1
End If
Exit Sub
Combo1_Error:
MsgBox "埠打開錯誤", vbInformation
End Sub
Private Sub Command1_Click()
Text1 = "CDHolding:" & MS.CDHolding & Chr(13) & " CTSHolding:" & MS.CTSHolding & Chr(13) _
& " DSRHolding:" & MS.DSRHolding & Chr(13) & " InBufferCount:" & MS.InBufferCount & Chr(13) _
& " OutBufferCount:" & MS.OutBufferCount & Chr(13) & " PortOpen:" & MS.PortOpen
End Sub
Private Sub Command2_Click()
If MS.RTSEnable Then
MS.RTSEnable = False
Command2.Caption = "RTS-OFF"
Else
MS.RTSEnable = True
Command2.Caption = "RTS-ON"
End If
Call Command1_Click
End Sub
Private Sub Command3_Click()
If MS.DTREnable Then
MS.DTREnable = False
Command3.Caption = "DTR-OFF"
Else
MS.DTREnable = True
Command3.Caption = "DTR-ON"
End If
Call Command1_Click
End Sub
Private Sub Command4_Click()
Text3 = ""
End Sub
Private Sub Command5_Click()
Text2 = ""
End Sub
Private Sub Comset_Click(Index As Integer) '埠屬性值設置
On Error GoTo ComsetError
comsetd1 = Comset(2).ListIndex
comsett1 = "n"
Select Case comsetd1
Case 0
comsett1 = "n"
Case 1
comsett1 = "o"
Case 2
comsett1 = "e"
End Select
MS.Settings = Comset(1).Text & "," & comsett1 & "," & Comset(3).Text & "," & Comset(4).Text
Exit Sub
ComsetError: '錯誤處理
MsgBox "埠屬性值無效!" & Te & Te & "將恢復為默認值(9600,N,8,1)", vbCritical
MS.Settings = "9600,n,8,1"
Comset(1).ListIndex = 9
Comset(2).ListIndex = 0
Comset(3).ListIndex = 0
Comset(4).ListIndex = 0
End Sub
Private Sub Comset0_Click(Index As Integer)
If MS.PortOpen Then Call Opencom_Click
MS.CommPort = Comset0(0).ListIndex + 1
End Sub
Private Sub Form_Load()
Comset0(0).ListIndex = 3
Comset(1).ListIndex = 9
Comset(2).ListIndex = 0
Comset(3).ListIndex = 0
Comset(4).ListIndex = 0
Call Timer1_Timer
End Sub
Private Sub MS_OnComm()
On Error GoTo OncommError
Dim Breceive() As Byte
Dim Sreceive As String
Dim intValue As Integer
Select Case MS.CommEvent
Case comEvReceive '接收數據
Sreceive = MS.Input
Text2 = Text2 & Sreceive '字元接收
' MsgBox "wate:"
'--------------------------------
Case 1001
MsgBox "收到斷開信號!", vbInformation
Case 1002
MsgBox "准備發送時,CTS為低", vbInformation
Case 1003
MsgBox "准備發送時,DSR為低", vbInformation
Case 1004
MsgBox "數據幀錯誤!", vbCritical
Case 1006
MsgBox "埠溢出!", vbCritical
Case 1007
MsgBox "准備發送時,CD為低", vbInformation
Case 1008
MsgBox "接收緩沖區溢出!", vbCritical
Case 1009
MsgBox "奇偶校驗錯!", vbCritical
Case 1010
MsgBox "發送緩沖區滿!", vbCritical
Case 1011
MsgBox "檢取埠時,發生了沒預料的錯誤!", vbCritical
'------------
Case 1
MsgBox "發送緩沖區字元小於設定值!", vbExclamation
Case 2
MsgBox "接收到" & MS.RThreshold & "個字元"
Case 3
'MsgBox IIf(MS.ctsRHolding, "可以發送", "不能發送")
Label1 = IIf(MS.CTSHolding, "可以發送", "不能發送")
Case 4
'MsgBox IIf(MS.dsrHolding, "外設接入", "外設移出")
Label1 = IIf(MS.DSRHolding, "外設接入", "外設移出")
Case 5
'MsgBox IIf(MS.CDHolding, "響鈴", "")
Label1 = IIf(MS.CDHolding, "CD置位", "CD復位")
Case 6
Label1 = IIf(MS.CDHolding, "響鈴", "不響")
Case Else
MsgBox "意外事件!代碼:" & MS.CommEvent, vbCritical
End Select
Exit Sub
OncommError:
MsgBox "設備出錯!代碼:" & Err.Number, vbCritical
End Sub
Private Sub Opencom_Click()
On Error GoTo PortError
If Not MS.PortOpen Then
MS.PortOpen = True
Opencom.Caption = "關閉串口"
Label1 = "設備 " & MS.Object & " Id: " & MS.CommID
Else
MS.PortOpen = False
Opencom.Caption = "打開串口"
End If
Call Command1_Click
Exit Sub
PortError: '錯誤處理
Select Case Err.Number
Case 8002
MsgBox "串口 " & MS.CommPort & " 不存在!", vbExclamation
Case 8005
MsgBox "串口 " & MS.CommPort & " 被佔用!", vbInformation
Case 380
MsgBox "無效的屬性值!", vbInformation
Case 8012
MsgBox "串口 " & MS.CommPort & " 沒有打開!", vbInformation
Case 8015
MsgBox "不能設置串口 " & MS.CommPort & "通信狀態!", vbInformation
Case 8019
MsgBox "串口 " & MS.CommPort & " 忙!", vbInformation
Case 8020
MsgBox "串口 " & MS.CommPort & " 錯誤!", vbInformation
Case Else
MsgBox "其它錯誤:" & Err.Number, vbInformation
End Select
End Sub
Private Sub Send_Click()
Dim Send_text As String
If Not MS.PortOpen Then Call Opencom_Click
If Not MS.PortOpen Then Exit Sub
If Not MS.DSRHolding Then GoTo NoConnect
If Not MS.CTSHolding Then
'MsgBox "外設不允許發送!"
'Exit Sub
End If
Send_text = Text3
MS.Output = Send_text
Exit Sub
NoConnect:
MsgBox "外設" & MS.CommPort & "沒接入"
End Sub
Private Sub Timer1_Timer()
Call Command1_Click
Form1.Caption = Now
End Sub
㈡ DSP處理器和滑鼠內部的晶元是否有區別
HDNS2000光學感測晶元在運動檢測中的應 用2009年02月17日 星期二 下午 10:40
摘 要:安捷倫(Agilent)公司的hdns2000晶元是一種高性能的運動檢測器件,在目前的光學滑鼠中應用廣泛,其易用性和廉價性使其非常適合應用於中低精度的運動和位置檢測中。本文介紹hdns2000的功能、特點,從硬體與軟體兩個方面討論hdns2000與AVR單片機的介面設計。
關鍵詞:hdns2000 運動檢測 AVR
在機電產品設計中,有時需要檢測物體間的相對運動,包括運動方向和運動距離。若採用機械式的結構,比如機械滑鼠中的滾輪和軌跡球,則會由於頻繁的機械運動而發生故障,導致精度下降甚至失效,維修起來也不方便。另外它需要兩個物體表面相接觸,靠相互間的摩擦進行工作,這在某些場合是不能允許的。解決方案之一就是採用光電器件,運用光學原理來測定運動。安捷倫公司的hdns2000就是為此而設計的,雖然它的市場是針對光學滑鼠,但也可以作為一種高性能而又廉價的器件運用於工業控制領域中。
1 hdns2000晶元介紹
1.1 主要功能與特性
hdns2000是安捷倫推出的高性能的光學感測晶元,它的內部包含三個基本模塊:圖像拾取系統、DSP處理器、PS/2或四狀態輸出轉換器,如圖1所示。在hdns2000晶元的底部有一個感光眼,如同一個小型的攝像頭,不斷地對物體表面進行拍照,接著將前後兩次的圖像送入DSP中進行處理,以判斷物體移動的方向和大小,最後將數據轉化為PS/2格式或者以兩通道四狀態格式輸出。圖2中的(a)與(b)分別為晶元前後兩次拾取的圖像。比較圖2中的(a)和(b)可以看出,物體向左下方移動了一點。
hdns2000的圖像拾取系統每秒鍾可以拾取1500張圖像,可以精確地測量最高30.48 cm/s(12 英寸/s)的運動,解析度為400點每英寸。
1.2 引腳介紹
hdns2000的主要引腳框圖如圖3所示。
PS2_C:PS/2介面的時鍾端。
MODE/XA:復用引腳,接高電平時表示選擇PS/2模式;否則,為XA輸出。
RB/XB:復用引腳,PS/2模式時為滑鼠右鍵輸入;否則,為XA輸出。
MB/YB:復用引腳,PS/2模式時為滑鼠中鍵輸入;否則,為YB輸出。
LB/YA:復用引腳,PS/2模式為滑鼠左鍵輸入;否則,為YA輸出。
XY_LED:激光LED控制輸出,在物體長時間不移動時,hdns2000可以控制LED關閉,以節約能量。
VDD3:3.3 V直流電源輸入。
REFB:內部參考引腳,通過電容與VDD3相連。
PS2_D :PS/2介面的數據端。
NRESET:低電平復位引腳。
VDD5:5 V直流電源輸入。
GND:電源地。
OSC2:晶振輸出。
OSC1:晶振輸入,外接18.432 MHz晶振。
2 hdns2000與AVR單片機介面設計
2.1 hdns2000與AT90S8015介面
hdns2000直接提供有PS/2介面,方便了PS/2滑鼠的設計;但在機電控制中,為了提高效率,宜直接採用hdns2000的另一種輸出模式,即X向與Y向兩通道四狀態輸出模式。此時XA、XB指示X向移動狀態,而YA、YB指示Y向移動狀態。圖 4為hdns2000與AVR單片機AT90S8515的介面原理圖。介面主要佔用了4個引腳,其它兩個是可選的,所以,即使是AVR中最低檔的ATtiny系列也可以方便地與hdns2000連接。
另外在對節能要求不高的場合,可以將激光LED的一端直接與地相連接,而通過控制開關三極體2N3906來主動控制hdns2000的工作狀態。本文作者在設計時正是採用的這種方式。在進行系統設計時,最好採用安捷倫公司提供的套件,其中包括hdns2000晶元、HDNS2100透鏡、HDNS2200 激光LED卡件及HLMP-ED80激光LED,激光波長為639 nm。
2.2 四位狀態機的工作過程
在hdns2000內部有兩個狀態機分別指示X、Y兩個方向,每個狀態機又有四個穩定的狀態。圖5是狀態機的示意圖。由圖5可見,一開始系統處於狀態0,每當檢測到物體向正向或反向移動1個單位時就轉移到下一個狀態,所以只要連續監測狀態機狀態的變化就可以判斷物體移動的方向和距離。圖6(a)和(b)分別為負向移動和正向移動時狀態機輸出的波形。值得注意的是,每個狀態的最少停留時間為133μs。
2.3 介面軟體設計
由狀態機輸出波形圖可以看出,有一種很簡單自然的介面設計方法,就是將狀態輸出引腳接到單片機的外部中斷引腳上,使其在每個波形的上下邊沿都產生中斷,再在中斷處理程序中,檢測另一對應波形的電平高低,就可以判斷移動方向。比如在XA的上升沿時,若XB是低電平就是左移,若XB是高電平就是右移。這種方法需要單片機提供足夠多的外部中斷。若同時檢測X向與Y向運動,且單片機1個引腳不能同時提供上升沿和下降沿中斷的情況下,就需要佔用8個中斷、8條引腳;而目前許多單片機僅提供2個外部中斷引腳,這種要求顯然較為苛刻。
另一種方式就是降低精度要求,僅在XA與YA的上升沿進行檢測,此時僅需要2個外部中斷引腳。但這種方式在一種極端條件下會出錯,讀者可以自行分析。若只檢測X一個方向,則可以同時檢測上下沿中斷,這樣不會出錯。這種方式犧牲了一點對運動換向和震顫的敏感度;但編程簡單,不失為一種好方法。
本文採用的是查詢方式,這種方式不佔用任何中斷,且能夠不損精度地同時檢測X向與Y向運動。前面已經提過,每個狀態的最小保持時間為133 μs,所以,只要將查詢的周期控制在60μs之下就可以抓住每個狀態的變化。對於AT90S8515,若按晶振為8 MHz計算,則只需將查詢周期匯編指令數控制在450條以下就可以了。實際上,以下給出的C語言程序經過編譯後只有不大於60條匯編指令,完全能夠滿足系統要求。
該方法的基本思想是將狀態機的前一狀態與現在的狀態組合在同一位元組內,如表1所列,尋找其中的規律,簡化程序設計。表1中以PRE開頭的表示前一狀態的對應值。
以X向移動為例(僅看前半位元組),正向移動時對應的值為0b1000、0b1110、0b0111、0b0001,負向移動時對應的值為0b0010、0b1011、0b1101、0b0100。假設狀態不變的情況已經排除,且查詢周期足夠短,不會出現相對周期的組合值。所以只要能將以上兩組值區分開來就可以了,這也正是程序中兩條條件判斷語句的目的。讀者可以對照程序自行驗證。介面程序如下:
while(1){
state=PINA&0xcc;
state_change=state^pre_state;
combo_state=sate | (pre_state>>2);
if(state_change & 0x0c)
{
if((combo_state & 0x06) == 0x06)
{asm("INC R20");goto next;}
if((combo_state | 0x09) == 0x09)
{asm("INC R20");goto next;}
asm("DEC R20");
}
next:
if(state_change & 0xc0)
{
if((temp & 0x60) == 0x60)
{asm("INC R21");goto end;}
if((temp | 0x90) == 0x90)
{asm("INC R21");goto end;}
asm("DEC R21");
}
end:pre_state=state;}
程序已經事先定義了寄存器R20與R21分別為X、Y向的計數器,用來表示X、Y向移動的距離。以上程序段利用內嵌匯編語句優化了程序結構。實際上,還可以對編譯器生成的匯編代碼進行優化,這里就不再詳述了。
結 語
以上軟硬體介面設計雖然是以功能強大的AVR單片機作為例子,但通過仔細分析不難發現,在簡單的應用場合,用普通的51單片機,甚至如AT89C2051在12 MHz晶振頻率下也可以實現其功能。所以整個系統會是相當廉價的。
㈢ 用MFC怎麼做串口測試程序,我要詳細步聚!!!!!!!!
添加一個mscomm 控制項裡面有,然後設置它的波特率,波特率和下位機的波特率要一致。然後就用
Write和Read方法讀寫數據就行了。
推薦關於MSCOMM控制項的一些說明
VB5.0/6.的MSComm通信控制項提供了一系列標准通信命令的介面,它允許建立串口連接,可以連接到其他通信設備(如Modem).
還可以發送命令、進行數據交換以及監視和響應在通信過程中可能發生的各種錯誤和事件,從而可以用它創建全雙工 、事件驅
動的、高效實用的通信程序。但在實際通信軟體設計過程中,MSComm控制項並非像想像中那樣完美和容易控制.特別是在中文Wln
95/98下通信時更會出現問題。下面就從基礎開始介紹,然後逐步討淪MSComm控制項在編程中出現的問題以及編程技巧。
一、用MSComm控制項通信
1.串口通信基礎知識
一般悅來,計算機都有一個或多個串列埠,它們依次為com1、Com2、…,這些串口還提供了外部設備與pC進行數據傳輸和
皿信的通道。這些串口在CPU和外設之間充當解釋器的角色。當字元數據從CPU發送給外設時,這些字元數據將被轉換成串列比特
流數據;當接收數據時,比特流數據被轉換為字元數據傳遞給CPU,再進一步說,在操作系統方面,Windows用通信驅動程序
(COMM.DRV)調用API函數發送和接收數據,當用通信控制項或聲明調用API函數時,它門由COMM. DRV解釋並傳遞給設備驅動程序,
作為一個vB程序員,要編寫通信程序.只需知道通信控制項提供給Windows通信AP1函數的介面即可.換句話說,只需設定和監視通
信控制項的屬性和事件即可。
2.使用Mscomm控制項
在開始使用MSComm控制項之前。需要先了解其屬性、事件或錯誤
屬性 描述
CommPort 設置或返回通信埠號
Settings 以字元串的形式設置或返回波特率、奇偶校驗、數據位和停止位
PortOpen 設置或返回通信埠的狀態。也可以打開和關閉埠
Input 返回和刪除接收緩沖區中的字元
Output 將字元串寫入發送緩沖區
CommEvent屬性為通信事件或錯誤返回下列值之一。在該控制項的對象庫中也可以找到這些常量。
常量 值 描述
ComEventBreak 1001 收到了斷開信號
ComEventCTSTO 1002 Clear To Send Timeout。在發送字元時,在系統指定的事1件內,CTS(Clear To Send)線是低電平
ComEventDSRTO 1003 Data Set Ready Timeout。在發送字元時,在系統指定的事件內,DSR(Data Set Ready)線是低電平
ComEventFrame 1004 數據幀錯誤。硬體檢測到一個數據幀錯誤
ComEventOverrun 1006 埠溢出。硬體中的字元尚未讀,下一個字元又到達,並且丟失
ComEventCDTO 1007 Carrier Detect Time。在發送字元時,在系統指定的事件內,CD(Carrier Detect)線是低電平。CD
也稱為RLSD(Receive Line Singal Detect,接收線信號檢測)
ComEventRxOver 1008 接收緩沖區溢出。在接收緩沖區中沒有空間
ComEventRxParity 1009 奇偶校驗錯。硬體檢測到奇偶校驗錯誤7
ComEventTxFull 1010 發送緩沖區滿。在對發送字元排隊時,發送緩沖區滿
ComEventDCB 1011 檢取埠DCB(Device Control Blick)時發生了沒有預料到的錯誤
通信事件包含了下面的設置:
常量 值 描述
ComEvSend 1 發送緩沖區中的字元數比Sthreshold值低
ComEvReceive 2 接收到了Rthreshold個字元。持續產生該事件,直到使用了Input屬性刪除了接收緩沖區中的數據
ComEvCTS 3 CTS(Clear To Send)線改變
ComEvDSR 4 DSR(Data Set Ready)線改變。當DSR從1到0改變時,該事件發生
ComEvCD 5 CD(Carrier Detect)線改變ComEvRing6檢測到響鈴信號。一些URAT(Universal AsynchronousReciver-
-Transmitters,通用非同步收發器)不支持該事件
ComEvEOF 7 收到了EOF字元(ASCII字元26)
Error消息(MSComm控制項)下表列出了MSComm控制項可捕獲的錯誤消息:
常量 值 描述
ComInvalidPropertyValue 380 無效的屬性值
ComSetNotSupported 383 屬性只讀
ComGetNotSupported 394 屬性只讀
ComPortOpen 8000 埠打開時該存在無效
8001 超時設置必須比0值大
ComPortInvalid 8002 無效的埠號
8003 屬性只在運行時有效
8004 屬性在運行時是只讀的
ComPortAleadyOpen 8005 埠已經打開
8006 設備標識符無效或不支持
8007 不支持設備的波特率
8008 指定的位元組大小無效
8009 預設參數錯誤
8010 硬體不可用(被其他設備鎖住)
8011 函數不能分配隊列
ComNoOpen 8012 設備沒有打開
8013 設備已經打開
8014 不能使用通信通知
ComSetCommStateFailed 8015 不能設置通信狀態
8016 不能設置通信事件屏蔽
ComPortNotOpen 8018 該存在只在埠打開是有效
8019 設備忙
ComReadError 8020 通信設備讀錯誤
ComDCBError 8021 檢取埠設備控制塊時出現內部錯誤
搞清楚以上基本屬性後,就可以開始編寫通信許程序了。在VB5.0/6.0中新建一個工程文件。添加Microsoft Comm Control 5.0組
件,在簡體Form1中加入Command命令按鈕並取名為CmdTest,MSComm控制項取名為MSComm1,加入如下程序代碼。
Private Sub cmdTestClick ( ) '打開串口
MSComml.CommPort =2 '設定Com2
If MSComml.PortOpen = False Then
MSComm1.Settings = "9600,n,8,1" '9600波特率,無校驗,8位數據位,1位停止位
MSComm1.PortOpen = True '打開串口
End if
MSComm1.OutBufferCount = 0 '清空發送緩沖區
MSComm1.InBufferCount = 0 '滑空接收緩沖區
'發送字元數據時注意必須用回車符(vbcr)結束
MSComm1.Output="This is a qood book ! " &vbCr
'潑打電話號碼或發送AT命令
MSComm1.Output = "ATDT 05778191898 , & vbCr
'發送字元數組數據時注意ByteArray必須事先定義賦值
Dim ByteArray as byte( )
'定義動態數組
ReDim ByteArray(1)
'重定義數組大小
ByteArray ( 0 ) =0
ByteArray ( 1 ) = 1
MSComm1.Output = ByteArray
End Sub
private Sub MScommEvent( )
Select Case MSComm1.CommEvent
Case comEvReceive
Dim Buffer As Variant
MSComm1.InputLen = 0
'接收二進制數據
MSComm1.InputMode= ComInputModeBinary
Buffer=MSComm1.Input
'接收字元數據
MSComm1.InputMode=comInputModeText
Buffer = MSComml.Input
Case else
End Select
End sub
( 程序1)
二、中文Win 95/98下的通信問題與解決方法
1.接收的數據少於發送的數據
如果通過MSComm控制項一次性傳送較多的二進制數據,那麼,很可能收到的數據不足。例如在設置為24oobps傳輸率的情況下,
一次性可以傳輸2048個字元數據 那麼在大多數情況下。一次只能收到1200個字元左右,這址出為新版的MSComm32.OCX中存在一
個影響傳輸二進制數據的臭蟲(bug).注意這不是特性。
32位Windows API函數(以下簡稱API)使用了幾個用COMMTIMEOUTS結構表示的限時變數,WriteTotalTimeOutConstant 即是其
中的一個,它被Windows內部設定為5000(即5秒),這個常量決定了在通信驅動程序停止傳輸之前花費在發送緩沖區中數據的時間
的長短,5秒鍾意味著通信速度為1200bps情況下僅能發送600個字元,24oobps情況下僅能發送1200個左右的字元。事實上,在一個
緩沖區內一次性發送更多的數據是非常可能的。這個bug同樣也能引發問題,甚至在高速串口門通信情況下,即使系統在使用流控
制,無論叢軟體流(Xon/XofI)還是硬體流(CTS/RTS)。假如數據在發送緩沖區中時,流控制停止了傳輸,如果停止時間超過5
秒鍾.則數據就會丟失。在某些環境下,5秒鍾可能相當短.不過也不必擔心, VB 5.0/6.0版本的MSComm控制項有一個新增的重要的
屬性稱為CommID, CommID指的是當串口被打開時,被API所調用的串口句柄或稱標志,這也意味著能利用API介面函數去修改這個
常量。每次串口關閉後,Windows會自動將之恢復為5000,所以,每次打開串口後需要重斬設定以下API聲明,其代碼見下程序。
Type COMMTIMEOUTS
ReadIntervalTimeout As Long
ReadTotalTimeoutMultiplier As Long
ReadTotalTimeoutConstant As Long
WriteTotalTimeoutMultiplier As Long
WriteTotalTimeoutConstant As Long
End Type
Declare Function SetCommTimeouts Lib "Kernel32"
(BYVal hFile As Long, lpComm TimeoutsAs COMMTIMEOUTS) As Long
Declare Function GetCommTimeouts Lib "Kernel32"
(ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Dim timeouts As COMMEOUTS
Dim Ret As Long
If Comm1.PortOpen = False Then
Comm1.PortOpen = True
End if
Ret=GetCommTimeouts ( Comm1.CommID , timeouts )
'Set some default timeouts
timeOuts.ReadIntervalTimeout = 1
timeouts.ReadTotalTimeoutMultiplier =1
timeouts.ReadTotalTimeoutConstant =1
timeouts.WriteTotalTimeoutMultiplier =1
timeouts.WriteTotalTimeoutConstant=
( Comm1.OutBufferSize\Val(Comm1.Settings))*10000+1000
Ret=SetCommTimeouts( Comm1.CommID , timeouts )
( 程序2)
2.如何發送大於128的字元數據
在通信程序中,以單字元方式逐個發送數據時,每一個數據范圍 0-255(即十六進制的00-FF)。在單字元版本的英文Win95或
DOS版的BASIC程序中,只需要將相應的數據轉換成相應的字元發送到通信埠即可。但在中文Win95/98下卻行不通,假設在中文
Win95/98下運行以下程序:
Dim i
For i=0 to 255
MSComm1.Output=chr(i)
Next i
希望在接收端得到預期的0-255之間的數據,結果卻是:前129個數據接收正確,為0-128,後面127個數據為126個0和一個255,
造成這種給果的原因在於中文Windows使用的是雙位元組字元集(DBCS)系統。DBCS系統使用0-128之間的數字表示ASCII字元,大於
128的數字僅作為前導字元,它只是顯示是一個非拉丁語系的字元,而並不代表實際意義。上述程序在調用CHR()函數時用到了
DBCS字元集,岡此產生了此類錯誤。那麼,如何發送人於128的數據呢?答案是使用字元數組,將以上程序改為:
Dim cc(255) As Byte
For i = 0 To 255
cc(i) = i
Next i
MSComm1.Output = cc
Do
DoEvents
Loop Until MSComm1.OutBufferCount = 0
'接收過程 MSComm1_OnComm()
Select Case MSComm1.CommEvent
Case comEvReceive
Dim Buffer As Variant, b1,i
MSComm1.InputMode=comInputModeBinery
MSComm1.InputLen = 0
Buffer = MSComm1.Input
For i=LBound (Buffer) To UBound (Buffer )
Debug.Print Buffer ( i ) ;
Next i
Case . . . . .
3.如何發送0字元(00H,NULL)
在VisuaI C++中使用串口控制項發送0字元有些麻煩,但在VB5.0/6.0中只要注意以下兩點即可:
(1)設置MSComm控制項的屬性 NullDiscard=False;。
(2)使用二進制接收,即用 MSComm1.InputMode=ComInputModeBinary便可以解決問題;
4.如何發送遞中文字元串(DBcS字元)
VB5.0/6.0的各種參考書上均指明MSComm通信控制項不能發送或接收雙位元組字元集系統DBCS)的二進制數據,這對於我國及亞洲一些
使用DBCS字元集的國家不能不說是一大人遺憾。但是我在實踐中發現,用MSComm控制項也可以發送中文字元,具體方法有以下兩種:
(1)直接發送
直接發送即把中文字元等同於英文字元。如:MSComm1.Intput= " 這是一行中文數據!" ,但這種方法發送的中文數據不能太
長,發送緩沖區和接收緩沖區的大小需設定為中文字元的兩倍以上,而且發送與接收系統所處的操作系統版本最好要一致,否則會
出現接收或發送緩沖區溢出之類的錯誤。這種方法時用於一般要求不太高的場合。
(2)間接發送
在發送端將漢字或字元轉換為機器內碼或區位碼數據數組,然後將詠轉換後的數據發送到串口,在接收端接收到數據後,按照
相反的順序得到的數據轉換為相應的漢字或字元,在轉換過程中.要用到位運算,如取得漢字的內碼後需要將高位元組和低位元組分開,
而VB5.0/6.0中並沒有提供此類函數,以下是求整數高、低位元組的函數。
Public Function HiByte(a As Integer )
Dim b
b= a And &HFF00
b = b / 256
If b<0 Then b = b + 256
HiByte = b
End Function
Public Function LowByte(a As Integ`er)
Dim b
b = a And &HFF
LowByte = b
End Function
5.如何用單機進行通信測試
通常在寫好了通信程序後需要兩台PC或一台Pc、一台單片機.將通信口連接後進行測試,但很多時侯因條件限制僅有單台PC機,
測試項目很簡單,那麼能否測試呢?當然可以,而且方法也很簡單。對於九針的串口,找一個廢棄的串口滑鼠,剝外滑鼠線,將連
接2、3針的線對接即可;對於25針的串口,找一枚曲別針(最好有塑料外套的)將它扯直,剝削去兩頭的塑料後在兩頭各彎一個圓
圈,中間對忻後直接套接在串口的2、3針上即可。如果但心不夠安全,則可以將5針按地。
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
關於mscomm的用法,提高篇......[mgwmj]?
MSCOMM控制項是個好東西,如果您能夠充分了解他,他會為您衷心的效勞。
大致看了一下下午有關討論MSCOMM的話題,覺得有必要說說我的心得,我一般只做硬體,沒有系統的學過軟體,只是業余時間
學學用用,多少掌握了一點,也在此拿出來玩玩,不知有錯沒有,我可是以為我已經做的很好了^_^
這是一個VB通用串口事件驅動接收程序。一次性接收一個數據包,數據包可以為任意位元組,保證不會丟失一個數據!
Private Sub MSComm_OnComm()
Dim S() As Byte
Dim SS(1024) As Byte
Static N As Long
Static T As Variant
If (MSComm.CommEvent = comEvReceive) Then
S = MSComm.Input '只要有數據就收進來,哪怕只是一個
If (Timer - T > 0.01) Then '間隔10MS以上就認為是一個新的包
text1="" 'text1用於搜集和顯示接收(HEX格式)
N = 0
End If
T = Timer
For i = 0 To UBound(S) '一個數據包可能產生若干個oncomm事件
Text1.Text = Text1.Text & Right("0" & Hex(S(i)) & "H", 3) + " "
SS(N+i)=S(i) '接收數據包緩存於SS()
N=N+UBound(S)
Next i
End If
End Sub
㈣ 8015單片機儲存器結構是什麼
這個簡單,大家都是知道的。
㈤ 急!請教RS485串口通訊的問題
你用vb還是vc?
看OnComm事件應該是vb吧。
(參照出處http://www.gjwtech.com/serialcomm.htm):
MSComm控制項使用詳解
摘要:本文詳細介紹了MSComm控制項在串口編程中使用。
目 次
MSComm控制項兩種處理通訊的方式
CommPort屬性
RThreshold 屬性
CTSHolding 屬性
SThreshold 屬性
CDHolding 屬性
DSRHolding 屬性
Settings 屬性
InputLen 屬性
EOFEnable 屬性
Handshake 常數
OnComm 常數
InputMode 常數
錯誤消息
MSComm 控制項通過串列埠傳輸和接收數據,為應用程序提供串列通訊功能。MSComm控制項在串口編程時非常方便,程序員不必去花時間去了解較為復雜的API函數,而且在VC、VB、Delphi等語言中均可使用。 Microsoft Communications Control(以下簡稱MSComm)是Microsoft公司提供的簡化Windows下串列通信編程的ActiveX控制項,它為應用程序提供了通過串列介面收發數據的簡便方法。具體的來說,它提供了兩種處理通信問題的方法:一是事件驅動(Event-driven)方法,一是查詢法。
1.MSComm控制項兩種處理通訊的方式
MSComm控制項提供下列兩種處理通訊的方式:事件驅動方式和查詢方式。
1.1 事件驅動方式
事件驅動通訊是處理串列埠交互作用的一種非常有效的方法。在許多情況下,在事件發生時需要得到通知,例如,在串口接收緩沖區中有字元,或者 Carrier Detect (CD) 或 Request To Send (RTS) 線上一個字元到達或一個變化發生時。在這些情況下,可以利用 MSComm 控制項的 OnComm 事件捕獲並處理這些通訊事件。OnComm 事件還可以檢查和處理通訊錯誤。所有通訊事件和通訊錯誤的列表,參閱 CommEvent 屬性。在編程過程中,就可以在OnComm事件處理函數中加入自己的處理代碼。這種方法的優點是程序響應及時,可靠性高。每個MSComm 控制項對應著一個串列埠。如果應用程序需要訪問多個串列埠,必須使用多個 MSComm 控制項。
1.2 查詢方式
查詢方式實質上還是事件驅動,但在有些情況下,這種方式顯得更為便捷。在程序的每個關鍵功能之後,可以通過檢查 CommEvent 屬性的值來查詢事件和錯誤。如果應用程序較小,並且是自保持的,這種方法可能是更可取的。例如,如果寫一個簡單的電話撥號程序,則沒有必要對每接收一個字元都產生事件,因為唯一等待接收的字元是數據機的「確定」響應。
2.MSComm 控制項的常用屬性
MSComm 控制項有很多重要的屬性,但首先必須熟悉幾個屬性。
CommPort 設置並返回通訊埠號。
Settings 以字元串的形式設置並返回波特率、奇偶校驗、數據位、停止位。
PortOpen 設置並返回通訊埠的狀態。也可以打開和關閉埠。
Input 從接收緩沖區返回和刪除字元。
Output 向傳輸緩沖區寫一個字元串。
下面分別描述:
CommPort屬性 設置並返回通訊埠號。
語法 object.CommPort[value ] (value 一整型值,說明埠號。)
說明 在設計時,value 可以設置成從 1 到 16 的任何數(預設值為 1)。但是如果用 PortOpen 屬性打開一個並不存在的埠時,MSComm 控制項會產生錯誤 68(設備無效)。
注意:必須在打開埠之前設置 CommPort 屬性。
RThreshold 屬性:在 MSComm 控制項設置 CommEvent 屬性為 comEvReceive 並產生 OnComm 之前,設置並返回的要接收的字元數。
語法 object.Rthreshold [ = value ](value 整型表達式,說明在產生 OnComm 事件之前要接收的字元數。 )
說明 當接收字元後,若 Rthreshold 屬性設置為 0(預設值)則不產生 OnComm 事件。例如,設置 Rthreshold 為 1,接收緩沖區收到每一個字元都會使 MSComm 控制項產生 OnComm 事件。
CTSHolding 屬性:確定是否可通過查詢 Clear To Send (CTS) 線的狀態發送數據。Clear To Send 是數據機發送到相聯計算機的信號,指示傳輸可以進行。該屬性在設計時無效,在運行時為只讀。
語法: object.CTSHolding(Boolean)
Mscomm 控制項的 CTSHolding 屬性設置值:
True Clear To Send 線為高電平。
False Clear To Send 線為低電平。
說明:如果 Clear To Send 線為低電平 (CTSHolding = False) 並且超時時,MSComm 控制項設置 CommEvent 屬性為 comEventCTSTO (Clear To Send Timeout) 並產生 OnComm 事件。
Clear To Send 線用於 RTS/CTS (Request To Send/Clear To Send) 硬體握手。如果需要確定 Clear To Send 線的狀態,CTSHolding 屬性給出一種手工查詢的方法。
詳細信息 有關握手協議,請參閱 Handshaking 屬性。
SThreshold 屬性: MSComm 控制項設置 CommEvent 屬性為 comEvSend 並產生 OnComm 事件之前,設置並返回傳輸緩沖區中允許的最小字元數。
語法 object.SThreshold [ = value ]
value 整形表達式,代表在 OnComm 事件產生之前在傳輸緩沖區中的最小字元數。
說明:若設置 Sthreshold 屬性為 0(預設值),數據傳輸事件不會產生 OnComm 事件。若設置 Sthreshold 屬性為 1,當傳輸緩沖區完全空時,MSComm 控制項產生 OnComm 事件。如果在傳輸緩沖區中的字元數小於 value,CommEvent 屬性設置為 comEvSend,並產生 OnComm 事件。comEvSend 事件僅當字元數與 Sthreshold 交叉時被激活一次。例如,如果 Sthreshold 等於 5,僅當在輸出隊列中字元數從 5 降到 4 時,comEvSend 才發生。如果在輸出隊列中從沒有比 Sthreshold 多的字元,comEvSend 事件將絕不會發生。
Handshake 常數
常數 值 描述
comNone 0 無握手。
comXonXoff 1 XOn/Xoff 握手。
comRTS 2 Request-to-send/clear-to-send 握手。
comRTSXOnXOff 3 Request-to-send 和 clear-to-send 握手皆可。
OnComm 常數
常數 值 描述
comEvSend 1 發送事件。
comEvReceive 2 接收事件。
comEvCTS 3 clear-to-send 線變化。
comEvDSR 4 data-set ready 線變化。
comEvCD 5 carrier detect 線變化。
comEvRing 6 振鈴檢測。
comEvEOF 7 文件結束。
Error 常數
常數 值 描述
comEventBreak 1001 接收到中斷信號
comEventCTSTO 1002 Clear-to-send 超時
comEventDSRTO 1003 Data-set ready 超時
comEventFrame 1004 幀錯誤
comEventOverrun 1006 埠超速
comEventCDTO 1007 Carrier detect 超時
comEventRxOver 1008 接收緩沖區溢出
comEventRxParity 1009 Parity 錯誤
comEventTxFull 1010 傳輸緩沖區滿
comEventDCB 1011 檢索埠 設備控制塊 (DCB) 時的意外錯誤
InputMode 常數
常數 值 描述
comInputModeText 0 (預設)通過 Input 屬性以文本方式取回數據。
comInputModeBinary 1 通過 Input 屬性以二進制方式檢取回數據。
CDHolding 屬性:通過查詢 Carrier Detect (CD) 線的狀態確定當前是否有傳輸。Carrier Detect 是從數據機發送到相聯計算機的一個信號,指示數據機正在聯機。該屬性在設計時無效,在運行時為只讀。
語法 object.CDHolding
設置值:CDHolding 屬性的設置值為:
設置 描述
True Carrier Detect 線為高電平
False Carrier Detect 線為低電平
說明:注意當 Carrier Detect 線為高電平 (CDHolding = True) 且超時時,MSComm 控制項設置CommEvent 屬性為 comEventCDTO(Carrier Detect 超時錯誤),並產生 OnComm 事件。
注意 在主機應用程序中捕獲一個丟失的傳輸是特別重要的,例如一個公告板,因為呼叫者可以隨時掛起(放棄傳輸)。
Carrier Detect 也被稱為 Receive Line Signal Detect (RLSD)。
數據類型 Boolean
DSRHolding 屬性:確定 Data Set Ready (DSR) 線的狀態。Data Set Ready 信號由數據機發送到相連計算機,指示作好操作準備。該屬性在設計時無效,在運行時為只讀。
語法:object.DSRHolding
object 所在處表示對象表達式,其值是「應用於」列表中的對象。
DSRHolding 屬性返回以下值:
值 描述
True Data Set Ready 線高
False Data Set Ready 線低
說明:當 Data Set Ready 線為高電平 (DSRHolding = True) 且超時時,MSComm 控制項設置 CommEvent 屬性為 comEventDSRTO(數據准備超時)並產生 OnComm 事件。
當為 Data Terminal Equipment (DTE) 機器寫 Data Set Ready/Data Terminal Ready 握手常式時該屬性是十分有用的。
數據類型:Boolean
Settings 屬性: 設置並返回波特率、奇偶校驗、數據位、停止位參數。
語法: object.Settings[ = value]
說明:當埠打開時,如果 value 非法,則 MSComm 控制項產生錯誤 380(非法屬性值)。
Value 由四個設置值組成,有如下的格式:
"BBBB,P,D,S"
BBBB 為波特率,P 為奇偶校驗,D 為數據位數,S 為停止位數。value 的預設值是:
"9600,N,8,1"
InputLen 屬性:設置並返回 Input 屬性從接收緩沖區讀取的字元數。
語法 object.InputLen [ = value]
InputLen 屬性語法包括下列部分:
value 整型表達式,說明 Input 屬性從接收緩沖區中讀取的字元數。
說明:InputLen 屬性的預設值是 0。設置 InputLen 為 0 時,使用 Input 將使 MSComm 控制項讀取接收緩沖區中全部的內容。
若接收緩沖區中 InputLen 字元無效,Input 屬性返回一個零長度字元串 ("")。在使用 Input 前,用戶可以選擇檢查 InBufferCount 屬性來確定緩沖區中是否已有需要數目的字元。該屬性在從輸出格式為定長數據的機器讀取數據時非常有用。
EOFEnable 屬性:確定在輸入過程中 MSComm 控制項是否尋找文件結尾 (EOF) 字元。如果找到 EOF 字元,將停止輸入並激活 OnComm 事件,此時 CommEvent 屬性設置為 comEvEOF,
語法:object.EOFEnable [ = value ]
EOFEnable 屬性語法包括下列部分:
value 布爾表達式,確定當找到 EOF 字元時,OnComm 事件是否被激活,如「設置值」中所描述。
value 的設置值:
True 當 EOF 字元找到時 OnComm 事件被激活。
False (預設)當 EOF 字元找到時 OnComm 事件不被激活。
說明:當 EOFEnable 屬性設置為 False,OnComm 控制項將不在輸入流中尋找 EOF 字元。
錯誤消息(MS Comm 控制項)
下表列出 MSComm 控制項可以捕獲的錯誤:
值 描述
380 無效屬性值 comInvalidPropertyValue
383 屬性為只讀 comSetNotSupported
394 屬性為只讀 comGetNotSupported
8000 埠打開時操作不合法 comPortOpen
8001 超時值必須大於 0
8002 無效埠號 comPortInvalid
8003 屬性只在運行時有效
8004 屬性在運行時為只讀
8005 埠已經打開 comPortAlreadyOpen
8006 設備標識符無效或不支持該標識符
8007 不支持設備的波特率
8008 指定的位元組大小無效
8009 預設參數錯誤
8010 硬體不可用(被其它設備鎖定)
8011 函數不能分配隊列
8012 設備沒有打開 comNoOpen
8013 設備已經打開
8014 不能使用 comm 通知
8015 不能設置 comm 狀態 comSetCommStateFailed
8016 不能設置 comm 事件屏蔽
8018 僅當埠打開時操作才有效 comPortNotOpen
8019 設備忙
8020 讀 comm 設備錯誤 comReadError
8021 為該埠檢索設備控制塊時的內部錯誤 comDCBError
///-----------------------------------------------------
串口數據接收方式
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
Deson
1999-10-16
--------------------------------------------------------------------------------
2、Q:各位大俠,在下被兩個問題困擾多時,實在無法找到答案,請各位多多指教。
1、在用MSCOMM控制項設計通訊程序時,我始終無法將ASC碼大於127的值發送出去,查閱了VB論壇以前的文章,按部就班也不行,部分 VB 程序如下,請指教:
Private Sub OkBtn_Click()
Dim Data() as byte
Dim Temp as variant
redim data(10)
For i = 0 to 10
Data(i) = int(rnd()*256)
next
temp = data
mscomm.output = temp
end Sub
A:接收方式使用了文本方式,用二進制方式即可。
㈥ 可編程式控制制器原理作業題
1.PLC是在什麼控制系統基礎上發展起來的( A).
(A) 繼電控制系統 (B) 單片機 (C)工業電腦(D)機器人
2.常見的接近開關按感應的物體來分為( A )。
( A)電感式/電容式 (B) PNP/NPN (C)常開/常閉 ( D)定時器/計數器
3.工業中控制電壓一般是多少伏(A)
(A)24V (B)36V (C)110V (D)220V
4.三菱FX系列PLC普通輸入點,輸入響應時間大約是多少ms?(B )
(A) 100 ms (B)10ms (C)15 ms (D)30 ms
5.對於小的PLC系統,如( C )點以內的系統.一般不需要擴展.
(A)60 (B)70 (C)80 (D)90
6.PLC的輸入電流是由內部的DC24V電源供給的,為了確實切斷,必須取( A )以下電流。
(A)1.5mA (B)2.5mA (C)3.5mA (D)4.5mA
7.FX2N的輸出繼電器最多可達( C )點
(A)64 (B)128 (C)256 (D)512
8.一般要求模擬放大電路的輸入電阻(A)
(A)大些好,輸出電阻小些好(B)小些好,輸出電阻大些好
(C)和輸出電阻都大些好(D)和輸出電阻都小些好
9.FX2N PLC軟元件中有( C )點狀態可構成狀態轉移圖。
(A)300 (B)600 (C)900 (D)1200
10.對於所有的FX CPU ,表示1 秒時鍾脈沖的是(B )
(A)M8011 (B)M8013 (C)M8014 9D)M8015
11.OUT指令對於( A )是不能使用的
(A)輸入繼電器 (B)輸出繼電器 (C)輔助繼電器 (D)狀態繼電器
12.串聯電路塊並聯連接時,分支的結束用( C )指令
(A)AND/ADI (B)OR/ORI (C)ORB (D)ANB
13.使用( B )指令,元件Y、M僅在驅動斷開後的一個掃描周期內動作
(A)PLS (B)PLF (C)MPS (D)MRD
14.存儲器是存放程序的倉庫,採用電擦除的存儲器使用非常方便,它是( D )
(A)RAM (B)EPROM (C)EPRAM (D)EP2ROM
15.狀態的順序可以自由選擇,但在一系列的STL指令後,必須寫入(C )指令
(A)MC (B)MRC (C)RET (D)END
16. ( B )是PLC每執行一遍從輸入到輸出所需的時間.
(A)8 (B)掃描周期 (C)設定時間 (D)32
17.對於STL指令後的狀態S,OUT指令與( B )指令具有相同的功能
(A)OFF (B)SET (C)END (D)NOP
18.助記符後附的( B )表示脈沖執行
(A)(D)符號(B)(P)符號 (C)(V)符號 (D)(Z)符號
㈦ 三菱Q系列PLC中各個特殊寄存器的意義
1、通用數掘寄存器:
(1)、可用於傳送和暫存數據,也可參與算術邏輯運算,並保存運算結果。除此之外,它們還各自具有一些特殊功能。
(2)、匯編語言程序員必須熟悉每個寄存器的一般用途和特殊用途,只有這樣,才能在程序中做到正確、合理地使用它們。
2、斷電保持數據查存器:可以利用外部設備的參數設定改變通用數據查存器與有斷電保持功能數據寄存器的分配, D512-D7999的斷電保持功能不能用軟體改變,但可用指令清除它們的內容。
3、特殊數據寄存器:特殊數據查存器的作用是用來監控PLC的運行狀態,如掃描時間、電池電壓等,具體可參見用戶手冊。
4、變址寄存器:實際上是一種特殊用途的數據高存器,其作用相當於微機中的變址寄存器,用於改變元件的編號(變址) 。
1、三菱(Mitsubish)不是一個單獨的公司,是由眾多的獨立公司組成的團體,其中大多數公司使用「三菱」這一名稱,但不會簡單地自稱「三菱」。
2、三菱Kinyokai(也被稱為Friday Club,直譯為星期五俱樂部)的核心成員有28家,三菱的成員公司約有500家,名稱中有「三菱」的公司約有400家,另有數以百計的三菱公司名稱中沒有「三菱」。
3、這些公司的商業活動是獨立進行的,甚至在很多領域彼此競爭,
4、這些公司起源於1870年岩崎彌太郎(Yataro Iwasaki)經營的一家船運公司,隨後公司開始涉足礦業、造船、銀行和保險,為日後三菱公司的成長與發展奠定了堅實的基礎。
5、值得注意的是,三菱鉛筆株式會社(Mitsubishi Pencil)不是三菱的成員公司。