摘 要:在簡要介紹基于USB接口激光粒度儀的工作原理的基礎(chǔ)上,著重講述線程方法在此系統(tǒng)中的應(yīng)用。
關(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)該平行光照射在測量區(qū)中的顆粒群時便產(chǎn)生光的衍射現(xiàn)象。衍射散射光的強(qiáng)度分布與測量區(qū)中被照射的顆粒直徑、顆粒數(shù)有關(guān)。衍射光被接收透鏡聚焦在半圓多元光電探測器上。此探測器將含有顆粒直徑和顆粒數(shù)信息的衍射光信號轉(zhuǎn)換成相應(yīng)的電信號,經(jīng)信號前置處理電路及USB數(shù)據(jù)采集卡轉(zhuǎn)換成數(shù)字信號送入PC機(jī)計算處理,得到顆粒的粒度分布和濃度情況。

1.2數(shù)據(jù)采集卡簡介
本系統(tǒng)采用某公司的USB2002型數(shù)據(jù)采集卡。主要性能指標(biāo)如下:(a)模擬電壓輸入范圍:±5V,±10V;(b)A/D轉(zhuǎn)換分辨率:14Bit,32K字FIFO存儲器;(c)32路單端模擬信號輸入;16路雙端模擬信號輸入;(d)轉(zhuǎn)換速率:400kHz;(c)程控增益(×1、2、4、8)。
2系統(tǒng)的軟件實現(xiàn)
2.1線程
線程指的是程序代碼的執(zhí)行途徑外加一組操作系統(tǒng)分配的資源(堆棧、寄存器狀態(tài)等等)。線程一般分為用戶界面線程和工作者線程兩類,用戶界面線程可以創(chuàng)建窗口并處理發(fā)送給這些窗口的消息;工作者線程執(zhí)行后臺任務(wù),因其不接受用戶的直接輸入,所以不需要窗口和消息循環(huán)。線程的應(yīng)用可以提高CPU的利用率,提高程序的響應(yīng)能力,降低系統(tǒng)對數(shù)據(jù)采集速度的影響。
2.2系統(tǒng)軟件實現(xiàn)
2.2.1軟件組成
程序主要由兩部分組成,一是數(shù)據(jù)采集部分,另一部分為數(shù)據(jù)處理部分(見圖2)。數(shù)據(jù)采集部分對USB數(shù)據(jù)采集卡進(jìn)行系統(tǒng)初始化、數(shù)據(jù)讀取并存入數(shù)據(jù)緩沖區(qū)及釋放系統(tǒng)資源停止數(shù)據(jù)采集等工作。數(shù)據(jù)處理部分進(jìn)行原始數(shù)據(jù)的存儲、數(shù)據(jù)計算、各個通道數(shù)據(jù)的數(shù)值和直方圖實時顯示以及獲取各通道中的最大值為采集卡程控增益的設(shè)置提供依據(jù)。由于后者進(jìn)行的數(shù)據(jù)計算和圖形操作,需消耗CPU很多時間,在單線程的情況下將會阻塞主線程運行,出現(xiàn)采集數(shù)據(jù)溢出丟失的現(xiàn)象。
為此采用基于線程的多任務(wù)編程方法。
2.2.2數(shù)據(jù)采集線程
將數(shù)據(jù)采集部分定義為工作者線程(數(shù)據(jù)采集線程)。USB設(shè)備與AD轉(zhuǎn)換進(jìn)度同步完全由硬件和驅(qū)動程序自動完成。用戶若要用程序方式實現(xiàn)連續(xù)數(shù)據(jù)采集,對其軟件實現(xiàn)就顯得極為容易。數(shù)據(jù)采集線程每次用ReadDeviceAD函數(shù)(USB采集卡接口函數(shù))讀取AD數(shù)據(jù)時,設(shè)備驅(qū)動程序會按照AD轉(zhuǎn)換進(jìn)度將AD數(shù)據(jù)一一放進(jìn)用戶數(shù)據(jù)緩沖區(qū);當(dāng)完成該次所指定的采樣點數(shù)時,便會返回;當(dāng)再次用這個函數(shù)讀取數(shù)據(jù)時,會接著上一次的位置傳遞數(shù)據(jù)到用戶數(shù)據(jù)緩沖區(qū)。高速數(shù)據(jù)采集要求每兩次調(diào)用ReadDeviceAD之間的時間間隔越短越好。由圖3數(shù)據(jù)采集線程流程圖可知,為保證每兩次ReadDeviceAD之間較小的時間間隔,應(yīng)盡量減少USB設(shè)備AD初始化的次數(shù)。為此,采用了一次性設(shè)置增益的方法。即根據(jù)所采信號大小和對應(yīng)的原增益計算出原始信號大小,然后根據(jù)信號應(yīng)放大的數(shù)值換算出合適的增益進(jìn)行一次設(shè)置。另外,設(shè)置了一個布爾控制變量(ParaChange)來記錄增益是否被剛剛改變,如果剛剛改變就跳過增益是否應(yīng)該改變(ADPARA)的判斷直接讀取采集數(shù)據(jù)從而減少讀取采集數(shù)據(jù)時間間隔,以利于高速采集。圖3中Runstatus為數(shù)據(jù)采集線程運行控制布爾變量。

