上位機(jī)是指可以直接發(fā)出操控命令的計(jì)算機(jī),一般是PC/host computer/master computer/upper computer,屏幕上顯示各種信號變化(液壓,水位,溫度等)。下位機(jī)是直接控制設(shè)備獲取設(shè)備狀況的計(jì)算機(jī),一般是PLC/單片機(jī)single chip microcomputer/slave computer/lower computer之類的。上位機(jī)發(fā)出的命令首先給下位機(jī),下位機(jī)再根據(jù)此命令解釋成相應(yīng)時(shí)序信號直接控制相應(yīng)設(shè)備。下位機(jī)不時(shí)讀取設(shè)備狀態(tài)數(shù)據(jù)(一般為模擬量),轉(zhuǎn)換成數(shù)字信號反饋給上位機(jī)。簡言之如此,實(shí)際情況千差萬別,但萬變不離其宗:上下位機(jī)都需要編程,都有專門的開發(fā)系統(tǒng)。
上位機(jī)工作原理
兩機(jī)如何通訊,一般取決于下位機(jī),TCP/IP一般是支持的,但是下位機(jī)一般具有更可靠的獨(dú)有通訊協(xié)議,購買下位機(jī)時(shí),會(huì)帶一大堆手冊光盤,告訴你如何使用特有協(xié)議通訊,里面會(huì)舉大量例子,一般對編程人員而言一看也就那么回事,使用一些新的API(API(Application Programming Interface,應(yīng)用程序編程接口)是一些預(yù)先定義的函數(shù),目的是提供應(yīng)用程序與開發(fā)人員基于某軟件或硬件的以訪問一組例程的能力,而又無需訪問源碼,或理解內(nèi)部工作機(jī)制的細(xì)節(jié)罷了,多語言支持功能模塊,一般同時(shí)支持?jǐn)?shù)種高級語言為上位機(jī)編程。
通常上位機(jī)和下位機(jī)通訊可以采用不同的上位機(jī)示例圖片通訊協(xié)議,可以有RS232的串口通訊或者采用RS485串行通訊。當(dāng)用計(jì)算機(jī)和PLC通訊的時(shí)候,不但可以采用傳統(tǒng)的D形式的串行通訊,還可以采用更適合工業(yè)控制的雙線的PROFIBUS-DP通訊。采用封裝好的程序開發(fā)工具就可以實(shí)現(xiàn)PLC和上位機(jī)的通訊,當(dāng)然可以自己編寫驅(qū)動(dòng)類的接口協(xié)議控制上位機(jī)和下位機(jī)的通訊。
通常工控機(jī),工作站,觸摸屏作為上位機(jī),通信控制PLC,單片機(jī)等作為下位機(jī),從而控制相關(guān)設(shè)備元件和驅(qū)動(dòng)裝置。
上位機(jī)開發(fā)的軟件
1、visual studio 2008
Microsoft Visual Studio 2008是面向Windows Vista、Office 2007、Web 2.0的下一代開發(fā)工具,代號“Orcas”,是對Visual Studio 2005的一次及時(shí)、全面的升級。
VS2008引入了250多個(gè)新特性,整合了對象、關(guān)系型數(shù)據(jù)、XML的訪問方式,語言更加簡潔。使用Visual Studio 2008可以高效開發(fā)Windows應(yīng)用程序。設(shè)計(jì)器中可以實(shí)時(shí)反映變更,XAML中智能感知功能可以提高開發(fā)效率。同時(shí)Visual Studio 2008支持項(xiàng)目模板、調(diào)試器和部署程序。Visual Studio 2008可以高效開發(fā)Web應(yīng)用,集成了AJAX 1.0,包含AJAX項(xiàng)目模板,它還可以高效開發(fā)Office應(yīng)用和Mobile應(yīng)用。
2、MFC
是微軟公司提供的一個(gè)類庫(class libraries),以C++類的形式封裝了Windows API,并且包含一個(gè)應(yīng)用程序框架,以減少應(yīng)用程序開發(fā)人員的工作量。其中包含大量Windows句柄封裝類和很多Windows的內(nèi)建控件和組件的封裝類。
3、Qt
Qt[1] 是一個(gè)1991年由Qt Company開發(fā)的跨平臺(tái)C++圖形用戶界面應(yīng)用程序開發(fā)框架。它既可以開發(fā)GUI程序,也可用于開發(fā)非GUI程序,比如控制臺(tái)工具和服務(wù)器。Qt是面向?qū)ο蟮目蚣埽褂锰厥獾拇a生成擴(kuò)展(稱為元對象編譯器(Meta Object Compiler, moc))以及一些宏,Qt很容易擴(kuò)展,并且允許真正地組件編程。2008年,Qt Company科技被諾基亞公司收購,Qt也因此成為諾基亞旗下的編程語言工具。
4、GTK
GTK+(GIMP Toolkit)是一套源碼以LGPL許可協(xié)議分發(fā)、跨平臺(tái)的圖形工具包。最初是為GIMP寫的,已成為一個(gè)功能強(qiáng)大、設(shè)計(jì)靈活的一個(gè)通用圖形庫,是GNU/Linux下開發(fā)圖形界面的應(yīng)用程序的主流開發(fā)工具之一。并且,GTK+也有Windows版本和Mac OS X版。
5、wxWidgets
wxWidgets是一個(gè)開源的跨平臺(tái)的C++構(gòu)架庫(framework),它可以提供GUI(圖形用戶界面)和其它工具。目前的2.x版本支持所有版本的Windows、帶GTK+或Motif的Unix和MacOS。一個(gè)支持OS/2的版本正在開發(fā)中。開源跨平臺(tái), 和 CodeBlocks (開源跨平臺(tái)的IDE)配合的很好, 而且可以用 wxSmith 很方便的設(shè)計(jì)界面。 而且學(xué)過MFC上手 wxWidgets 很快。
上位機(jī)快速開發(fā)教程
(1)準(zhǔn)備工作
一臺(tái)裝有VS2010的計(jì)算機(jī),用于測試的虛擬串口軟件。同時(shí)你必須具有VB基礎(chǔ)知識(shí),這個(gè)VB上位機(jī)開發(fā)是入門級的,僅將VB.NET通信基礎(chǔ)方法稍作介紹。
(2)串口通信常識(shí)
在串口通信中,通過編寫單片機(jī)程序知道,我們應(yīng)對如下參數(shù)進(jìn)行設(shè)置:波特率、數(shù)據(jù)位和停止位、奇偶校驗(yàn)位。如果自己編寫上位機(jī)的時(shí)候,我們考慮的不能僅僅是這些了,下面介紹上位機(jī)開發(fā)過程中需要特別注意的知識(shí)點(diǎn)。
MSComm控件提供了兩種處理通信的方式:一種為事件驅(qū)動(dòng)方式,該方式相當(dāng)于一般程序設(shè)計(jì)中的中斷方式。當(dāng)串口發(fā)生事件或錯(cuò)誤時(shí),MSComm控件會(huì)產(chǎn)生OnComm事件,用戶程序可以捕獲該事件進(jìn)行相應(yīng)處理。
常用屬性和方法
利用MSComm控件實(shí)現(xiàn)計(jì)算機(jī)通信的關(guān)鍵是理解并正確設(shè)置MSComm控件眾多屬性和方法。以下是MSComm控件的常用屬性和方法:
●Commport:設(shè)置或返回串口號。其值從COM1到COM16。
●Settings:以字符串的形式設(shè)置或返回串口通信參數(shù)。
●Portopen:設(shè)置或返回串口狀態(tài)。
●InputMode:設(shè)置或返回接收數(shù)據(jù)的類型。有文本和二進(jìn)制兩種類型。
●Inputlen:設(shè)置或返回一次從接收緩沖區(qū)中讀取字節(jié)數(shù)。
●InBufferSize:設(shè)置或返回接收緩沖區(qū)的大小,缺省值為1024字節(jié)。
●InBufferCount:設(shè)置或返回接收緩沖區(qū)中等待計(jì)算機(jī)接收的字符數(shù)。
●Input:從接收緩沖區(qū)中讀取數(shù)據(jù)并清空該緩沖區(qū),該屬性設(shè)計(jì)時(shí)無效,運(yùn)行時(shí)只讀。
●OutBufferSize:設(shè)置或返回發(fā)送緩沖區(qū)的大小,缺省值為512字節(jié)。
●OutBufferCount:設(shè)置或返回發(fā)送緩沖區(qū)中等待計(jì)算機(jī)發(fā)送的字符數(shù)。
●Output:向發(fā)送緩沖區(qū)發(fā)送數(shù)據(jù),該屬性設(shè)計(jì)時(shí)無效,運(yùn)行時(shí)只讀。
●Rthreshold:該屬性為一閥值。當(dāng)接收緩沖區(qū)中字符數(shù)達(dá)到該值時(shí),MSComm控件設(shè)置Commevent屬性為ComEvReceive,并產(chǎn)生OnComm事件。用戶可在OnComm事件處理程序中進(jìn)行相應(yīng)處理。若Rthreshold屬性設(shè)置為0,則不產(chǎn)生OnComm事件。例如用戶希望接收緩沖區(qū)中達(dá)到一個(gè)字符就接收一個(gè)字符,可將Rthreshold設(shè)置為1。這樣接收緩沖區(qū)中接收到一個(gè)字符,就產(chǎn)生一次OnComm事件。
●Sthreshold:該屬性亦為一閥值。當(dāng)發(fā)送緩沖區(qū)中字符數(shù)小于該值時(shí),MSComm控件設(shè)置Commevent屬性為ComEvSend,并產(chǎn)生OnComm事件。若Sthreshold屬性設(shè)置為0,則不產(chǎn)生OnComm事件。要特別注意的是僅當(dāng)發(fā)送緩沖區(qū)中字符數(shù)小于該值的瞬間才產(chǎn)生OnComm事件,其后就不再產(chǎn)生OnComm事件。例如Sthreshold設(shè)置為3,僅當(dāng)發(fā)送緩沖區(qū)中字符數(shù)從3降為2時(shí),MSComm控件設(shè)置Commevent屬性為ComEvSend,同時(shí)產(chǎn)生OnComm事件,如發(fā)送緩沖區(qū)中字符始終為2,則不會(huì)再產(chǎn)生OnComm事件。這就避免了發(fā)送緩沖區(qū)中數(shù)據(jù)未發(fā)送完就反復(fù)發(fā)生OnComm事件。
●CommEvent:這是一個(gè)非常重要的屬性。該屬性設(shè)計(jì)時(shí)無效,運(yùn)行時(shí)只讀。一旦串口發(fā)生通信事件或產(chǎn)生錯(cuò)誤,依據(jù)產(chǎn)生的事件和錯(cuò)誤,MSComm控件為CommEvent屬性賦不同的代碼,同時(shí)產(chǎn)生OnComm事件。用戶程序就可在OnComm事件處理程序中針對不同的代碼,進(jìn)行相應(yīng)的處理。
(3)開發(fā)步驟(僅供參考)
1. 運(yùn)行VS2010,新建一個(gè)Visual Basic的Windows窗體應(yīng)用程序項(xiàng)目。將窗體的StartPosition屬性改為CenterScreen,運(yùn)行程序時(shí),窗體在屏幕中央顯示。
2. 由于默認(rèn)情況下,通信所需的“Microsoft Communications Control,version 6.0”組件不在工具箱里面,所以我們需要手動(dòng)添加。單擊左側(cè)的工具箱,并在控件欄單擊鼠標(biāo)右鍵,在彈出的菜單中選中“選擇項(xiàng)”,在彈出的對話框中單擊“COM組件”并選中“MicrosoftCommunications Control,version 6.0”,單擊確定即可完成添加。
此時(shí)移動(dòng)鼠標(biāo)到窗體上時(shí),鼠標(biāo)箭頭就會(huì)變成電話的形狀,在窗體任意位置單擊放置該控件。
3. 單擊工具箱,在窗體上添加5個(gè)Label,并在屬性里將Text屬性依次改為:串口號、波特率、校驗(yàn)、數(shù)據(jù)位、停止位。再向窗體上添加5個(gè)ComboBox,從上到下依次排列。
?
? ? ? ?4. 向窗體添加一個(gè)OvalShape和一個(gè)Button。將OvalShape的size屬性改為“24,24”,F(xiàn)illStyle改為Solid。
5. 向窗體添加一個(gè)CheckBox、一個(gè)按鈕Button和一個(gè)TextBox,將CheckBox的Text屬性改為“十六進(jìn)制發(fā)送”將這個(gè)按鈕的text屬性改為“發(fā)送”。
6. 向窗體添加一個(gè)Label和一個(gè)TextBox。更改Label的Text屬性為“接收區(qū)”。
? ? ? ?7. 向窗體添加一個(gè)CheckBox,將其Text屬性改為“十六進(jìn)制顯示”
下面將要對部分控件進(jìn)行設(shè)置,這樣可以減少代碼的長度 將波特率一欄ComboBox的Item屬性中添加如下內(nèi)容:
將校驗(yàn)一欄ComboBox的Item屬性中添加如下內(nèi)容
將數(shù)據(jù)位一欄ComboBox的Item屬性中添加如下內(nèi)容
將波特率一欄ComboBox的Item屬性中添加如下內(nèi)容
四、源代碼
Public Class Form1 Dim cpSetting As String
Dim com_last_num As Integer = 0 ‘定義一個(gè)全局變量,作用為記錄上一個(gè)串口號 Sub GetSerialPortNames() ’搜索計(jì)算機(jī)中所有可用串口函數(shù) On Error GoTo eRRHND ‘錯(cuò)誤處理 ’搜索計(jì)算機(jī)中可用串口
For Each sp As String In My.Computer.Ports.SerialPortNames ComboBox1.Items.Add(sp) Next
ComboBox1.Sorted = True
ComboBox1.SelectedIndex = 0 ‘選擇搜索到的第一個(gè)串口名稱 Exit Sub
eRRHND: ’表示未搜到串口 MsgBox(“Oh, NO!”) End Sub
‘檢測串口是否可用函數(shù)
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 ‘關(guān)閉串口
Test_COM = True ’串口可用則返回
Exit Function
Comm_Error: ‘根據(jù)錯(cuò)誤號作出相應(yīng)處理 If Err.Number = 8002 Then
MsgBox(“串口錯(cuò)誤,請重新選擇串口”, vbOKOnly, “錯(cuò)誤提示!”) ElseIf Err.Number = 8005 Then MsgBox(“串口已打開!”) Else
MsgBox(“其它錯(cuò)誤”) End If
Test_COM = False ’如果出錯(cuò),則返回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 ‘接收緩沖區(qū)大小,此項(xiàng)無法在串口打開時(shí)進(jìn)行設(shè)置 AxMSComm1.OutBufferSize = 1024 ’發(fā)送緩沖區(qū)大小 ComboBox2.Text = “9600” ComboBox3.Text = “無校驗(yàn)” ComboBox4.Text = “8” ComboBox5.Text = “1” ChangePortProperty()
‘設(shè)置接收數(shù)據(jù)的格式為二進(jìn)制
AxMSComm1.InputMode = MSCommLib.InputModeConstants.comInputModeBinary AxMSComm1.InputLen = 0 ’設(shè)置從緩沖區(qū)讀取全部數(shù)據(jù) AxMSComm1.RThreshold = 1 ‘設(shè)置接收串口OnCommon事件 AxMSComm1.PortOpen = True ’打開串口 If AxMSComm1.PortOpen = True Then
OvalShape1.FillColor = Color.Green ‘OvalShape顏色設(shè)為綠色 Button1.Text = “關(guān)閉端口” ’按鈕上的文字顯示為關(guān)閉端口 Else
OvalShape1.FillColor = Color.Red ‘OvalShape顏色設(shè)為紅色 Button1.Text = “打開端口” ’按鈕上的文字顯示為打開端口 End If End Sub
‘打開關(guān)閉串口代碼
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 ‘如果串口是關(guān)閉的 If Test_COM(ptNum) = True Then ’如果選擇的串口可用? ‘ ChangePortProperty()
AxMSComm1.PortOpen = True ’則打開該串口
Button1.Text = “關(guān)閉端口” ‘按鈕上的文字顯示為關(guān)閉端口 OvalShape1.FillColor = Color.Green ’OvalShape顏色設(shè)為綠色 End If Else
AxMSComm1.PortOpen = False ‘關(guān)閉該串口
OvalShape1.FillColor = Color.Red ’OvalShape顏色設(shè)為紅色 Button1.Text = “打開端口” ‘按鈕上的文字顯示為打開端口 End If End Sub
’如下是訪問網(wǎng)站的鏈接的代碼,可以選擇訪問網(wǎng)站的瀏覽器,這里只使用默認(rèn)的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
‘處理發(fā)送數(shù)據(jù)的代碼
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 ’將要發(fā)送的數(shù)據(jù)存放到變量source_Txt中
If CheckBox1.CheckState = CheckState.Checked Then ‘如果十六進(jìn)制發(fā)送復(fù)選框被勾上 If Len(source_Txt) Mod 2 = 0 And Len(source_Txt) 《》 0 Then ’如果將要發(fā)送的數(shù)據(jù)長度不為或者能被2整除
ReDim hexString(Len(source_Txt) / 2 - 1) ‘重新定義hexString數(shù)組 For i = 0 To Len(source_Txt) - 1 Step 2
hexString(i / 2) = Val(“&H” & Mid(source_Txt, i + 1, 2)) ’將hexString轉(zhuǎn)換成十六進(jìn)制顯示
Next
AxMSComm1.Output = hexString ‘將轉(zhuǎn)換的數(shù)據(jù)發(fā)送到串口 Else ’否則提示格式不正確 MsgBox(“格式不正確!”) End If
Else ‘否則輸出字符串
AxMSComm1.Output = TextBox1.Text
End If End Sub
Sub ChangePortProperty() Dim comSetting As String Dim parity As String = “” ‘關(guān)閉端口
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 ‘設(shè)置校驗(yàn)方式
If ComboBox3.Text = “無校驗(yàn)” Then parity = “N”
ElseIf ComboBox3.Text = “奇校驗(yàn)” Then parity = “O”
ElseIf ComboBox3.Text = “偶校驗(yàn)” Then parity = “E” End If
comSetting = ComboBox2.Text & “,” & parity & “,” & ComboBox4.Text & “,” & ComboBox5.Text
’串口設(shè)置格式:9600,N,8,1 AxMSComm1.Settings = comSetting End Sub
‘將十進(jìn)制轉(zhuǎn)換為16進(jìn)制
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
’串口號發(fā)生改變的處理程序
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 ‘用來從接收緩沖區(qū)讀取數(shù)據(jù)
Select Case AxMSComm1.CommEvent ’
對接收事件進(jìn)行處理
Case MSCommLib.OnCommConstants.comEvReceive
bytData = AxMSComm1.Input ‘將接收到的數(shù)據(jù)暫存 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 ’將轉(zhuǎn)換后的數(shù)據(jù)在接收區(qū)顯示
End Select
End Sub
End Class
五、程序中用到的幾個(gè)函數(shù)解釋
Microsoft.VisualBasic.Strings.Right(String,Num):將字符串從右邊開始截取字符串String中Num個(gè)字符。例如當(dāng)String的值為“Welcome”,Num值為3,則該函數(shù)返回的值為字符串“ome”。另外通過將COM1拆分即可得到1,這是上例中得到得到串口號的方法。
Val(String):將字符串類型轉(zhuǎn)換為數(shù)值型。例如String為字符串“123”,則返回值為數(shù)值型123。 Hex(Integer):將整型數(shù)轉(zhuǎn)換為16進(jìn)制數(shù)。如:Integer為13,則返回十六進(jìn)制的D
其實(shí)有些函數(shù)看不懂也沒關(guān)系,可能我介紹的不是很詳細(xì),有些資料上網(wǎng)查一下也很方便的,這里就不再多羅嗦了。
評論
查看更多