關(guān)鍵詞:激光粒度儀;USB總線;線程;數(shù)據(jù)采集
Application of Threads in Laser Particle Sizer Based on USB??
LU Yumin, ZHENG Gang, SUN Hao
(College of Optics and Electronics, University of Shanghai for Science and Technology, Shanghai 200093, China)
Abstract: The paper introduces the principle of laser particle sizer and the application of threads in laser particle sizer based on USB.
Key words: laser particle sizer; USB; threads; data collection
1系統(tǒng)原理結(jié)構(gòu)與數(shù)據(jù)采集卡
1.1系統(tǒng)原理與結(jié)構(gòu)
系統(tǒng)原理結(jié)構(gòu)圖如圖1所示。由激光器發(fā)出的光束經(jīng)空間濾波器擴(kuò)束成平行單色光。當(dāng)該平行光照射在測(cè)量區(qū)中的顆粒群時(shí)便產(chǎn)生光的衍射現(xiàn)象。衍射散射光的強(qiáng)度分布與測(cè)量區(qū)中被照射的顆粒直徑、顆粒數(shù)有關(guān)。衍射光被接收透鏡聚焦在半圓多元光電探測(cè)器上。此探測(cè)器將含有顆粒直徑和顆粒數(shù)信息的衍射光信號(hào)轉(zhuǎn)換成相應(yīng)的電信號(hào),經(jīng)信號(hào)前置處理電路及USB數(shù)據(jù)采集卡轉(zhuǎn)換成數(shù)字信號(hào)送入PC機(jī)計(jì)算處理,得到顆粒的粒度分布和濃度情況。
1.2數(shù)據(jù)采集卡簡(jiǎn)介
本系統(tǒng)采用某公司的USB2002型數(shù)據(jù)采集卡。主要性能指標(biāo)如下:(a)模擬電壓輸入范圍:±5V,±10V;(b)A/D轉(zhuǎn)換分辨率:14Bit,32K字FIFO存儲(chǔ)器;(c)32路單端模擬信號(hào)輸入;16路雙端模擬信號(hào)輸入;(d)轉(zhuǎn)換速率:400kHz;(c)程控增益(×1、2、4、8)。
2系統(tǒng)的軟件實(shí)現(xiàn)
2.1線程
線程指的是程序代碼的執(zhí)行途徑外加一組操作系統(tǒng)分配的資源(堆棧、寄存器狀態(tài)等等)。線程一般分為用戶界面線程和工作者線程兩類,用戶界面線程可以創(chuàng)建窗口并處理發(fā)送給這些窗口的消息;工作者線程執(zhí)行后臺(tái)任務(wù),因其不接受用戶的直接輸入,所以不需要窗口和消息循環(huán)。線程的應(yīng)用可以提高CPU的利用率,提高程序的響應(yīng)能力,降低系統(tǒng)對(duì)數(shù)據(jù)采集速度的影響。
2.2系統(tǒng)軟件實(shí)現(xiàn)
2.2.1軟件組成
程序主要由兩部分組成,一是數(shù)據(jù)采集部分,另一部分為數(shù)據(jù)處理部分(見(jiàn)圖2)。數(shù)據(jù)采集部分對(duì)USB數(shù)據(jù)采集卡進(jìn)行系統(tǒng)初始化、數(shù)據(jù)讀取并存入數(shù)據(jù)緩沖區(qū)及釋放系統(tǒng)資源停止數(shù)據(jù)采集等工作。數(shù)據(jù)處理部分進(jìn)行原始數(shù)據(jù)的存儲(chǔ)、數(shù)據(jù)計(jì)算、各個(gè)通道數(shù)據(jù)的數(shù)值和直方圖實(shí)時(shí)顯示以及獲取各通道中的最大值為采集卡程控增益的設(shè)置提供依據(jù)。由于后者進(jìn)行的數(shù)據(jù)計(jì)算和圖形操作,需消耗CPU很多時(shí)間,在單線程的情況下將會(huì)阻塞主線程運(yùn)行,出現(xiàn)采集數(shù)據(jù)溢出丟失的現(xiàn)象。
為此采用基于線程的多任務(wù)編程方法。
2.2.2數(shù)據(jù)采集線程
將數(shù)據(jù)采集部分定義為工作者線程(數(shù)據(jù)采集線程)。USB設(shè)備與AD轉(zhuǎn)換進(jìn)度同步完全由硬件和驅(qū)動(dòng)程序自動(dòng)完成。用戶若要用程序方式實(shí)現(xiàn)連續(xù)數(shù)據(jù)采集,對(duì)其軟件實(shí)現(xiàn)就顯得極為容易。數(shù)據(jù)采集線程每次用ReadDeviceAD函數(shù)(USB采集卡接口函數(shù))讀取AD數(shù)據(jù)時(shí),設(shè)備驅(qū)動(dòng)程序會(huì)按照AD轉(zhuǎn)換進(jìn)度將AD數(shù)據(jù)一一放進(jìn)用戶數(shù)據(jù)緩沖區(qū);當(dāng)完成該次所指定的采樣點(diǎn)數(shù)時(shí),便會(huì)返回;當(dāng)再次用這個(gè)函數(shù)讀取數(shù)據(jù)時(shí),會(huì)接著上一次的位置傳遞數(shù)據(jù)到用戶數(shù)據(jù)緩沖區(qū)。高速數(shù)據(jù)采集要求每?jī)纱握{(diào)用ReadDeviceAD之間的時(shí)間間隔越短越好。由圖3數(shù)據(jù)采集線程流程圖可知,為保證每?jī)纱蜶eadDeviceAD之間較小的時(shí)間間隔,應(yīng)盡量減少USB設(shè)備AD初始化的次數(shù)。為此,采用了一次性設(shè)置增益的方法。即根據(jù)所采信號(hào)大小和對(duì)應(yīng)的原增益計(jì)算出原始信號(hào)大小,然后根據(jù)信號(hào)應(yīng)放大的數(shù)值換算出合適的增益進(jìn)行一次設(shè)置。另外,設(shè)置了一個(gè)布爾控制變量(ParaChange)來(lái)記錄增益是否被剛剛改變,如果剛剛改變就跳過(guò)增益是否應(yīng)該改變(ADPARA)的判斷直接讀取采集數(shù)據(jù)從而減少讀取采集數(shù)據(jù)時(shí)間間隔,以利于高速采集。圖3中Runstatus為數(shù)據(jù)采集線程運(yùn)行控制布爾變量。
2.2.3數(shù)據(jù)處理線程
將數(shù)據(jù)處理部分定義為數(shù)據(jù)處理線程,以便處理圖形操作及數(shù)據(jù)處理等較耗時(shí)的工作。最初,數(shù)據(jù)處理線程不做任何工作,而是在Win32API函數(shù)WaitForSingleObject的作用下進(jìn)入睡眠狀態(tài)(見(jiàn)圖2),此時(shí)它不消耗CPU任何時(shí)間,可保證數(shù)據(jù)采集線程代碼有充分的運(yùn)行機(jī)會(huì)。當(dāng)數(shù)據(jù)采集線程取得指定長(zhǎng)度的數(shù)據(jù)到用戶空間時(shí),再用Win32API函數(shù)SetEvent將指定事件消息發(fā)送給數(shù)據(jù)處理線程,則數(shù)據(jù)處理線程即刻恢復(fù)運(yùn)行狀態(tài),迅速對(duì)這批數(shù)據(jù)進(jìn)行處理。
2.2.4數(shù)據(jù)緩沖隊(duì)列
數(shù)據(jù)處理線程可能處理花費(fèi)CPU過(guò)多時(shí)間的工作,從而導(dǎo)致數(shù)據(jù)處理線程阻塞;而數(shù)據(jù)采集線程則在不停地采集數(shù)據(jù),這樣數(shù)據(jù)處理線程很有可能因此而丟失數(shù)據(jù)采集線程發(fā)來(lái)的某一段數(shù)據(jù)。為避免這個(gè)問(wèn)題,建立了數(shù)據(jù)緩沖隊(duì)列。即假設(shè)數(shù)據(jù)采集線程每一次從設(shè)備上取出8K數(shù)據(jù),那么就創(chuàng)建一個(gè)緩沖隊(duì)列,在用戶程序中開(kāi)辟一個(gè)兩維數(shù)組,如Buffe(Count??1,DataLen??1),將DataLen視為數(shù)據(jù)采集線程每次采集的數(shù)據(jù)長(zhǎng)度(DataLen必須等于采集通道數(shù)的整數(shù)倍),從而保證采集數(shù)據(jù)與各通道的一一對(duì)應(yīng)關(guān)系。另外,也要注意在USB采集卡每次增益改變時(shí)要保證數(shù)據(jù)采集線程和數(shù)據(jù)處理線程從第一個(gè)緩沖隊(duì)列的第一數(shù)據(jù)存儲(chǔ)和讀取。這可以保證采集數(shù)據(jù)與各通道的一一對(duì)應(yīng)關(guān)系,以防止數(shù)據(jù)錯(cuò)位。Count則為緩沖隊(duì)列的成員個(gè)數(shù)。應(yīng)根據(jù)計(jì)算機(jī)物理內(nèi)存大小和總體使用情況來(lái)設(shè)定。假如設(shè)成32,則這個(gè)緩沖隊(duì)列實(shí)際上就是數(shù)組Buffer(31,8191)的形式,共32個(gè)緩沖隊(duì)列(數(shù)組各維的基為0)。它跟一個(gè)普通的緩沖區(qū),如一維數(shù)組差不多,唯一不同是,兩個(gè)線程首先要通過(guò)改變Count字段的值,即Count的索引值(ReadIndex或ProcIndex)來(lái)填充和引用某一段DataLen長(zhǎng)度的數(shù)據(jù)緩沖區(qū)。需要注意的是,兩個(gè)線程不共用一個(gè)Count的索引值。具體情況(見(jiàn)圖4)是當(dāng)數(shù)據(jù)采集線程在AD部件被初始化之后,首次采集數(shù)據(jù)時(shí),則將自己的ReadIndex下標(biāo)置為0,即用第一個(gè)緩沖區(qū)采集AD數(shù)據(jù)。當(dāng)采集完后,則向數(shù)據(jù)處理線程發(fā)送消息,且兩個(gè)線程的公共變量Segments加1(Segments變量記錄當(dāng)前時(shí)刻緩沖隊(duì)列中有多少個(gè)已被數(shù)據(jù)采集線程使用了,但是卻沒(méi)被數(shù)據(jù)處理線程處理掉的緩沖區(qū)數(shù)量。)然后再接著將ReadIndex偏移至1,再用第二個(gè)緩沖區(qū)采集數(shù)據(jù)。再將Segments加1,至到Readlndex等于32為止,然后再回到0位置,重新開(kāi)始。而數(shù)據(jù)處理線程則在每次接受到消息時(shí)判斷有多少由于自己被堵塞而沒(méi)有被處理的緩沖區(qū)個(gè)數(shù),然后逐一進(jìn)行處理,最后再?gòu)腟egments變量中減去在所接受到的當(dāng)前事件下所處理的緩沖區(qū)個(gè)數(shù)。因此,即便是數(shù)據(jù)處理線程由于系統(tǒng)的偶爾繁忙而被堵塞,也很難使數(shù)據(jù)丟失。而且,通過(guò)這種方案,用戶還可以在數(shù)據(jù)采集線程中對(duì)Segments加以判斷,觀察其值是否大于32,如果大于,則緩沖區(qū)隊(duì)列肯定因數(shù)據(jù)處理線程的堵塞而被溢出;如果溢出則報(bào)警。因此,具有強(qiáng)大的容錯(cuò)處理能力。
3結(jié)束語(yǔ)
本文介紹了線程編程方法在激光粒度儀數(shù)據(jù)采集中的應(yīng)用。經(jīng)實(shí)驗(yàn)驗(yàn)證,采集速度能滿足設(shè)計(jì)要求,而且,獲得了理想的測(cè)量標(biāo)準(zhǔn)粒子的測(cè)量結(jié)果。