2.2.3數(shù)據(jù)處理線程
將數(shù)據(jù)處理部分定義為數(shù)據(jù)處理線程,以便處理圖形操作及數(shù)據(jù)處理等較耗時的工作。最初,數(shù)據(jù)處理線程不做任何工作,而是在Win32API函數(shù)WaitForSingleObject的作用下進(jìn)入睡眠狀態(tài)(見圖2),此時它不消耗CPU任何時間,可保證數(shù)據(jù)采集線程代碼有充分的運行機(jī)會。當(dāng)數(shù)據(jù)采集線程取得指定長度的數(shù)據(jù)到用戶空間時,再用Win32API函數(shù)SetEvent將指定事件消息發(fā)送給數(shù)據(jù)處理線程,則數(shù)據(jù)處理線程即刻恢復(fù)運行狀態(tài),迅速對這批數(shù)據(jù)進(jìn)行處理。
2.2.4數(shù)據(jù)緩沖隊列
數(shù)據(jù)處理線程可能處理花費CPU過多時間的工作,從而導(dǎo)致數(shù)據(jù)處理線程阻塞;而數(shù)據(jù)采集線程則在不停地采集數(shù)據(jù),這樣數(shù)據(jù)處理線程很有可能因此而丟失數(shù)據(jù)采集線程發(fā)來的某一段數(shù)據(jù)。為避免這個問題,建立了數(shù)據(jù)緩沖隊列。即假設(shè)數(shù)據(jù)采集線程每一次從設(shè)備上取出8K數(shù)據(jù),那么就創(chuàng)建一個緩沖隊列,在用戶程序中開辟一個兩維數(shù)組,如Buffe(Count??1,DataLen??1),將DataLen視為數(shù)據(jù)采集線程每次采集的數(shù)據(jù)長度(DataLen必須等于采集通道數(shù)的整數(shù)倍),從而保證采集數(shù)據(jù)與各通道的一一對應(yīng)關(guān)系。另外,也要注意在USB采集卡每次增益改變時要保證數(shù)據(jù)采集線程和數(shù)據(jù)處理線程從第一個緩沖隊列的第一數(shù)據(jù)存儲和讀取。這可以保證采集數(shù)據(jù)與各通道的一一對應(yīng)關(guān)系,以防止數(shù)據(jù)錯位。Count則為緩沖隊列的成員個數(shù)。應(yīng)根據(jù)計算機(jī)物理內(nèi)存大小和總體使用情況來設(shè)定。假如設(shè)成32,則這個緩沖隊列實際上就是數(shù)組Buffer(31,8191)的形式,共32個緩沖隊列(數(shù)組各維的基為0)。它跟一個普通的緩沖區(qū),如一維數(shù)組差不多,唯一不同是,兩個線程首先要通過改變Count字段的值,即Count的索引值(ReadIndex或ProcIndex)來填充和引用某一段DataLen長度的數(shù)據(jù)緩沖區(qū)。需要注意的是,兩個線程不共用一個Count的索引值。具體情況(見圖4)是當(dāng)數(shù)據(jù)采集線程在AD部件被初始化之后,首次采集數(shù)據(jù)時,則將自己的ReadIndex下標(biāo)置為0,即用第一個緩沖區(qū)采集AD數(shù)據(jù)。當(dāng)采集完后,則向數(shù)據(jù)處理線程發(fā)送消息,且兩個線程的公共變量Segments加1(Segments變量記錄當(dāng)前時刻緩沖隊列中有多少個已被數(shù)據(jù)采集線程使用了,但是卻沒被數(shù)據(jù)處理線程處理掉的緩沖區(qū)數(shù)量。)然后再接著將ReadIndex偏移至1,再用第二個緩沖區(qū)采集數(shù)據(jù)。再將Segments加1,至到Readlndex等于32為止,然后再回到0位置,重新開始。而數(shù)據(jù)處理線程則在每次接受到消息時判斷有多少由于自己被堵塞而沒有被處理的緩沖區(qū)個數(shù),然后逐一進(jìn)行處理,最后再從Segments變量中減去在所接受到的當(dāng)前事件下所處理的緩沖區(qū)個數(shù)。因此,即便是數(shù)據(jù)處理線程由于系統(tǒng)的偶爾繁忙而被堵塞,也很難使數(shù)據(jù)丟失。而且,通過這種方案,用戶還可以在數(shù)據(jù)采集線程中對Segments加以判斷,觀察其值是否大于32,如果大于,則緩沖區(qū)隊列肯定因數(shù)據(jù)處理線程的堵塞而被溢出;如果溢出則報警。因此,具有強(qiáng)大的容錯處理能力。
3結(jié)束語
本文介紹了線程編程方法在激光粒度儀數(shù)據(jù)采集中的應(yīng)用。經(jīng)實驗驗證,采集速度能滿足設(shè)計要求,而且,獲得了理想的測量標(biāo)準(zhǔn)粒子的測量結(jié)果。
關(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)該平行光照射在測量區(qū)中的顆粒群時便產(chǎn)生光的衍射現(xiàn)象。衍射散射光的強(qiáng)度分布與測量區(qū)中被照射的顆粒直徑、顆粒數(shù)有關(guān)。衍射光被接收透鏡聚焦在半圓多元光電探測器上。此探測器將含有顆粒直徑和顆粒數(shù)信息的衍射光信號轉(zhuǎn)換成相應(yīng)的電信號,經(jīng)信號前置處理電路及USB數(shù)據(jù)采集卡轉(zhuǎn)換成數(shù)字信號送入PC機(jī)計算處理,得到顆粒的粒度分布和濃度情況。

