1.前言伴隨著計算機技術的進步,計算機與智能化儀器儀表之間的串行通訊接口也得到了同步發(fā)展。眾所周知,早期的RS-232接口,只能完成單點對單點的單向通訊。后來誕生的RS-422接口,可以完成單點對多點的單向通訊。再后來誕生的RS-485接口,可以完成單點對多點的雙向通訊。由于RS-485接口的先進性,迅速在工農(nóng)業(yè)各領域得到了普及應用。本文介紹的溫濕度監(jiān)測系統(tǒng),就是在RS-485總線架構(gòu)下,由計算機主機和若干個帶RS-485接口的溫濕度表構(gòu)成的。該系統(tǒng)可以對32至128點的溫濕度進行實時監(jiān)測。
本文引用地址:http://www.biyoush.com/article/201612/330199.htm2.硬件系統(tǒng)的設計
2.1硬件系統(tǒng)設備的選型
作為硬件系統(tǒng)的主角——計算機,應選擇奔騰4以上的臺式計算機,操作系統(tǒng)應選擇安裝Windows2000或Windows XP或更高。溫濕度表應選擇壁掛式且?guī)S-485接口的,最好是220V交流供電。如選用電池供電的,需要經(jīng)常檢查和更換電池,還會頻發(fā)因電解質(zhì)泄漏而腐蝕電路的故障,增加應用時期的維護工作量。此外,還需要一個RS-232/485轉(zhuǎn)換器。組網(wǎng)用的電纜線應采用帶屏蔽線的RS-485專用雙絞線電纜。
2.2基于485總線的硬件系統(tǒng)結(jié)構(gòu)
由RS-485接口設備構(gòu)成的網(wǎng)絡,一般應采用一線到底的總線結(jié)構(gòu),不支持星形或樹形等復雜的網(wǎng)絡。各溫濕度表安裝地點與485總線的距離應盡量短。否則,將增加分支引線中的反射信號對總線信號的影響,造成通訊數(shù)據(jù)出錯。由于計算機只配備1~2個RS-232串行接口,需要在RS-232接口處串接一個RS-232/485轉(zhuǎn)換器。如果總線的長度大于300米時,應在485總線的起點和終點處的AB兩線之間并接120Ω電阻,以實現(xiàn)總線的阻抗匹配。
普通的帶RS-485接口的設備,接入485總線的數(shù)量通常不能大于32個,帶加強型芯片的設備可以接入128個或更多。圖1是由32個設備組成的溫濕度監(jiān)測系統(tǒng)的組網(wǎng)結(jié)構(gòu)圖。
3.軟件系統(tǒng)的設計
軟件系統(tǒng)采用VB6設計。為了保證軟件系統(tǒng)能夠不斷升級,在設計系統(tǒng)框架時,應該對今后可能需要增加的功能模塊留出擴充余地。本系統(tǒng)的框架結(jié)構(gòu)如下所示:

3.1軟件系統(tǒng)各界面的設計
軟件系統(tǒng)啟動時,首先顯示一個歡迎界面,停留若干秒后自動轉(zhuǎn)入主程序界面。如圖2、圖3所示。

圖2

圖3
各功能模塊的顯示界面主要有“查詢溫濕度數(shù)據(jù)”界面、“系統(tǒng)參數(shù)設置”界面和“串口調(diào)試”界面,參見圖4、圖5、圖6。

圖4

