上位機快速開發教程
?。?)準備工作
一臺裝有VS2010的計算機,用于測試的虛擬串口軟件。同時你必須具有VB基礎知識,這個VB上位機開發是入門級的,僅將VB.NET通信基礎方法稍作介紹。
?。?)串口通信常識
在串口通信中,通過編寫單片機程序知道,我們應對如下參數進行設置:波特率、數據位和停止位、奇偶校驗位。如果自己編寫上位機的時候,我們考慮的不能僅僅是這些了,下面介紹上位機開發過程中需要特別注意的知識點。
MSComm控件提供了兩種處理通信的方式:一種為事件驅動方式,該方式相當于一般程序設計中的中斷方式。當串口發生事件或錯誤時,MSComm控件會產生OnComm事件,用戶程序可以捕獲該事件進行相應處理。
常用屬性和方法
利用MSComm控件實現計算機通信的關鍵是理解并正確設置MSComm控件眾多屬性和方法。以下是MSComm控件的常用屬性和方法:
●Commport:設置或返回串口號。其值從COM1到COM16。
●Settings:以字符串的形式設置或返回串口通信參數。
●Portopen:設置或返回串口狀態。
●InputMode:設置或返回接收數據的類型。有文本和二進制兩種類型。
●Inputlen:設置或返回一次從接收緩沖區中讀取字節數。
●InBufferSize:設置或返回接收緩沖區的大小,缺省值為1024字節。
●InBufferCount:設置或返回接收緩沖區中等待計算機接收的字符數。
●Input:從接收緩沖區中讀取數據并清空該緩沖區,該屬性設計時無效,運行時只讀。
●OutBufferSize:設置或返回發送緩沖區的大小,缺省值為512字節。
●OutBufferCount:設置或返回發送緩沖區中等待計算機發送的字符數。
●Output:向發送緩沖區發送數據,該屬性設計時無效,運行時只讀。
●Rthreshold:該屬性為一閥值。當接收緩沖區中字符數達到該值時,MSComm控件設置Commevent屬性為ComEvReceive,并產生OnComm事件。用戶可在OnComm事件處理程序中進行相應處理。若Rthreshold屬性設置為0,則不產生OnComm事件。例如用戶希望接收緩沖區中達到一個字符就接收一個字符,可將Rthreshold設置為1。這樣接收緩沖區中接收到一個字符,就產生一次OnComm事件。
●Sthreshold:該屬性亦為一閥值。當發送緩沖區中字符數小于該值時,MSComm控件設置Commevent屬性為ComEvSend,并產生OnComm事件。若Sthreshold屬性設置為0,則不產生OnComm事件。要特別注意的是僅當發送緩沖區中字符數小于該值的瞬間才產生OnComm事件,其后就不再產生OnComm事件。例如Sthreshold設置為3,僅當發送緩沖區中字符數從3降為2時,MSComm控件設置Commevent屬性為ComEvSend,同時產生OnComm事件,如發送緩沖區中字符始終為2,則不會再產生OnComm事件。這就避免了發送緩沖區中數據未發送完就反復發生OnComm事件。
●CommEvent:這是一個非常重要的屬性。該屬性設計時無效,運行時只讀。一旦串口發生通信事件或產生錯誤,依據產生的事件和錯誤,MSComm控件為CommEvent屬性賦不同的代碼,同時產生OnComm事件。用戶程序就可在OnComm事件處理程序中針對不同的代碼,進行相應的處理。
?。?)開發步驟(僅供參考)
1. 運行VS2010,新建一個Visual Basic的Windows窗體應用程序項目。將窗體的StartPosition屬性改為CenterScreen,運行程序時,窗體在屏幕中央顯示。
2. 由于默認情況下,通信所需的“Microsoft Communications Control,version 6.0”組件不在工具箱里面,所以我們需要手動添加。單擊左側的工具箱,并在控件欄單擊鼠標右鍵,在彈出的菜單中選中“選擇項”,在彈出的對話框中單擊“COM組件”并選中“MicrosoftCommunications Control,version 6.0”,單擊確定即可完成添加。
此時移動鼠標到窗體上時,鼠標箭頭就會變成電話的形狀,在窗體任意位置單擊放置該控件。
3. 單擊工具箱,在窗體上添加5個Label,并在屬性里將Text屬性依次改為:串口號、波特率、校驗、數據位、停止位。再向窗體上添加5個ComboBox,從上到下依次排列。
?
? ? ? ?4. 向窗體添加一個OvalShape和一個Button。將OvalShape的size屬性改為“24,24”,FillStyle改為Solid。
5. 向窗體添加一個CheckBox、一個按鈕Button和一個TextBox,將CheckBox的Text屬性改為“十六進制發送”將這個按鈕的text屬性改為“發送”。
6. 向窗體添加一個Label和一個TextBox。更改Label的Text屬性為“接收區”。
? ? ? ?7. 向窗體添加一個CheckBox,將其Text屬性改為“十六進制顯示”
下面將要對部分控件進行設置,這樣可以減少代碼的長度 將波特率一欄ComboBox的Item屬性中添加如下內容:
將校驗一欄ComboBox的Item屬性中添加如下內容
將數據位一欄ComboBox的Item屬性中添加如下內容
將波特率一欄ComboBox的Item屬性中添加如下內容
四、源代碼
Public Class Form1 Dim cpSetting As String
Dim com_last_num As Integer = 0 ‘定義一個全局變量,作用為記錄上一個串口號 Sub GetSerialPortNames() ’搜索計算機中所有可用串口函數 On Error GoTo eRRHND ‘錯誤處理 ’搜索計算機中可用串口
For Each sp As String In My.Computer.Ports.SerialPortNames ComboBox1.Items.Add(sp) Next
ComboBox1.Sorted = True
ComboBox1.SelectedIndex = 0 ‘選擇搜索到的第一個串口名稱 Exit Sub
eRRHND: ’表示未搜到串口 MsgBox(“Oh, NO!”) End Sub
‘檢測串口是否可用函數
Private Function Test_COM(ByVal com_num As Integer) As Boolean
If com_num 《》 com_last_num Or Button1.Text = “打開端口” Then ’如果選擇的端口跟上次一樣就不檢測了
On Error GoTo Comm_Error
AxMSComm1.CommPort = com_num ‘將新串口號賦給ComPort
AxMSComm1.PortOpen = True ’打開串口
AxMSComm1.PortOpen = False ‘關閉串口
Test_COM = True ’串口可用則返回
Exit Function
Comm_Error: ‘根據錯誤號作出相應處理 If Err.Number = 8002 Then
MsgBox(“串口錯誤,請重新選擇串口”, vbOKOnly, “錯誤提示!”) ElseIf Err.Number = 8005 Then MsgBox(“串口已打開!”) Else
MsgBox(“其它錯誤”) End If
Test_COM = False ’如果出錯,則返回0 Exit Function Resume Next End If End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
‘載入窗體初始化
GetSerialPortNames() ’將搜到的串口在下拉菜單中顯示出來
AxMSComm1.InBufferSize = 1024 ‘接收緩沖區大小,此項無法在串口打開時進行設置 AxMSComm1.OutBufferSize = 1024 ’發送緩沖區大小 ComboBox2.Text = “9600” ComboBox3.Text = “無校驗” ComboBox4.Text = “8” ComboBox5.Text = “1” ChangePortProperty()
‘設置接收數據的格式為二進制
AxMSComm1.InputMode = MSCommLib.InputModeConstants.comInputModeBinary AxMSComm1.InputLen = 0 ’設置從緩沖區讀取全部數據 AxMSComm1.RThreshold = 1 ‘設置接收串口OnCommon事件 AxMSComm1.PortOpen = True ’打開串口 If AxMSComm1.PortOpen = True Then
OvalShape1.FillColor = Color.Green ‘OvalShape顏色設為綠色 Button1.Text = “關閉端口” ’按鈕上的文字顯示為關閉端口 Else
OvalShape1.FillColor = Color.Red ‘OvalShape顏色設為紅色 Button1.Text = “打開端口” ’按鈕上的文字顯示為打開端口 End If End Sub
‘打開關閉串口代碼
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ptNum As Integer ’通過串口名稱獲取串口號
If Len(ComboBox1.SelectedItem) 》 4 Then
ptNum = Val(Microsoft.VisualBasic.Strings.Right(ComboBox1.Text, 2)) Else
ptNum = Val(Microsoft.VisualBasic.Strings.Right(ComboBox1.Text, 1)) End If
If AxMSComm1.PortOpen = False Then ‘如果串口是關閉的 If Test_COM(ptNum) = True Then ’如果選擇的串口可用? ‘ ChangePortProperty()
AxMSComm1.PortOpen = True ’則打開該串口
Button1.Text = “關閉端口” ‘按鈕上的文字顯示為關閉端口 OvalShape1.FillColor = Color.Green ’OvalShape顏色設為綠色 End If Else
AxMSComm1.PortOpen = False ‘關閉該串口
OvalShape1.FillColor = Color.Red ’OvalShape顏色設為紅色 Button1.Text = “打開端口” ‘按鈕上的文字顯示為打開端口 End If End Sub
’如下是訪問網站的鏈接的代碼,可以選擇訪問網站的瀏覽器,這里只使用默認的IE瀏覽器 Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked LinkLabel1.LinkVisited = True
System.Diagnostics.Process.Start(“www.baidu.com/p/huzhiqianglz”) End Sub
‘處理發送數據的代碼
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim hexString() As Byte Dim source_Txt As String Dim i As Integer
source_Txt = TextBox1.Text ’將要發送的數據存放到變量source_Txt中
If CheckBox1.CheckState = CheckState.Checked Then ‘如果十六進制發送復選框被勾上 If Len(source_Txt) Mod 2 = 0 And Len(source_Txt) 《》 0 Then ’如果將要發送的數據長度不為或者能被2整除
ReDim hexString(Len(source_Txt) / 2 - 1) ‘重新定義hexString數組 For i = 0 To Len(source_Txt) - 1 Step 2
hexString(i / 2) = Val(“&H” & Mid(source_Txt, i + 1, 2)) ’將hexString轉換成十六進制顯示
Next
AxMSComm1.Output = hexString ‘將轉換的數據發送到串口 Else ’否則提示格式不正確 MsgBox(“格式不正確!”) End If
Else ‘否則輸出字符串
AxMSComm1.Output = TextBox1.Text
End If End Sub
Sub ChangePortProperty() Dim comSetting As String Dim parity As String = “” ‘關閉端口
If AxMSComm1.PortOpen = True Then AxMSComm1.PortOpen = False End If ’獲取串口號
If Len(ComboBox1.SelectedItem) 》 4 Then
AxMSComm1.CommPort = Val(Microsoft.VisualBasic.Strings.Right(ComboBox1.Text, 2)) Else
AxMSComm1.CommPort = Val(Microsoft.VisualBasic.Strings.Right(ComboBox1.Text, 1)) End If ‘設置校驗方式
If ComboBox3.Text = “無校驗” Then parity = “N”
ElseIf ComboBox3.Text = “奇校驗” Then parity = “O”
ElseIf ComboBox3.Text = “偶校驗” Then parity = “E” End If
comSetting = ComboBox2.Text & “,” & parity & “,” & ComboBox4.Text & “,” & ComboBox5.Text
’串口設置格式:9600,N,8,1 AxMSComm1.Settings = comSetting End Sub
‘將十進制轉換為16進制
Private Function Decimal2Hex(ByRef c As String) As String Decimal2Hex = Hex(CInt(c)) If Len(Decimal2Hex) 《 2 Then
Decimal2Hex = “0” & Decimal2Hex End If End Function
’串口號發生改變的處理程序
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged ChangePortProperty()
End Sub
Private ReadStr As String = “”
Private Sub AxMSComm1_OnComm(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles AxMSComm1.OnComm
Dim i As Object
Dim bytData As Object ‘用來從接收緩沖區讀取數據
Select Case AxMSComm1.CommEvent ’
對接收事件進行處理
Case MSCommLib.OnCommConstants.comEvReceive
bytData = AxMSComm1.Input ‘將接收到的數據暫存 For i = 0 To UBound(bytData)
If CheckBox2.CheckState = CheckState.Checked Then
ReadStr = ReadStr & Decimal2Hex(CStr(bytData(i)))
Else
ReadStr = ReadStr & CStr(bytData(i))
End If
Next
TextBox2.Text = ReadStr ’將轉換后的數據在接收區顯示
End Select
End Sub
End Class
五、程序中用到的幾個函數解釋
Microsoft.VisualBasic.Strings.Right(String,Num):將字符串從右邊開始截取字符串String中Num個字符。例如當String的值為“Welcome”,Num值為3,則該函數返回的值為字符串“ome”。另外通過將COM1拆分即可得到1,這是上例中得到得到串口號的方法。
Val(String):將字符串類型轉換為數值型。例如String為字符串“123”,則返回值為數值型123。 Hex(Integer):將整型數轉換為16進制數。如:Integer為13,則返回十六進制的D
其實有些函數看不懂也沒關系,可能我介紹的不是很詳細,有些資料上網查一下也很方便的,這里就不再多羅嗦了。
評論
查看更多