摘要: 本文介紹一種基于DSP平臺(tái),以USB接口方式實(shí)現(xiàn)用于繼電器檢測(cè)與保護(hù)裝置的通信方式的實(shí)現(xiàn)。它采用Philips公司的ISP1581_BD接口芯片,實(shí)現(xiàn)DSP數(shù)據(jù)采集與PC機(jī)的高速傳輸。并介紹了在設(shè)計(jì)開(kāi)發(fā)USB外設(shè)時(shí)主機(jī)應(yīng)用程序及設(shè)備驅(qū)動(dòng)程序的方法及代碼。
關(guān)鍵詞:USB設(shè)備驅(qū)動(dòng)程序 ISP1581_BD
1 引言
ISP1581 是一種價(jià)格低、功能強(qiáng)的通用串行總線(xiàn)(USB)接口器件,它完全符合USB 2.0 規(guī)范,并為基于微控制器或微處理器的系統(tǒng)提供了高速USB 通信能力。ISP1581與系統(tǒng)的微控制器/微處理器的通信是通過(guò)一個(gè)高速的通用并行接口來(lái)實(shí)現(xiàn)的。它符合現(xiàn)有的大多數(shù)器件的分類(lèi)規(guī)格,比如:成像類(lèi)、海量存儲(chǔ)器件、通信器件、打印設(shè)備以及人機(jī)接口設(shè)備。
內(nèi)部通用DMA 模塊使得數(shù)據(jù)流很方便的集成。另外,多種結(jié)構(gòu)的DMA模塊實(shí)現(xiàn)了海量存儲(chǔ)的應(yīng)用。這種實(shí)現(xiàn)USB 接口的標(biāo)準(zhǔn)組件使得使用者可以在各種不同類(lèi)型的微控制器中選擇出一種最合適的微控制器。通過(guò)使用已有的結(jié)構(gòu)和減少固件上的投資縮短了開(kāi)發(fā)時(shí)間、減少了開(kāi)發(fā)風(fēng)險(xiǎn)和費(fèi)用。從而用最快捷的方法實(shí)現(xiàn)了最經(jīng)濟(jì)的USB外設(shè)的解決方案。ISP1581可理想地用于許多外設(shè),例如:打印機(jī)、掃描儀、MO、CD、DVD 和Zip/Jaz 驅(qū)動(dòng)器、數(shù)碼相機(jī)、USB和以太網(wǎng)的鏈接、電纜和DSL調(diào)制解調(diào)器等等。另外,ISP1581 所具有的低掛起功耗還可以滿(mǎn)足ACPITM,OnNOWTM和USB電源管理的要求。此外,ISP1581內(nèi)部還集成了許多特性,包括SoftConnectTM、低頻晶體振蕩器和集成的終止寄存器。所有這些特性都為系統(tǒng)大大節(jié)約了成本,同時(shí)使強(qiáng)大的USB功能很容易地用于PC機(jī)外設(shè)。
2 系統(tǒng)設(shè)計(jì)
系統(tǒng)設(shè)計(jì)包括硬件方案設(shè)計(jì)與USB設(shè)備的軟件設(shè)計(jì)。而USB設(shè)備的軟件設(shè)計(jì)主要包括兩部分:一是USB設(shè)備端的軟件,主要完成USB協(xié)議處理與數(shù)據(jù)交換(多數(shù)情況下是一個(gè)中斷子程序)以及其它應(yīng)用功能程序;二是PC端的程序,由USB通信程序和用戶(hù)服務(wù)程序兩部分組成,用戶(hù)服務(wù)程序通過(guò)USB通信程序與系統(tǒng)USBDI(USB設(shè)備接口)通信,USB通信程序開(kāi)發(fā)難度比較大,可用DDK或DriverWork等開(kāi)發(fā)工具開(kāi)發(fā)。
2.1 USB芯片與DSP的硬件連接
本方案以TI公司的TMS320C5XX作為微控制器,采用外部供電方式,連接電路如圖1所示。
ISP1581的16根數(shù)據(jù)線(xiàn)直接與DSP的數(shù)據(jù)線(xiàn)相連,存儲(chǔ)管理單元(MMU)和集成RAM作為USB的緩沖區(qū),允許微控制器以自己的速率對(duì)USB信息包進(jìn)行讀寫(xiě)。D+,D-信號(hào)線(xiàn)上串接18Ω電阻。XTAL1接12MHz晶振。
2.2 固件程序設(shè)計(jì)
由于采用的是不帶微控制器內(nèi)核的USB接口芯片,所以關(guān)于USB2.0協(xié)議規(guī)范的實(shí)現(xiàn)都必須靠DSP控制ISP1581芯片來(lái)完成。固件的主要設(shè)計(jì)任務(wù)是:在DSP的平臺(tái)上編寫(xiě)程序,以完成USB2.0規(guī)范所要求的標(biāo)準(zhǔn)請(qǐng)求及用戶(hù)根據(jù)產(chǎn)品需要自己定義的請(qǐng)求。為了不影響程序的執(zhí)行效率,本方案采用中斷方式完成固件的編寫(xiě),同時(shí),為了保證程序的模塊化及良好的可移植性,在設(shè)計(jì)中采用分層結(jié)構(gòu)進(jìn)行固件的編寫(xiě)。詳細(xì)方法可參見(jiàn)文獻(xiàn) 。
在本方案中,采用端點(diǎn)2以批量方式來(lái)與上位機(jī)進(jìn)行通信,采用端點(diǎn)0來(lái)進(jìn)行除設(shè)備枚舉之外的設(shè)備命令控制字的處理,這在下面的設(shè)備驅(qū)動(dòng)程序中將會(huì)談到。因?yàn)閷?duì)于繼電器來(lái)說(shuō),有很多標(biāo)志位需要傳送;且因USB是單向控制的,故在每次讀寫(xiě)數(shù)據(jù)時(shí)均需首先發(fā)送一命令控制字,然后再通過(guò)API讀寫(xiě)函數(shù)進(jìn)行雙方通信。所以我在此設(shè)一個(gè)IO請(qǐng)求結(jié)構(gòu):struct IOREQ{unsigned int wValue;unsigned int wIndex;},wValue代表16位標(biāo)志位,wIndex代表需傳送的字節(jié)數(shù),這個(gè)結(jié)構(gòu)命令傳送的驅(qū)動(dòng)需要自己在設(shè)備驅(qū)動(dòng)程序中實(shí)現(xiàn)(通過(guò)設(shè)備類(lèi)請(qǐng)求的方式,見(jiàn)2.3述),且在上層應(yīng)用程序中通過(guò)DeviceIoControl(…)函數(shù),通過(guò)驅(qū)動(dòng)的類(lèi)請(qǐng)求傳給USB設(shè)備端點(diǎn)0,USB設(shè)備則以類(lèi)設(shè)備請(qǐng)求方式處理這個(gè)設(shè)備控制命令。
本驅(qū)動(dòng)中采用0x00作為USB設(shè)備寫(xiě)命令的請(qǐng)求類(lèi)型號(hào),0x01作為USB設(shè)備讀命令的請(qǐng)求類(lèi)型號(hào),設(shè)備固件中處理IO控制請(qǐng)求的代碼如下:
unsigned char type, req;
type = ControlData.DeviceRequest.bmRequestType & 0x60;//請(qǐng)求類(lèi)型
req = ControlData.DeviceRequest.bRequest & 0x0F;//請(qǐng)求號(hào)
if (type == 0x00)
(*StandardDeviceRequest[req])();//調(diào)用標(biāo)準(zhǔn)請(qǐng)求
else if (type ==0x40)//類(lèi)請(qǐng)求
{if (req==0x00) Handle_Write_DeviceIo();//處理寫(xiě)控制命令
if(req==0x01) Handle_Read_DeviceIo();//處理讀控制命令
}
2.3 PC端的USB驅(qū)動(dòng)程序設(shè)計(jì)
DriverStudio 是一套用來(lái)簡(jiǎn)化微軟Windows 平臺(tái)下設(shè)備驅(qū)動(dòng)程序的開(kāi)發(fā)、調(diào)試和測(cè)試的工具包。DriverStudio 當(dāng)前的版本包括DriverWorks、SoftICE及其它工具模塊。DriverWorks:對(duì)于Windows NT下和 Windows 98與Windows 2000/XP共同支持的Win32驅(qū)動(dòng)模型(WDM)設(shè)備驅(qū)動(dòng)程序的開(kāi)發(fā)提供完全的支持。DriverWorks中包含一個(gè)非常完善的源代碼生成工具(DriverWizard)以及相應(yīng)的類(lèi)庫(kù)和驅(qū)動(dòng)程序樣本,它提供了在C++下進(jìn)行設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)的支持。SoftICE:SoftICE 是一個(gè)功能極其強(qiáng)大的內(nèi)核模式調(diào)試器,它支持在配置一臺(tái)單獨(dú)的計(jì)算機(jī)或兩臺(tái)計(jì)算機(jī)下進(jìn)行設(shè)備驅(qū)動(dòng)程序的調(diào)試。DriverWorks提供了三個(gè)與USB直接相關(guān)的類(lèi):UsbLowerDevice,KUsbInterface和KUsbPipe類(lèi),用于實(shí)現(xiàn)USB設(shè)備操作。KUsbLowerDevice類(lèi)用于邏輯設(shè)備的編程,KUsbInterface類(lèi)用于接口的編程,KUsbPipe類(lèi)用于管道的編程。最基本的例程有設(shè)備的啟動(dòng),停止,卸載,讀寫(xiě),設(shè)備控制等例程 。
DriverStudio本身提供了一個(gè)設(shè)備驅(qū)動(dòng)的框架,且可自動(dòng)生成端點(diǎn)2的各種傳輸方式的源代碼,故在此不討論。對(duì)于設(shè)備控制命令傳送的驅(qū)動(dòng)則需根據(jù)實(shí)際應(yīng)用具體實(shí)現(xiàn)如下:采用設(shè)備類(lèi)請(qǐng)求函數(shù)
PURB BuildVendorRequest(
PUCHAR TransferBuffer,//為驅(qū)動(dòng)程序存放傳輸數(shù)據(jù)的內(nèi)存區(qū)
ULONG TransferBufferLength,//傳輸?shù)淖止?jié)數(shù),對(duì)應(yīng)于類(lèi)請(qǐng)求的wLength
UCHAR RequestTypeReservedBits,//為類(lèi)請(qǐng)求字節(jié)中的保留位
UCHAR Request,//具體請(qǐng)求數(shù)值,對(duì)應(yīng)于類(lèi)請(qǐng)求的bRequest
USHORT Value,//對(duì)應(yīng)于類(lèi)請(qǐng)求的wValue
BOOLEAN bIn=FALSE,//TRUE為輸入:設(shè)備->主機(jī),F(xiàn)ALSE為輸出:主機(jī)->設(shè)備
BOOLEAN bShortOk=FALSE,//TRUE表示設(shè)備傳輸?shù)淖止?jié)數(shù),可少于指定的字節(jié)數(shù)
PURB Link=NULL,//為下一個(gè)傳輸?shù)腢RB
UCHAR Index=0, //對(duì)應(yīng)于類(lèi)請(qǐng)求的wIndex
USHORT Function=URB_FUNCTION_VENTOR_DEVICE,//類(lèi)別的請(qǐng)求
PURB pUrb=NULL//指向一存在的URB
);
實(shí)現(xiàn)的方法是對(duì)于讀請(qǐng)求IOCTL_READ及寫(xiě)請(qǐng)求IOCTL_WRITE, 將相應(yīng)的類(lèi)別代碼通過(guò)此成員函數(shù)傳送給底層驅(qū)動(dòng),實(shí)現(xiàn)IO控制命令請(qǐng)求。代碼實(shí)現(xiàn)如下:
NTSTATUS USBDRIVERDevice::DeviceControl(KIrp I)
{
NTSTATUS status;
PURB pUrb;
struct IOREQ* Ioctrl;
switch (I.IoctlCode())
{
case IOCTL_READ://處理IO讀請(qǐng)求
PIRP pIrp=(PIRP)I;
Ioctrl=(struct IOREQ*)pIrp->AssociatedIrp.SystemBuffer;//取緩沖區(qū)數(shù)據(jù)
pUrb=m_Lower.BuildVendorRequest(NULL,0,0,0,Ioctrl->wvalue,TRUE,TRUE,NULL,
Ioctrl->wIndex,URB_FUNCTION_VENDOR_DEVICE);//類(lèi)請(qǐng)求:讀請(qǐng)求
if(pUrb==NULL)
status=STATUS_INSUFFICIENT_RESOURCES;
else
{status=m_Lower.SubmitUrb(pUrb);delete pUrb;}
break;
case IOCTL_WRITE:
PIRP pIrp=(PIRP)I;
Ioctrl=(struct IOREQ*)pIrp->AssociatedIrp.SystemBuffer; //取緩沖區(qū)數(shù)據(jù)
pUrb=m_Lower.BuildVendorRequest(NULL,0,0,1,Ioctrl->wvalue,TRUE,TRUE,NULL,
Ioctrl->wIndex,URB_FUNCTION_VENDOR_DEVICE); //類(lèi)請(qǐng)求:寫(xiě)請(qǐng)求
if(pUrb==NULL)
status=STATUS_INSUFFICIENT_RESOURCES;
else
{status=m_Lower.SubmitUrb(pUrb);delete pUrb;}
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
if (status == STATUS_PENDING)
return status;
else
return I.PnpComplete(this, status);//成功,提交URB
}
另外,對(duì)于設(shè)備驅(qū)動(dòng)的安裝,還應(yīng)修改設(shè)備配置文件中的安裝程序類(lèi)別和GUID:Class=USB,ClassGUID={36FC9E60-C465-11CF-8056-444553540000},否則將無(wú)法識(shí)別出是USB設(shè)備 。
2.4 PC端的應(yīng)用程序設(shè)計(jì)
通過(guò)調(diào)用API函數(shù)編寫(xiě)PC的應(yīng)用程序。函數(shù)有CreateFile(),CloseHandle(), DeviceIOControl(),ReadFile(),WriteFile()。其中DeviceIOControl()用于PC(主機(jī))向DSP發(fā)送請(qǐng)求,ReadFile()和WriteFile()分別用于從USB設(shè)備中讀出數(shù)據(jù)以及向USB設(shè)備中寫(xiě)入數(shù)據(jù)。在設(shè)計(jì)過(guò)程中必須注意的問(wèn)題是:由于USB接口是主-從方式的接口,它的一切傳輸過(guò)程都必須通過(guò)主機(jī)向外設(shè)發(fā)送請(qǐng)求后才可以開(kāi)始,所以在使用ReadFile()、WriteFile()讀寫(xiě)數(shù)據(jù)之前,必須先通過(guò)DeviceIOControl()向USB設(shè)備發(fā)送請(qǐng)求,而且還須采用異步IO方式。例如,讀數(shù)據(jù)的部分代碼為:
struct IOREQ Ioctrl;//IO請(qǐng)求的結(jié)構(gòu)
OVERLAPPED ov;//異步IO
memset(&ov,0,sizeof(OVERLAPPED));
ov.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//創(chuàng)建一事件
ResetEvent(ov.hEvent);//復(fù)位事件
unsigned long nBytes;
Ioctrl.wvalue=xx; Ioctrl.wIndex=xx;// 傳送的標(biāo)志位及要傳輸?shù)淖止?jié)數(shù)
bResult = DeviceIoControl(hDevice,IOCTL_READ,&Ioctrl,8,NULL,0,&nBytes,&ov);//啟動(dòng) //讀命令,
if (bResult != TRUE)
{
if(GetLastError()!=ERROR_IO_PENDING)//IO錯(cuò)誤
{
MessageBox("請(qǐng)求數(shù)據(jù)傳送失敗! 已放棄", "錯(cuò)誤");
return 0;
}
switch(::WaitForSingleObject(ov.hEvent,20))//等待20ms
{
case WAIT_OBJECT_0:
if(!::GetOverlappedResult(hDevice,&ov,&nBytes,TRUE))
return 0;
break;
case WAIT_TIMEOUT://超時(shí)錯(cuò)誤
::CancelIo(hDevice);
return 0;
default:
return 0;
}
}
bResult = ReadFile(hDevice,…,&ov);// 從設(shè)備讀數(shù)據(jù)
if (bResult != TRUE)
{…//同上}
3 系統(tǒng)測(cè)試及結(jié)果
繼電器測(cè)試與保護(hù)裝置的交流實(shí)驗(yàn)部分測(cè)試結(jié)果如下圖所示。實(shí)驗(yàn)證明,利用USB傳輸響應(yīng)時(shí)間完全達(dá)到設(shè)定要求,即使在有10路AD數(shù)據(jù)的情況下也反應(yīng)靈敏,特別地,用USB傳輸方式,有效的解決了現(xiàn)場(chǎng)作業(yè)方便性的問(wèn)題。
4 結(jié)束語(yǔ)
本文以一實(shí)際開(kāi)發(fā)的項(xiàng)目為例,對(duì)以DSP芯片為控制器的USB傳輸系統(tǒng)具體的硬件和軟件實(shí)現(xiàn)進(jìn)行了闡述,特別地詳述了適用于具體應(yīng)用的設(shè)備驅(qū)動(dòng)的開(kāi)發(fā),此設(shè)備驅(qū)動(dòng)也已成功應(yīng)用于USB接口的圖像傳輸,具有一定的通用性。
參考文獻(xiàn)
[1]周立功等. PDIUSBD12 USB固件編程與驅(qū)動(dòng)開(kāi)發(fā)[M]. 北京:北京航空航天大學(xué)出版社,2003,2
[2]武安河等. Windows 2000/XP WDM設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)[M]. 北京:電子工業(yè)出版社,2003,4
[3]施諾等[譯]. Windows 2000 設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)指南[M]. 北京:機(jī)械工業(yè)出版社,2001,9
|