1.2數(shù)據(jù)采集卡簡介
本系統(tǒng)采用某公司的USB2002型數(shù)據(jù)采集卡。主要性能指標(biāo)如下:(a)模擬電壓輸入范圍:±5V,±10V;(b)A/D轉(zhuǎn)換分辨率:14Bit,32K字FIFO存儲器;(c)32路單端模擬信號輸入;16路雙端模擬信號輸入;(d)轉(zhuǎn)換速率:400kHz;(c)程控增益(×1、2、4、8)。
2系統(tǒng)的軟件實現(xiàn)
2.1線程
線程指的是程序代碼的執(zhí)行途徑外加一組操作系統(tǒng)分配的資源(堆棧、寄存器狀態(tài)等等)。線程一般分為用戶界面線程和工作者線程兩類,用戶界面線程可以創(chuàng)建窗口并處理發(fā)送給這些窗口的消息;工作者線程執(zhí)行后臺任務(wù),因其不接受用戶的直接輸入,所以不需要窗口和消息循環(huán)。線程的應(yīng)用可以提高CPU的利用率,提高程序的響應(yīng)能力,降低系統(tǒng)對數(shù)據(jù)采集速度的影響。
2.2系統(tǒng)軟件實現(xiàn)
2.2.1軟件組成
程序主要由兩部分組成,一是數(shù)據(jù)采集部分,另一部分為數(shù)據(jù)處理部分(見圖2)。數(shù)據(jù)采集部分對USB數(shù)據(jù)采集卡進(jìn)行系統(tǒng)初始化、數(shù)據(jù)讀取并存入數(shù)據(jù)緩沖區(qū)及釋放系統(tǒng)資源停止數(shù)據(jù)采集等工作。數(shù)據(jù)處理部分進(jìn)行原始數(shù)據(jù)的存儲、數(shù)據(jù)計算、各個通道數(shù)據(jù)的數(shù)值和直方圖實時顯示以及獲取各通道中的最大值為采集卡程控增益的設(shè)置提供依據(jù)。由于后者進(jìn)行的數(shù)據(jù)計算和圖形操作,需消耗CPU很多時間,在單線程的情況下將會阻塞主線程運行,出現(xiàn)采集數(shù)據(jù)溢出丟失的現(xiàn)象。
為此采用基于線程的多任務(wù)編程方法。
2.2.2數(shù)據(jù)采集線程
將數(shù)據(jù)采集部分定義為工作者線程(數(shù)據(jù)采集線程)。USB設(shè)備與AD轉(zhuǎn)換進(jìn)度同步完全由硬件和驅(qū)動程序自動完成。用戶若要用程序方式實現(xiàn)連續(xù)數(shù)據(jù)采集,對其軟件實現(xiàn)就顯得極為容易。數(shù)據(jù)采集線程每次用ReadDeviceAD函數(shù)(USB采集卡接口函數(shù))讀取AD數(shù)據(jù)時,設(shè)備驅(qū)動程序會按照AD轉(zhuǎn)換進(jìn)度將AD數(shù)據(jù)一一放進(jìn)用戶數(shù)據(jù)緩沖區(qū);當(dāng)完成該次所指定的采樣點數(shù)時,便會返回;當(dāng)再次用這個函數(shù)讀取數(shù)據(jù)時,會接著上一次的位置傳遞數(shù)據(jù)到用戶數(shù)據(jù)緩沖區(qū)。高速數(shù)據(jù)采集要求每兩次調(diào)用ReadDeviceAD之間的時間間隔越短越好。由圖3數(shù)據(jù)采集線程流程圖可知,為保證每兩次ReadDeviceAD之間較小的時間間隔,應(yīng)盡量減少USB設(shè)備AD初始化的次數(shù)。為此,采用了一次性設(shè)置增益的方法。即根據(jù)所采信號大小和對應(yīng)的原增益計算出原始信號大小,然后根據(jù)信號應(yīng)放大的數(shù)值換算出合適的增益進(jìn)行一次設(shè)置。另外,設(shè)置了一個布爾控制變量(ParaChange)來記錄增益是否被剛剛改變,如果剛剛改變就跳過增益是否應(yīng)該改變(ADPARA)的判斷直接讀取采集數(shù)據(jù)從而減少讀取采集數(shù)據(jù)時間間隔,以利于高速采集。圖3中Runstatus為數(shù)據(jù)采集線程運行控制布爾變量。

