發(fā)表于:2008/11/25 22:16:00
#0樓
----一臺工業(yè)專用實時檢測儀表,接高精度位移傳感器,用于測量微小形變或微量位移,儀表測量精度為0.01毫米,測量范圍最大值為50毫米。該儀表帶有一個9針的rs-232c 串口,能與微機(jī)進(jìn)行串口數(shù)據(jù)通信,實時傳送檢測數(shù)據(jù),通過微機(jī)軟件處理可實現(xiàn)工業(yè)實時監(jiān)控。
----該儀表的串口數(shù)據(jù)通信協(xié)議是:數(shù)據(jù)傳輸速率為 9600bps,1位開始位,8位數(shù)據(jù)位,1位停止位,無奇偶校驗位。儀表每秒發(fā)送50幀檢測數(shù)據(jù),每幀數(shù)據(jù)由4個字節(jié)組成。第一個字節(jié)定義為二進(jìn)制常數(shù)0f0h,是每幀數(shù)據(jù)開始的標(biāo)志字節(jié);后面連續(xù)2個字節(jié)為數(shù)據(jù)字節(jié),采用壓縮的bcd碼編碼方式,高位在前,低位在后,即一個字節(jié)表示兩位十進(jìn)制數(shù),則兩個字節(jié)表示四位十進(jìn)制數(shù),小數(shù)點采用固定形式,定義在兩字節(jié)中間;第四個字節(jié)為符號字節(jié),該字節(jié)第八位為1,即:
![圖]()
----則為負(fù)數(shù);第八位為0,即:
![圖]()
----則為正數(shù)。
----例如:0f0h 26h 87h 80h 0f0h 34h 62h 00h 表示 -26.87 34.62。
----通信傳輸速率為9600bps,則最快速度1.04ms發(fā)送一個字節(jié),儀表每秒發(fā)送50幀數(shù)據(jù),每幀數(shù)據(jù)有4個字節(jié),即每秒發(fā)送200個字節(jié),平均5.0ms 發(fā)送一個字節(jié),連續(xù)讀取串口數(shù)據(jù)時要在程序中添加循環(huán)等待程序。
----為了實現(xiàn)實時監(jiān)測功能,接收數(shù)據(jù)的讀取要盡可能的快速,則設(shè)置mscomm1的屬性如下:
rthreshold = 1
接收緩沖區(qū)收到一個字節(jié)產(chǎn)生oncomm事件
inputlen = 1 每次讀取一個字節(jié)
----儀表每秒發(fā)送50幀數(shù)據(jù),微機(jī)收到一幀完整數(shù)據(jù)至少需要20 ms時間,然后再進(jìn)行數(shù)據(jù)處理。如果微機(jī)在下一幀數(shù)據(jù)接收前即20ms內(nèi)能將數(shù)據(jù)計算處理完畢,則接收緩沖區(qū)內(nèi)只會保存有一幀數(shù)據(jù),不會存有兩幀以上數(shù)據(jù),接收緩沖區(qū)的大小不會影響實時監(jiān)測效果(接收緩沖區(qū)>4字節(jié)),這時完全可以實現(xiàn)實時監(jiān)測或?qū)崟r控制;如果微機(jī)在20ms內(nèi)不能將數(shù)據(jù)計算處理完畢,接收緩沖區(qū)設(shè)置得又很大,在數(shù)據(jù)計算處理完畢前,接收緩沖區(qū)內(nèi)就會保存有兩幀以上數(shù)據(jù),而且一次工作時間越長,緩沖區(qū)內(nèi)滯留數(shù)據(jù)幀就越多,數(shù)據(jù)采集和數(shù)據(jù)處理之間產(chǎn)生逐漸增大的額外時間差,當(dāng)接收緩沖區(qū)充滿后,時間差不再增大,固定在某一值,部分?jǐn)?shù)據(jù)因不能及時采集到接收緩沖區(qū)中,數(shù)據(jù)產(chǎn)生丟失現(xiàn)象,真實工作情況就會和微機(jī)處理結(jié)果產(chǎn)生較大的時間差,對實時監(jiān)測和實時控制很不利,這種情況下接收緩沖區(qū)的大小就會影響實時監(jiān)測效果,所以接收緩沖區(qū)設(shè)置不能過大,以保證數(shù)據(jù)處理的實時性。
----設(shè)置接收數(shù)據(jù)模式采用二進(jìn)制形式,即 inputmode=cominputmodebinary,但用input屬性讀取數(shù)據(jù)時,不能直接賦值給 byte 類型變量,只能通過先賦值給一個 variant 類型變量,返回一個二進(jìn)制數(shù)據(jù)的數(shù)組,再轉(zhuǎn)換保存到byte類型數(shù)變量中。
----vb中有byte類型變量,但沒有字節(jié)的位處理語句,符號字節(jié)的位處理要判斷符號字節(jié)的值是否大于 127,大于127則為負(fù)數(shù);壓縮的bcd碼存入 byte類型變量,vb系統(tǒng)只按十進(jìn)制數(shù)處理,這要通過一個簡單算法換算,解壓bcd碼才能還原成十進(jìn)制表示數(shù)值。假如a是byte類型變量,d是single類型變量,將一個壓縮的bcd 碼存入a中,則算法是:
d=(a\16)*10 + a-(a\16)*16
則d=a-(a\16)*6
----程序清單:
----在通用聲明中定義程序所用變量:
dim ab(4) as byte
‘字節(jié)數(shù)據(jù)類型數(shù)組,用來存儲接收到的一組字節(jié)數(shù)據(jù)
dim av as variant ‘用來從接收緩沖區(qū)讀取數(shù)據(jù)
dim i as integer
dim j as integer
dim w as integer ‘接收數(shù)據(jù)個數(shù)計數(shù)器
dim b1 as single
dim b2 as single
dim ww as single ‘十進(jìn)制檢測值
dim maxw as single ‘最大值
dim minw as single ‘最小值
----在窗體中添加名為command1的[開始]按鈕和名為 mscomm1的mscomm控件。
---- [開始]按鈕的click事件處理程序主要是對mscomm1控制的參數(shù)初始化設(shè)置,程序中大部分參數(shù)在設(shè)計時可在mscomm1控制的屬性窗口中設(shè)置:
private sub command1_click()
‘開始按鈕
with mscomm1
.commport=2 ‘使用com2
.setting=“9600,n,8,1 ‘設(shè)置通信口參數(shù)
.inbuffersize=40
‘設(shè)置mscomm1接收緩沖區(qū)為40字節(jié)
.outbuffersize=2
‘設(shè)置mscomm1發(fā)送緩沖區(qū)為2字節(jié)
.inputmode = cominputmodebinary
‘設(shè)置接收數(shù)據(jù)模式為二進(jìn)制形式
.inputlen = 1
‘設(shè)置input 一次從接收緩沖讀取字節(jié)數(shù)為1
.sthreshold = 1
‘設(shè)置output 一次從發(fā)送緩沖讀取字節(jié)數(shù)為1
.inbuffercount = 0 ‘清除接收緩沖區(qū)
.outbuffercount = 0 ‘清除發(fā)送緩沖區(qū)
maxw = -99
‘最大值賦初值
minw = 99 ‘最小值賦初值
w = 0
‘?dāng)?shù)據(jù)個數(shù)計數(shù)器清零
.rthreshold = 1
‘設(shè)置接收一個字節(jié)產(chǎn)生oncomm事件
if .portopen = false then
‘判斷通信口是否打開
.portopen = true ‘打開通信口
if err then ‘錯誤處理
msgbox “串口通信無效
exit sub
end if
end if
end with
end sub
----為了達(dá)到實時數(shù)據(jù)采集目的,實時數(shù)據(jù)采集處理程序采用mscomm事件驅(qū)動方式。
----mscomm1_oncomm的事件處理程序只處理 comevreceive事件,首先判斷幀數(shù)據(jù)的開始字節(jié),關(guān)閉oncomm接收事件,然后接收數(shù)據(jù)字節(jié),將壓縮bcd進(jìn)行還原轉(zhuǎn)換,再接收符號字節(jié),判斷數(shù)據(jù)符號,判斷數(shù)據(jù)最大最小值,最后打開oncomm接收事件,等待下一次oncomm事件產(chǎn)生:
private sub mscomm1_oncomm()
with mscomm1
select case .commevent
‘判斷mscomm1通信事件
case comevreceive
‘收到rthreshold個字節(jié)產(chǎn)生的接收事件
av = .input
‘讀取一個接收字節(jié)
ab(1) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
if ab(1) = &hf0 then
‘判斷是否為數(shù)據(jù)開始標(biāo)志
rthreshold = 0
‘關(guān)閉oncomm事件接收
do
doevents
loop until .inbuffercount >= 3
‘循環(huán)等待mscomm1接收緩沖區(qū)>=3個字節(jié)
w = w + 1 ‘計數(shù)器累加計數(shù)
av = .input
‘讀取第二個數(shù)據(jù)字節(jié)(bcd碼高位字節(jié))
ab(2) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .input
‘讀取第三個數(shù)據(jù)字節(jié)(bcd碼低位字節(jié))
ab(3) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .input
‘讀取第四個數(shù)據(jù)字節(jié)(符號位字節(jié))
ab(4) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
b1 = ab(2) - 6 * (ab(2)\16)
‘高位字節(jié)壓縮bcd碼轉(zhuǎn)換為實數(shù)
b2 = ab(3) - 6 * (ab(3)\16)
‘低位字節(jié)壓縮bcd碼轉(zhuǎn)換為實數(shù)
ww = b1 + b2 / 100
‘?dāng)?shù)值組合,標(biāo)定小數(shù)點
if ab(4) > 127 then ww=ww
‘判斷數(shù)據(jù)符號位
label1(0) = format(ww, “0.00)
‘顯示毫米單位數(shù)值,2位小數(shù)
label1(1) =format(ww /25.4, “0.000)
‘顯示英寸單位數(shù)值,3位小數(shù)
if ww > maxw and ww
----‘判斷最大值,儀表在剛開始工作時有干擾,會傳導(dǎo)一些亂碼,位移傳感器有參數(shù)偏差,最大值一般都略大于50毫米,所以取51為極限最大值,取-51為極限最小值。
maxw = ww
label1(2) = format(maxw, “0.00)
‘顯示毫米單位最大值,2位小數(shù)
label1(3) = format(maxw/25.4,“0.000)
‘顯示英寸單位最大值,3位小數(shù)
end if
if ww -51 then
‘判斷最小值
minw = ww
label1(4) = format(minw, “0.00)
‘顯示毫米單位最小值,2位小數(shù)
label1(5) = format(minw/25.4,“0.000)
‘顯示英寸單位最小值,3位小數(shù)
end if
.rthreshold = 1
‘打開mscomm1事件接收
end if
case else
end select
end with
end sub
----------------------------------------------
此篇文章從博客轉(zhuǎn)發(fā)
原文地址: Http://blog.gkong.com/more.asp?id=69121&Name=yangyongxiang
----該儀表的串口數(shù)據(jù)通信協(xié)議是:數(shù)據(jù)傳輸速率為 9600bps,1位開始位,8位數(shù)據(jù)位,1位停止位,無奇偶校驗位。儀表每秒發(fā)送50幀檢測數(shù)據(jù),每幀數(shù)據(jù)由4個字節(jié)組成。第一個字節(jié)定義為二進(jìn)制常數(shù)0f0h,是每幀數(shù)據(jù)開始的標(biāo)志字節(jié);后面連續(xù)2個字節(jié)為數(shù)據(jù)字節(jié),采用壓縮的bcd碼編碼方式,高位在前,低位在后,即一個字節(jié)表示兩位十進(jìn)制數(shù),則兩個字節(jié)表示四位十進(jìn)制數(shù),小數(shù)點采用固定形式,定義在兩字節(jié)中間;第四個字節(jié)為符號字節(jié),該字節(jié)第八位為1,即:
----則為負(fù)數(shù);第八位為0,即:
----則為正數(shù)。
----例如:0f0h 26h 87h 80h 0f0h 34h 62h 00h 表示 -26.87 34.62。
----通信傳輸速率為9600bps,則最快速度1.04ms發(fā)送一個字節(jié),儀表每秒發(fā)送50幀數(shù)據(jù),每幀數(shù)據(jù)有4個字節(jié),即每秒發(fā)送200個字節(jié),平均5.0ms 發(fā)送一個字節(jié),連續(xù)讀取串口數(shù)據(jù)時要在程序中添加循環(huán)等待程序。
----為了實現(xiàn)實時監(jiān)測功能,接收數(shù)據(jù)的讀取要盡可能的快速,則設(shè)置mscomm1的屬性如下:
rthreshold = 1
接收緩沖區(qū)收到一個字節(jié)產(chǎn)生oncomm事件
inputlen = 1 每次讀取一個字節(jié)
----儀表每秒發(fā)送50幀數(shù)據(jù),微機(jī)收到一幀完整數(shù)據(jù)至少需要20 ms時間,然后再進(jìn)行數(shù)據(jù)處理。如果微機(jī)在下一幀數(shù)據(jù)接收前即20ms內(nèi)能將數(shù)據(jù)計算處理完畢,則接收緩沖區(qū)內(nèi)只會保存有一幀數(shù)據(jù),不會存有兩幀以上數(shù)據(jù),接收緩沖區(qū)的大小不會影響實時監(jiān)測效果(接收緩沖區(qū)>4字節(jié)),這時完全可以實現(xiàn)實時監(jiān)測或?qū)崟r控制;如果微機(jī)在20ms內(nèi)不能將數(shù)據(jù)計算處理完畢,接收緩沖區(qū)設(shè)置得又很大,在數(shù)據(jù)計算處理完畢前,接收緩沖區(qū)內(nèi)就會保存有兩幀以上數(shù)據(jù),而且一次工作時間越長,緩沖區(qū)內(nèi)滯留數(shù)據(jù)幀就越多,數(shù)據(jù)采集和數(shù)據(jù)處理之間產(chǎn)生逐漸增大的額外時間差,當(dāng)接收緩沖區(qū)充滿后,時間差不再增大,固定在某一值,部分?jǐn)?shù)據(jù)因不能及時采集到接收緩沖區(qū)中,數(shù)據(jù)產(chǎn)生丟失現(xiàn)象,真實工作情況就會和微機(jī)處理結(jié)果產(chǎn)生較大的時間差,對實時監(jiān)測和實時控制很不利,這種情況下接收緩沖區(qū)的大小就會影響實時監(jiān)測效果,所以接收緩沖區(qū)設(shè)置不能過大,以保證數(shù)據(jù)處理的實時性。
----設(shè)置接收數(shù)據(jù)模式采用二進(jìn)制形式,即 inputmode=cominputmodebinary,但用input屬性讀取數(shù)據(jù)時,不能直接賦值給 byte 類型變量,只能通過先賦值給一個 variant 類型變量,返回一個二進(jìn)制數(shù)據(jù)的數(shù)組,再轉(zhuǎn)換保存到byte類型數(shù)變量中。
----vb中有byte類型變量,但沒有字節(jié)的位處理語句,符號字節(jié)的位處理要判斷符號字節(jié)的值是否大于 127,大于127則為負(fù)數(shù);壓縮的bcd碼存入 byte類型變量,vb系統(tǒng)只按十進(jìn)制數(shù)處理,這要通過一個簡單算法換算,解壓bcd碼才能還原成十進(jìn)制表示數(shù)值。假如a是byte類型變量,d是single類型變量,將一個壓縮的bcd 碼存入a中,則算法是:
d=(a\16)*10 + a-(a\16)*16
則d=a-(a\16)*6
----程序清單:
----在通用聲明中定義程序所用變量:
dim ab(4) as byte
‘字節(jié)數(shù)據(jù)類型數(shù)組,用來存儲接收到的一組字節(jié)數(shù)據(jù)
dim av as variant ‘用來從接收緩沖區(qū)讀取數(shù)據(jù)
dim i as integer
dim j as integer
dim w as integer ‘接收數(shù)據(jù)個數(shù)計數(shù)器
dim b1 as single
dim b2 as single
dim ww as single ‘十進(jìn)制檢測值
dim maxw as single ‘最大值
dim minw as single ‘最小值
----在窗體中添加名為command1的[開始]按鈕和名為 mscomm1的mscomm控件。
---- [開始]按鈕的click事件處理程序主要是對mscomm1控制的參數(shù)初始化設(shè)置,程序中大部分參數(shù)在設(shè)計時可在mscomm1控制的屬性窗口中設(shè)置:
private sub command1_click()
‘開始按鈕
with mscomm1
.commport=2 ‘使用com2
.setting=“9600,n,8,1 ‘設(shè)置通信口參數(shù)
.inbuffersize=40
‘設(shè)置mscomm1接收緩沖區(qū)為40字節(jié)
.outbuffersize=2
‘設(shè)置mscomm1發(fā)送緩沖區(qū)為2字節(jié)
.inputmode = cominputmodebinary
‘設(shè)置接收數(shù)據(jù)模式為二進(jìn)制形式
.inputlen = 1
‘設(shè)置input 一次從接收緩沖讀取字節(jié)數(shù)為1
.sthreshold = 1
‘設(shè)置output 一次從發(fā)送緩沖讀取字節(jié)數(shù)為1
.inbuffercount = 0 ‘清除接收緩沖區(qū)
.outbuffercount = 0 ‘清除發(fā)送緩沖區(qū)
maxw = -99
‘最大值賦初值
minw = 99 ‘最小值賦初值
w = 0
‘?dāng)?shù)據(jù)個數(shù)計數(shù)器清零
.rthreshold = 1
‘設(shè)置接收一個字節(jié)產(chǎn)生oncomm事件
if .portopen = false then
‘判斷通信口是否打開
.portopen = true ‘打開通信口
if err then ‘錯誤處理
msgbox “串口通信無效
exit sub
end if
end if
end with
end sub
----為了達(dá)到實時數(shù)據(jù)采集目的,實時數(shù)據(jù)采集處理程序采用mscomm事件驅(qū)動方式。
----mscomm1_oncomm的事件處理程序只處理 comevreceive事件,首先判斷幀數(shù)據(jù)的開始字節(jié),關(guān)閉oncomm接收事件,然后接收數(shù)據(jù)字節(jié),將壓縮bcd進(jìn)行還原轉(zhuǎn)換,再接收符號字節(jié),判斷數(shù)據(jù)符號,判斷數(shù)據(jù)最大最小值,最后打開oncomm接收事件,等待下一次oncomm事件產(chǎn)生:
private sub mscomm1_oncomm()
with mscomm1
select case .commevent
‘判斷mscomm1通信事件
case comevreceive
‘收到rthreshold個字節(jié)產(chǎn)生的接收事件
av = .input
‘讀取一個接收字節(jié)
ab(1) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
if ab(1) = &hf0 then
‘判斷是否為數(shù)據(jù)開始標(biāo)志
rthreshold = 0
‘關(guān)閉oncomm事件接收
do
doevents
loop until .inbuffercount >= 3
‘循環(huán)等待mscomm1接收緩沖區(qū)>=3個字節(jié)
w = w + 1 ‘計數(shù)器累加計數(shù)
av = .input
‘讀取第二個數(shù)據(jù)字節(jié)(bcd碼高位字節(jié))
ab(2) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .input
‘讀取第三個數(shù)據(jù)字節(jié)(bcd碼低位字節(jié))
ab(3) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
av = .input
‘讀取第四個數(shù)據(jù)字節(jié)(符號位字節(jié))
ab(4) = av(0)
‘轉(zhuǎn)換保存到字節(jié)數(shù)據(jù)類型數(shù)組
b1 = ab(2) - 6 * (ab(2)\16)
‘高位字節(jié)壓縮bcd碼轉(zhuǎn)換為實數(shù)
b2 = ab(3) - 6 * (ab(3)\16)
‘低位字節(jié)壓縮bcd碼轉(zhuǎn)換為實數(shù)
ww = b1 + b2 / 100
‘?dāng)?shù)值組合,標(biāo)定小數(shù)點
if ab(4) > 127 then ww=ww
‘判斷數(shù)據(jù)符號位
label1(0) = format(ww, “0.00)
‘顯示毫米單位數(shù)值,2位小數(shù)
label1(1) =format(ww /25.4, “0.000)
‘顯示英寸單位數(shù)值,3位小數(shù)
if ww > maxw and ww
----‘判斷最大值,儀表在剛開始工作時有干擾,會傳導(dǎo)一些亂碼,位移傳感器有參數(shù)偏差,最大值一般都略大于50毫米,所以取51為極限最大值,取-51為極限最小值。
maxw = ww
label1(2) = format(maxw, “0.00)
‘顯示毫米單位最大值,2位小數(shù)
label1(3) = format(maxw/25.4,“0.000)
‘顯示英寸單位最大值,3位小數(shù)
end if
if ww -51 then
‘判斷最小值
minw = ww
label1(4) = format(minw, “0.00)
‘顯示毫米單位最小值,2位小數(shù)
label1(5) = format(minw/25.4,“0.000)
‘顯示英寸單位最小值,3位小數(shù)
end if
.rthreshold = 1
‘打開mscomm1事件接收
end if
case else
end select
end with
end sub
----------------------------------------------
此篇文章從博客轉(zhuǎn)發(fā)
原文地址: Http://blog.gkong.com/more.asp?id=69121&Name=yangyongxiang