VxWorks下AD/DA驅(qū)動(dòng)系統(tǒng)設(shè)計(jì)及測(cè)試
相對(duì)于其他嵌入式操作系統(tǒng),VxWorks以其高可靠性、微內(nèi)核、可裁減性以及高效的硬實(shí)時(shí)任務(wù)調(diào)度、中斷管理等優(yōu)點(diǎn),被廣泛地應(yīng)用在通信、軍事、航空、航天等高精尖技術(shù)和實(shí)時(shí)性要求極高的領(lǐng)域[1]。工程中實(shí)際應(yīng)用的嵌入式系統(tǒng)通常包括以下幾個(gè)部分:串口、并口、CAN總線和AD/DA等。對(duì)于前三種嵌入式硬件,VxWorks內(nèi)核本身已提供了完備的驅(qū)動(dòng)支持并給出了相應(yīng)驅(qū)動(dòng)的參考例程,但目前還未包括對(duì)A/D及D/A設(shè)備的支持;此外,由于相關(guān)技術(shù)資料的保密性,相應(yīng)驅(qū)動(dòng)設(shè)計(jì)的參考文獻(xiàn)也較少。因此,本文結(jié)合實(shí)際系統(tǒng)需要(利用12位D/A輸出可調(diào)模擬量控制電機(jī)轉(zhuǎn)速,利用12位A/D對(duì)壓電陀螺所敏感的電機(jī)轉(zhuǎn)速進(jìn)行數(shù)據(jù)采集),對(duì)AD/DA設(shè)備的驅(qū)動(dòng)進(jìn)行了相關(guān)研究,研究結(jié)果具有實(shí)際工程應(yīng)用價(jià)值。
本文在簡(jiǎn)要分析了VxWorks I/O系統(tǒng)及設(shè)備驅(qū)動(dòng)基礎(chǔ)之上,將A/D與D/A兩者整合為一個(gè)完整的字符設(shè)備掛接到VxWorks的I/O系統(tǒng)中,成功實(shí)現(xiàn)了該設(shè)備的硬件驅(qū)動(dòng)并附上對(duì)應(yīng)的核心驅(qū)動(dòng)代碼,最后在驅(qū)動(dòng)程序測(cè)試過(guò)程中簡(jiǎn)要說(shuō)明了應(yīng)用層軟件的設(shè)計(jì)方法,為工程應(yīng)用提供了完善的解決辦法。
1 VxWorks I/O系統(tǒng)與設(shè)備驅(qū)動(dòng)
了解和掌握VxWorks的I/O系統(tǒng)及設(shè)備的驅(qū)動(dòng)結(jié)構(gòu),是成功設(shè)計(jì)AD/DA設(shè)備驅(qū)動(dòng)的前提和基礎(chǔ)。具體來(lái)說(shuō):VxWorks是一個(gè)層次化分明的操作系統(tǒng),每層各負(fù)其責(zé),層與層之間又緊密相連。通常所說(shuō)的驅(qū)動(dòng)程序?qū)儆诘讓拥姆懂?,而用戶的?yīng)用程序則屬于上層,位于這兩層之間的是中間層,無(wú)需用戶開(kāi)發(fā),由VxWorks進(jìn)行維護(hù)和管理。這樣,操作系統(tǒng)把各層有機(jī)地連接在一起,使代碼緊湊而高效。VxWorks的I/O系統(tǒng)正是這樣的中間層,以本文所要研究的AD/DA驅(qū)動(dòng)系統(tǒng)設(shè)計(jì)為例,圖1詳細(xì)介紹了三者的關(guān)系。
圖1中的最底層就是所要編寫的設(shè)備驅(qū)動(dòng)程序,包括對(duì)具體硬件的初始化和各種操作,以及與上層I/O系統(tǒng)的接口;中間層為I/O系統(tǒng)層,VxWorks的I/O系統(tǒng)不但向上提供了7個(gè)基本的I/O接口,以供應(yīng)用程序調(diào)用,而且還向下提供與各種設(shè)備驅(qū)動(dòng)程序的接口;最頂層為應(yīng)用層,用戶根據(jù)實(shí)際應(yīng)用需要編寫應(yīng)用程序,并通過(guò)應(yīng)用程序向下調(diào)用I/O系統(tǒng)。與UNIX類似,VxWorks所有的I/O設(shè)備都被當(dāng)作文件來(lái)存取。關(guān)于VxWorks I/O系統(tǒng)驅(qū)動(dòng)機(jī)制的更多內(nèi)容請(qǐng)參考文獻(xiàn)[2][3]。
針對(duì)系統(tǒng)需要,選擇7個(gè)基本I/O接口函數(shù)中的open()、read()、write()以及ioctl()進(jìn)行驅(qū)動(dòng)系統(tǒng)設(shè)計(jì),各層函數(shù)與相應(yīng)實(shí)現(xiàn)的功能對(duì)應(yīng)關(guān)系如表1所示。
此外,D/A輸出通道在應(yīng)用程序中選擇,下面給出AD/DA驅(qū)動(dòng)系統(tǒng)的具體設(shè)計(jì)過(guò)程。
2 AD/DA驅(qū)動(dòng)系統(tǒng)設(shè)計(jì)
2.1 驅(qū)動(dòng)系統(tǒng)開(kāi)發(fā)環(huán)境
與其他嵌入式系統(tǒng)開(kāi)發(fā)類似,VxWorks也采用主機(jī)-目標(biāo)機(jī)模式[4],如圖2所示。
硬件平臺(tái)中主機(jī)使用CPU為迅馳的PC機(jī),運(yùn)行VxWorks開(kāi)發(fā)環(huán)境Tornado2.2;目標(biāo)機(jī)依照系統(tǒng)應(yīng)用要求選用基于PC104 總線的嵌入式CPU卡MSMP586SEV,該CPU是VxWorks所支持的Intel x86系列CPU。VxWorks自帶的板級(jí)支持包(BSP)支持該CPU,使得在驅(qū)動(dòng)開(kāi)發(fā)過(guò)程中無(wú)須過(guò)多考慮CPU部分的代碼設(shè)置。外擴(kuò)AD/DA采用的同樣是PC104總線的數(shù)據(jù)轉(zhuǎn)換卡ADT-650。開(kāi)發(fā)調(diào)試過(guò)程中,主機(jī)通過(guò)網(wǎng)絡(luò)方式下載VxWorks映像至目標(biāo)機(jī)中,目標(biāo)機(jī)設(shè)定為CF卡啟動(dòng)。
2.2 PC104-AD/DA卡硬件結(jié)構(gòu)[5]
PC104-AD/DA卡主要由A/D轉(zhuǎn)換控制器(AD1674)和D/A轉(zhuǎn)換控制器(ADC7724)兩個(gè)核心器件組成,可提供的硬件資源為12位分辨率的8通道A/D轉(zhuǎn)換和同分辨率的4通道D/A轉(zhuǎn)換;CPU卡通過(guò)I/O映射方式對(duì)其進(jìn)行訪問(wèn),可通過(guò)硬件開(kāi)關(guān)選通該卡的I/O映射基地址,為了避免與其他器件地址沖突,在此選擇其基地址為:BA=0x240(可根據(jù)實(shí)際情況選擇),其余各寄存器采用偏移地址訪問(wèn)的方式。為便于后續(xù)說(shuō)明,簡(jiǎn)要將卡上其他寄存器地址及功能列于表2。
在傳統(tǒng)非嵌入式實(shí)時(shí)操作系統(tǒng)(比如DOS)下應(yīng)用該卡,實(shí)際上是在應(yīng)用程序中對(duì)板卡進(jìn)行初始化和設(shè)置相應(yīng)功能寄存器以完成硬件功能。但由前面對(duì)VxWorks的I/O系統(tǒng)和設(shè)備驅(qū)動(dòng)結(jié)構(gòu)分析可知,該部分工作在VxWorks操作系統(tǒng)下由底層硬件驅(qū)動(dòng)完成,應(yīng)用程序中通過(guò)調(diào)用相應(yīng)I/O接口函數(shù)來(lái)實(shí)現(xiàn)硬件功能,由此實(shí)現(xiàn)分層結(jié)構(gòu)以達(dá)到隔離硬件的目的。因此,AD/DA驅(qū)動(dòng)的開(kāi)發(fā)就是依照I/O系統(tǒng)傳遞過(guò)來(lái)的應(yīng)用層各調(diào)用接口函數(shù)完成對(duì)相應(yīng)寄存器的不同設(shè)置。
2.3 AD/DA驅(qū)動(dòng)程序?qū)崿F(xiàn)
AD/DA驅(qū)動(dòng)的實(shí)現(xiàn)方式主要是完成以下6個(gè)函數(shù)的編寫:
設(shè)備驅(qū)動(dòng)程序安裝函數(shù)adcDrv();設(shè)備創(chuàng)建函數(shù)adcDevCreate();設(shè)備打開(kāi)函數(shù)adcOpen();設(shè)備讀函數(shù)(A/D轉(zhuǎn)換) adcRead();設(shè)備寫函數(shù)(D/A轉(zhuǎn)換)adcWrite();I/O控制函數(shù)adIoctl()。
其中前三個(gè)函數(shù)的設(shè)計(jì)與具體硬件關(guān)聯(lián)較少,與VxWorks下其他字符型設(shè)備驅(qū)動(dòng)開(kāi)發(fā)基本類似,不做過(guò)多介紹,僅需按照標(biāo)準(zhǔn)代碼形式編寫即可,具體詳細(xì)代碼可見(jiàn)參考文獻(xiàn)[6]。下面詳細(xì)介紹A/D轉(zhuǎn)換驅(qū)動(dòng)、D/A轉(zhuǎn)換驅(qū)動(dòng)以及設(shè)備控制驅(qū)動(dòng)等部分的程序設(shè)計(jì),給出核心代碼。
2.3.1 A/D轉(zhuǎn)換驅(qū)動(dòng)
A/D轉(zhuǎn)換驅(qū)動(dòng)實(shí)際是完成adcRead()函數(shù)的編寫,在該函數(shù)編寫之前,首先應(yīng)明確A/D轉(zhuǎn)換驅(qū)動(dòng)實(shí)現(xiàn)過(guò)程:當(dāng)應(yīng)用程序調(diào)用read()函數(shù)時(shí),VxWorks的I/O系統(tǒng)將調(diào)用底層驅(qū)動(dòng)adcRead()函數(shù),該函數(shù)隨即依照程序設(shè)定對(duì)表2所列卡上各相關(guān)寄存器進(jìn)行設(shè)置來(lái)實(shí)現(xiàn)A/D轉(zhuǎn)換的硬件功能,從而實(shí)現(xiàn)底層驅(qū)動(dòng)。
A/D轉(zhuǎn)換驅(qū)動(dòng)具體實(shí)現(xiàn)的核心代碼如下(偽指令為代碼說(shuō)明,以下同):
int adcRead(int adcDevId,char *pBuf,int nBytes)
{…/*觸發(fā)AD轉(zhuǎn)換*/
sysOutByte(BA+0, 0x00);
while(1)
{/*判斷AD轉(zhuǎn)換狀態(tài)*/
status=sysInByte(BA+5);
if((status0x01)==0)
{
/*存儲(chǔ)A/D轉(zhuǎn)換結(jié)果*/
pBuf[1]=sysInByte(BA+0);
pBuf[2]=sysInByte(BA+1);
…
}
}
}
首先選擇一個(gè)輸入通道(通過(guò)ioctl選擇)并觸發(fā)A/D轉(zhuǎn)換,隨后查詢A/D轉(zhuǎn)換狀態(tài)信息直到A/D轉(zhuǎn)換過(guò)程結(jié)束,最終將轉(zhuǎn)換結(jié)果保存在pBuf[]數(shù)組中傳送到應(yīng)用層,應(yīng)用程序使用得到的數(shù)字量信息,至此,A/D驅(qū)動(dòng)完畢。其中sysOutByte()和sysInByte()為VxWorks下對(duì)寄存器操作的標(biāo)準(zhǔn)函數(shù)。
2.3.2 D/A轉(zhuǎn)換驅(qū)動(dòng)
與上述驅(qū)動(dòng)實(shí)現(xiàn)過(guò)程類似,D/A轉(zhuǎn)換驅(qū)動(dòng)是完成對(duì)adcWrite()函數(shù)的編寫,轉(zhuǎn)換過(guò)程是A/D轉(zhuǎn)換的逆過(guò)程,由于其不涉及查詢判斷,代碼相對(duì)簡(jiǎn)化。D/A轉(zhuǎn)換驅(qū)動(dòng)具體實(shí)現(xiàn)的核心代碼如下:
int adcWrite(int adcDevId, char *pBuf,int nBytes)
{…/*將數(shù)據(jù)寫入緩沖區(qū)*/
sysOutByte(BA+2, pBuf[2]);
sysOutByte(BA+1, pBuf[1]);
…
}
首先將應(yīng)用程序中設(shè)定的待轉(zhuǎn)換數(shù)字量的低4位和高8位分別存放在pBuf[1]、pBuf[2]中,隨后依照先高后低的順序?qū)懭隓/A轉(zhuǎn)換緩沖區(qū)內(nèi),當(dāng)?shù)臀粩?shù)據(jù)寫入完成后,硬件將自動(dòng)開(kāi)始更新D/A輸出的模擬量,至此,D/A驅(qū)動(dòng)完畢。需要說(shuō)明的是:D/A通道選擇是在應(yīng)用程序中的編碼過(guò)程中實(shí)現(xiàn)的。
2.3.3 設(shè)備控制驅(qū)動(dòng)
設(shè)備控制驅(qū)動(dòng)用于完成A/D通道選擇,實(shí)現(xiàn)過(guò)程是對(duì)BA+3寄存器進(jìn)行設(shè)置,當(dāng)該寄存器高低位不同時(shí),通道進(jìn)行自動(dòng)掃描,每當(dāng)AD轉(zhuǎn)換完成時(shí)切換到下一個(gè)通道。以控制A/D對(duì)通道0至通道3循環(huán)掃描為例,具體代碼如下:
int adcIoctl(int adcDevId, int cmd, int arg)
{…/*CH30控制字控制通道0-3轉(zhuǎn)換*/
case CH30:
sysOutByte(BA+3, 0x30);
…
}
通過(guò)定義控制參數(shù)CH30,實(shí)現(xiàn)通道掃描的范圍為0、1、2、3、0、1、2、3……,利用該方法的好處是可以省去置通道的軟件操作時(shí)間,這個(gè)功能在高速多通道切換時(shí)起很關(guān)鍵作用,同樣可定義其他通道的控制參數(shù),如CH20、CH00等等。
3 應(yīng)用及測(cè)試
為了驗(yàn)證上面所設(shè)計(jì)的驅(qū)動(dòng)系統(tǒng)的有效性,文章對(duì)其進(jìn)行了詳細(xì)的實(shí)驗(yàn)驗(yàn)證。針對(duì)本系統(tǒng)而言,D/A能將電機(jī)轉(zhuǎn)速控制數(shù)字量轉(zhuǎn)換為相應(yīng)的模擬電壓量輸出至電機(jī),并且在控制電機(jī)運(yùn)轉(zhuǎn)的同時(shí),還能利用A/D將壓電陀螺敏感到的電機(jī)轉(zhuǎn)速所輸出的模擬電壓量轉(zhuǎn)換為數(shù)字量后并采集,以此證明驅(qū)動(dòng)系統(tǒng)設(shè)計(jì)是成功的。下面詳細(xì)給出實(shí)際工程中用于測(cè)試驅(qū)動(dòng)程序設(shè)計(jì)成功的應(yīng)用程序。
3.1 應(yīng)用程序設(shè)計(jì)
首先調(diào)用adcDrv()和adcDevCreat()初始化驅(qū)動(dòng)并創(chuàng)建AD/DA設(shè)備;并通過(guò)fd=open('/adc',O_RDWR,0)操作打開(kāi)設(shè)備。這樣,系統(tǒng)為AD/DA卡分配了一個(gè)文件描述符fd,通過(guò)讀寫該描述符操作即可完成相應(yīng)AD/DA變換。
隨后發(fā)起兩個(gè)任務(wù)[7][8]:寫任務(wù)和讀任務(wù),分別完成上述D/A與A/D的功能。兩個(gè)任務(wù)的核心代碼如下:
int Dac()
{…
pBuf[0]=xxx;
pBuf[1]=xxx;
t1=write(fd,pBuf[0],2);
…
}
int Adc()
{…
ioctl(fd,CH00,0);
t2=read(fd,pBuf[0],2);
LSB=pBuf[0];
MSB=pBuf[1];
…
}
3.2 測(cè)試結(jié)果
在WinShell下通過(guò)調(diào)用iosDevShow()函數(shù)可以看到,名為/adc的AD/DA卡設(shè)備已經(jīng)被VxWorks操作系統(tǒng)正確識(shí)別,如圖3所示。
測(cè)試分為兩個(gè)步驟來(lái)驗(yàn)證A/D及D/A驅(qū)動(dòng)的正確性:
步驟1:數(shù)字量→模擬量→電機(jī)轉(zhuǎn)速(D/A)
步驟2:電機(jī)轉(zhuǎn)速→模擬量→數(shù)字量(A/D)
步驟1控制電機(jī)加減速過(guò)程當(dāng)中,給定的控制電機(jī)運(yùn)轉(zhuǎn)的數(shù)字量如圖4中data1所示(其中:data1是通過(guò)16進(jìn)制數(shù)轉(zhuǎn)換為10進(jìn)制數(shù)實(shí)現(xiàn)的)。每隔0.5s對(duì)系統(tǒng)進(jìn)行一次D/A轉(zhuǎn)換,得到電機(jī)實(shí)際轉(zhuǎn)速rate如圖5所示。
對(duì)比data1和rate,兩條曲線規(guī)律一致,說(shuō)明D/A驅(qū)動(dòng)功能正常。
隨后將圖5中的電機(jī)轉(zhuǎn)速作為輸入量,輸入到步驟2中進(jìn)行實(shí)驗(yàn),以相同時(shí)間間隔對(duì)系統(tǒng)進(jìn)行A/D采樣,轉(zhuǎn)換后的數(shù)字量如圖4中data2所示,對(duì)比data2和rate,兩條曲線規(guī)律一致,說(shuō)明A/D驅(qū)動(dòng)功能正常。
data1與data2兩條曲線基本重合,二者之間的誤差曲線error(data1-data2)如圖6。
由圖6可得:誤差最大值為3.2LSB,最小為2.1LSB。由此可見(jiàn),AD/DA功能實(shí)現(xiàn)的同時(shí)精度完全符合要求(4LSB≥error≥2LSB)。實(shí)驗(yàn)結(jié)果表明:驅(qū)動(dòng)系統(tǒng)設(shè)計(jì)成功有效。
本文介紹了VxWorks下AD/DA驅(qū)動(dòng)的開(kāi)發(fā)過(guò)程,給出了驅(qū)動(dòng)中的核心代碼。同時(shí)在對(duì)驅(qū)動(dòng)程序進(jìn)行測(cè)試的過(guò)程中說(shuō)明了部分應(yīng)用程序的設(shè)計(jì)。測(cè)試結(jié)果表明,所開(kāi)發(fā)的驅(qū)動(dòng)系統(tǒng)滿足實(shí)際需要(12位AD/DA轉(zhuǎn)換分辨率),可在實(shí)際工程中應(yīng)用。限于篇幅本文未能給出全部代碼,但文中驅(qū)動(dòng)程序的設(shè)計(jì)是完全依照VxWorks的標(biāo)準(zhǔn)I/O機(jī)制實(shí)現(xiàn)的,具有普遍的指導(dǎo)意義,可為VxWorks下其他字符型設(shè)備驅(qū)動(dòng)開(kāi)發(fā)提供參考。
評(píng)論