2.2.3數(shù)據(jù)處理線程
將數(shù)據(jù)處理部分定義為數(shù)據(jù)處理線程,以便處理圖形操作及數(shù)據(jù)處理等較耗時的工作。最初,數(shù)據(jù)處理線程不做任何工作,而是在Win32API函數(shù)WaitForSingleObject的作用下進(jìn)入睡眠狀態(tài)(見圖2),此時它不消耗CPU任何時間,可保證數(shù)據(jù)采集線程代碼有充分的運行機(jī)會。當(dāng)數(shù)據(jù)采集線程取得指定長度的數(shù)據(jù)到用戶空間時,再用Win32API函數(shù)SetEvent將指定事件消息發(fā)送給數(shù)據(jù)處理線程,則數(shù)據(jù)處理線程即刻恢復(fù)運行狀態(tài),迅速對這批數(shù)據(jù)進(jìn)行處理。
2.2.4數(shù)據(jù)緩沖隊列

數(shù)據(jù)處理線程可能處理花費CPU過多時間的工作,從而導(dǎo)致數(shù)據(jù)處理線程阻塞;而數(shù)據(jù)采集線程則在不停地采集數(shù)據(jù),這樣數(shù)據(jù)處理線程很有可能因此而丟失數(shù)據(jù)采集線程發(fā)來的某一段數(shù)據(jù)。為避免這個問題,建立了數(shù)據(jù)緩沖隊列。即假設(shè)數(shù)據(jù)采集線程每一次從設(shè)備上取出8K數(shù)據(jù),那么就創(chuàng)建一個緩沖隊列,在用戶程序中開辟一個兩維數(shù)組,如Buffe(Count??1,DataLen??1),將DataLen視為數(shù)據(jù)采集線程每次采集的數(shù)據(jù)長度(DataLen必須等于采集通道數(shù)的整數(shù)倍),從而保證采集數(shù)據(jù)與各通道的一一對應(yīng)關(guān)系。另外,也要注意在USB采集卡每次增益改變時要保證數(shù)據(jù)采集線程和數(shù)據(jù)處理線程從第一個緩沖隊列的第一數(shù)據(jù)存儲和讀取。這可以保證采集數(shù)據(jù)與各通道的一一對應(yīng)關(guān)系,以防止數(shù)據(jù)錯位。Count則為緩沖隊列的成員個數(shù)。應(yīng)根據(jù)計算機(jī)物理內(nèi)存大小和總體使用情況來設(shè)定。假如設(shè)成32,則這個緩沖隊列實際上就是數(shù)組Buffer(31,8191)的形式,共32個緩沖隊列(數(shù)組各維的基為0)。它跟一個普通的緩沖區(qū),如一維數(shù)組差不多,唯一不同是,兩個線程首先要通過改變Count字段的值,即Count的索引值(ReadIndex或ProcIndex)來填充和引用某一段DataLen長度的數(shù)據(jù)緩沖區(qū)。需要注意的是,兩個線程不共用一個Count的索引值。具體情況(見圖4)是當(dāng)數(shù)據(jù)采集線程在AD部件被初始化之后,首次采集數(shù)據(jù)時,則將自己的ReadIndex下標(biāo)置為0,即用第一個緩沖區(qū)采集AD數(shù)據(jù)。當(dāng)采集完后,則向數(shù)據(jù)處理線程發(fā)送消息,且兩個線程的公共變量Segments加1(Segments變量記錄當(dāng)前時刻緩沖隊列中有多少個已被數(shù)據(jù)采集線程使用了,但是卻沒被數(shù)據(jù)處理線程處理掉的緩沖區(qū)數(shù)量。)然后再接著將ReadIndex偏移至1,再用第二個緩沖區(qū)采集數(shù)據(jù)。再將Segments加1,至到Readlndex等于32為止,然后再回到0位置,重新開始。而數(shù)據(jù)處理線程則在每次接受到消息時判斷有多少由于自己被堵塞而沒有被處理的緩沖區(qū)個數(shù),然后逐一進(jìn)行處理,最后再從Segments變量中減去在所接受到的當(dāng)前事件下所處理的緩沖區(qū)個數(shù)。因此,即便是數(shù)據(jù)處理線程由于系統(tǒng)的偶爾繁忙而被堵塞,也很難使數(shù)據(jù)丟失。而且,通過這種方案,用戶還可以在數(shù)據(jù)采集線程中對Segments加以判斷,觀察其值是否大于32,如果大于,則緩沖區(qū)隊列肯定因數(shù)據(jù)處理線程的堵塞而被溢出;如果溢出則報警。因此,具有強(qiáng)大的容錯處理能力。
3結(jié)束語
本文介紹了線程編程方法在激光粒度儀數(shù)據(jù)采集中的應(yīng)用。經(jīng)實驗驗證,采集速度能滿足設(shè)計要求,而且,獲得了理想的測量標(biāo)準(zhǔn)粒子的測量結(jié)果。