圖5、圖6
3.2定時讀寫各溫濕度表數(shù)據(jù)的程序設計
在軟件系統(tǒng)各功能模塊中,最核心的部分就是定時讀寫各溫濕度表的溫濕度數(shù)據(jù)。因此,下面將該模塊的程序清單詳細列出。
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Public btLoCRC As Byte, btHiCRC As Byte, t1 As Long
Public WPath1 As String, WPath2 As String, WFilename1 As String, WFilename2 As String, WFilename3 As String
Public RoomNumber As String, CommNumber As String, Baudrate As String, ReadT As String, WriteT As String
Public IntMinute1 As Integer, IntMinute2 As Integer, ReadTval As Integer, WriteTval As Integer
Public Rnumber As Integer, ii As Integer, i As Integer, j As Integer, k As Integer, Crc
Dim RoomAddress(32), Roomname(32) As String, TemperatureData(32), HumidityData(32)
Private Sub ReadFiles()’讀系統(tǒng)運行參數(shù)子程序
Open "D:Program FilesTmeasurewsboot.txt" For Input As #1 Len = 32
Input #1, WPath1, WPath2
Input #1, WFilename1, WFilename2, WFilename3
Input #1, RoomNumber, CommNumber, Baudrate, ReadT, WriteT
For i = 1 To Val(RoomNumber)
Input #1, RoomAddress(i), Roomname(i)
Form2.Frame1(i - 1).Caption = Roomname(i) & "(地址" & RoomAddress(i) & ")"
Next i
Close #1
End Sub
Private Sub Form_Load()’主窗口程序
Me.BorderStyle = 1
Me.Height = 6660’設定窗口高度
ReadFiles
Data1.DatabaseName = WPath1 & WFilename1 & WFilename2 & ".mdb"
Data1.RecordSource = "溫濕度數(shù)據(jù)"
Rnumber = Val(RoomNumber)
ReadTval = Val(ReadT)
WriteTval = Val(WriteT)
IntMinute1 = Val(ReadT)
With MSComm1’打開串口
If .PortOpen = False Then
.CommPort = Val(CommNumber)’指定使用的串口
.Settings = Baudrate & "N,8,1"
.NullDiscard = False’和下一句配合使之可以發(fā)送0(零)字符
.InputMode = comInputModeBinary’發(fā)送二進制數(shù)值(=comInputModeText發(fā)送字符)
.InputLen = 8 + 1’一次性從接收緩沖區(qū)中讀取所有數(shù)據(jù)(8個字節(jié)為一組)
.InBufferCount = 0’清空接收緩沖區(qū)
.OutBufferCount = 0’清空發(fā)送緩沖區(qū)
.SThreshold = 8’設置成發(fā)送8個字節(jié)就產(chǎn)生OnComm事件
.RThreshold = 5 + 2 * 2’設置成接收9個字節(jié)就產(chǎn)生OnComm事件
.InBufferSize = 1024
.OutBufferSize = 1024
.PortOpen = True
Else
MsgBox "串口已經(jīng)打開"
End If
End With
Timer1.Interval = 1000
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()’定時讀各溫濕度表數(shù)據(jù)
Timer1.Enabled = False
Dim tbisend(7) As Byte
Dim strTempFile As String, m As Integer
Dim conn As New ADODB.Connection
If MSComm1.PortOpen = True Then
For k = 1 To Rnumber
ii = k
tbisend(0) = "&h" + Hex(k)’被呼叫子機的地址碼
tbisend(1) = "&h" + Hex(4)’4是讀寄存器的功能碼
tbisend(2) = "&h" + Hex(0)’被讀寄存器的起始地址高字節(jié)
tbisend(3) = "&h" + Hex(0)’被讀寄存器的起始地址低字節(jié)
tbisend(4) = "&h" + Hex(0)’一次讀寄存器的個數(shù)的高字節(jié)
tbisend(5) = "&h" + Hex(2)’一次讀寄存器的個數(shù)的低字節(jié)
Crc = CRC16(tbisend, 6, btLoCRC, btHiCRC)
tbisend(6) = "&h" + Hex(btLoCRC)’CRC低位
tbisend(7) = "&h" + Hex(btHiCRC)’CRC高位
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
MSComm1.Output = tbisend’發(fā)送數(shù)據(jù)
t1 = timeGetTime
While timeGetTime < t1 + 40’延時的循環(huán)等待(延時40毫秒,控制精度1毫秒)
DoEvents’以便接收到被呼叫的從機發(fā)來的數(shù)據(jù)
Wend
MorphDisplay1(k - 1).Value = TemperatureData(k)
MorphDisplay2(k - 1).Value = HumidityData(k)
Next k
IntMinute2 = Val(Right(Time, 2))
If IntMinute2 < IntMinute1 Then
WriteTval = WriteTval – 1
If WriteTval = 0 Then
Data1.Refresh
If Data1.Recordset.EOF = False Then Data1.Recordset.MoveLast
If conn.State = adStateOpen Then conn.Close’向溫濕度數(shù)據(jù)庫文件寫入測量數(shù)據(jù)
conn.ConnectionString = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = " & WPath1 & WFilename1 & WFilename2 & ".mdb; Mode = ReadWrite; Persist Security Info = False"
conn.Open
s1 = "Insert Into溫濕度數(shù)據(jù)(日期,時間,1溫,1濕,2溫,2濕,3溫,3濕,4溫,4濕,5溫,5濕,"
s2 = "6溫,6濕,7溫,7濕,8溫,8濕,9溫,9濕,10溫,10濕) Values "
s3 = "(#" & Date & "# ,#" & Time & "#," & TemperatureData(1) & "," & HumidityData(1) & ","
s4 = "" & TemperatureData(2) & "," & HumidityData(2) & "," & TemperatureData(3) & ","
s5 = "" & HumidityData(3) & "," & TemperatureData(4) & "," & HumidityData(4) & ","
s6 = "" & TemperatureData(5) & "," & HumidityData(5) & "," & TemperatureData(6) & ","
s7 = "" & HumidityData(6) & "," & TemperatureData(7) & "," & HumidityData(7) & ","
s8 = "" & TemperatureData(8) & "," & HumidityData(8) & "," & TemperatureData(9) & ","
s9 = "" & HumidityData(9) & "," & TemperatureData(10) & "," & HumidityData(10) & ")"
conn.Execute s1 & s2 & s3 & s4 & s5 & s6 & s7 & s8 & s9
conn.Close
End If
WriteTval = Val(WriteT)
End If
End If
End If
Timer1.Interval = ReadTval
Timer1.Enabled = True
End Sub
Private Sub MSComm1_OnComm()’接收各溫濕度表數(shù)據(jù)程序
Dim TemperatureData6 As String, HumidityData6 As String
Dim INByte() As Byte
If MSComm1.CommEvent = comEvReceive Then’如有接收事件發(fā)生則......
INByte = MSComm1.Input
If INByte(0) = ii And INByte(1) = 4 Then’如果收到的地址碼=被叫從機并且功能碼=讀寄存器,
’則將收到的CRC碼與收到數(shù)據(jù)計算出的CRC碼比較
Crc = CRC16(INByte, UBound(INByte) - LBound(INByte) - 1, btLoCRC, btHiCRC)
If INByte(UBound(INByte) - 1) = btLoCRC And INByte(UBound(INByte)) = btHiCRC Then ’如校驗正確則轉(zhuǎn)換
TemperatureData6 = Hex(INByte(3)) & Format(Hex(INByte(4)), "00")’先轉(zhuǎn)換成十六進制
HumidityData6 = Hex(INByte(5)) & Format(Hex(INByte(6)), "00")’
TemperatureData(ii) = Format(Val("&H" & TemperatureData6) / 10, "##0.0")’再轉(zhuǎn)換為十進制
HumidityData(ii) = Format(Val("&H" & HumidityData6) / 10, "##0.0")
End If
End If
MSComm1.InBufferCount = 0’清接收緩存
End If
End Sub
Function CRC16(Data() As Byte, No As Integer, CRC16Lo As Byte, CRC16Hi As Byte) As String’CRC校驗函數(shù)
Dim CL As Byte, CH As Byte, SaveLo As Byte, SaveHi As Byte
CRC16Hi = &HFF’為16位CRC校驗寄存器賦初始值FFFF
CRC16Lo = &HFF
CH = &HA0’為16位CRC校驗多項式賦初始值A001
CL = &H1
For i = 1 To No
CRC16Lo = CRC16Lo Xor Data(i - 1)’每一個數(shù)據(jù)與CRC校驗寄存器進行異或
For j = 1 To 8
SaveHi = CRC16Hi
SaveLo = CRC16Lo
CRC16Hi = CRC16Hi 2’高位右移一位
CRC16Lo = CRC16Lo 2’低位右移一位
If ((SaveHi And &H1) = &H1) Then’如果高位字節(jié)最右一位為1
CRC16Lo = CRC16Lo Or &H80’則低位字節(jié)最左一位補1,否則自動補0
End If
If ((SaveLo And &H1) = &H1) Then’如低位字節(jié)最右一位為1,則與CRC校驗多項式異或
CRC16Hi = CRC16Hi Xor CH
CRC16Lo = CRC16Lo Xor CL
End If
Next j
Next i
End Function
4.結(jié)束語
經(jīng)過對軟件系統(tǒng)的多次修改和完善,本系統(tǒng)已經(jīng)于2009年10月交付用戶使用。受篇幅限制,以上僅扼要介紹了系統(tǒng)的主要設計思路與方法,未能將程序清單全部列出。如果發(fā)現(xiàn)本文或在應用中存在錯誤,歡迎指正。
參考文獻:
① 《微型計算機原理與接口技術》中國科學技術大學出版社作者:周荷琴 吳秀清
② 《單片機原理及串行外設接口技術》北京航空航天大學出版社作者:李朝青等
③ 《RS-232串口通信大全》下載網(wǎng)址:http://download.csdn.net/source/2443662
評論