/*;CH372/CH375 USB device mode & external firmware ; U2(AT89C51) Program ; ; Website: http://winchiphead.com ; Email: 個(gè)人信息保護(hù),已隱藏 ; Author: W.ch 2003.12, 2005.03 ; ;**************************************************************************** CH375 外部固件方式范例 這里僅處理標(biāo)準(zhǔn)請求和端點(diǎn)2的簡單讀寫
*/
/* MCS-51單片機(jī)C語言的示例程序 */ #pragma NOAREGS #include #include "CH375INC.H"
typedef union _REQUEST_PACK{ unsigned char buffer[8]; struct{ unsigned char bmReuestType; //標(biāo)準(zhǔn)請求字 unsigned char bRequest; //請求代碼 unsigned int wValue; //特性選擇高 unsigned int wIndx; //索引 unsigned int wLength; //數(shù)據(jù)長度 }r; } mREQUEST_PACKET, *mpREQUEST_PACKET;
//設(shè)備描述符 unsigned char code DevDes[]={ 0x12 //描述符大小 , 0x01 //常數(shù)DEVICE , 0x10 //USB規(guī)范版本信息 , 0x01 , 0xFF //類別碼, , 0x80 //子類別碼 , 0x37 //協(xié)議碼 , 0x08 //端點(diǎn)0的最大信息包大小 , 0x48 //廠商ID , 0x43 , 0x37 //產(chǎn)品ID , 0x55 , 0x00 //設(shè)備版本信息 , 0x01 , 0x00 //索引值 , 0x00 , 0x00 , 0x01 //可能配置的數(shù)目 , 00 //無意義 , 00 , 00 , 00 , 00 , 00 }; //配置描述符 unsigned char code ConDes[]={ //配置描述符 0x09 //描述符大小 , 0x02 //常數(shù)CONFIG , 0x27 //此配置傳回所有數(shù)據(jù)大小 , 0x00 // , 0x01 //接口數(shù) , 0x01 //配置值 , 0x00 //索引 , 0x80 //電源設(shè)置 , 0x40 //需要總線電源 //接口描述符 , 0x09 //描述符大小 , 0x04 //常數(shù)INTERFACE , 0x00 //識別碼 , 0x00 //代替數(shù)值 , 0x03 //支持的端點(diǎn)數(shù) , 0xFF //類別碼 , 0x80 //子類別碼 , 0x37 //協(xié)議碼 , 0x00 //索引 //端點(diǎn)描述符 , 0x07 //述符大小 , 0x05 //常數(shù)ENDPOINT , 0x82 //端點(diǎn)數(shù)目及方向 , 0x02 //支持的傳輸類型 , 0x40 //支持的最大信息包大小 , 0x00 , 0x00 // , 0x07 , 0x05 , 0x02 , 0x02 , 0x40 , 0x00 , 0x00 , 0x07 , 0x05 , 0x81 , 0x03 , 0x08 , 0x00 , 0x01
, 0x07 , 0x05 , 0x01 , 0x02 , 0x08 , 0x00 , 0x00 }; //配置描述符 unsigned char code LangDes[]={0x04,0x03,0x09,0x04}; //語言描述符 unsigned char code SerDes[]={0x12,0x03,'C',0,'H',0,'3',0,'7',0,'5',0,'U',0,'S',0,'B',0}; //字符串描述符
unsigned char mVarSetupRequest; // ;USB請求碼 unsigned char mVarSetupLength; // ;后續(xù)數(shù)據(jù)長度 unsigned char code * VarSetupDescr; // ;描述符偏移地址
unsigned char VarUsbAddress ; //
bit CH375FLAGERR; //錯(cuò)誤清0 bit CH375CONFLAG; //配置標(biāo)志
unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */ unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; /* CH375數(shù)據(jù)端口的I/O地址 */
mREQUEST_PACKET request; sbit CH375ACT = P1^4;
/* 延時(shí)2微秒,不精確 */ void Delay1us(){ ; }
void Delay2us( ) { unsigned char i; #define DELAY_START_VALUE 1 /* 根據(jù)單片機(jī)的時(shí)鐘選擇初值,20MHz以下為0,30MHz以上為2 */ for ( i=DELAY_START_VALUE; i!=0; i-- ); }
/* 延時(shí)50毫秒,不精確 */ void Delay50ms( ) { unsigned char i, j; for ( i=200; i!=0; i-- ) for ( j=250; j!=0; j-- ); }
/* 將PC機(jī)的低字節(jié)在前的16位字?jǐn)?shù)據(jù)轉(zhuǎn)換為C51的高字節(jié)在前的數(shù)據(jù) */ //unsigned int BIG_ENDIAN( unsigned int value ) //{ // unsigned int in, out; // in = value; // ((unsigned char *)&out)[1] = ((unsigned char *)&in)[0]; // ((unsigned char *)&out)[0] = ((unsigned char *)&in)[1]; // return( out ); //}
void CH375_WR_CMD_PORT( unsigned char cmd ) { /* 向CH375的命令端口寫入命令,周期不小于4uS,如果單片機(jī)較快則延時(shí) */ //delay2us(); CH375_CMD_PORT=cmd; Delay2us( ); }
void CH375_WR_DAT_PORT( unsigned char dat ) { /* 向CH375的數(shù)據(jù)端口寫入數(shù)據(jù),周期不小于1.5uS,如果單片機(jī)較快則延時(shí) */ CH375_DAT_PORT=dat; Delay1us(); /* 因?yàn)镸CS51單片機(jī)較慢所以實(shí)際上無需延時(shí) */ }
unsigned char CH375_RD_DAT_PORT() { /* 從CH375的數(shù)據(jù)端口讀出數(shù)據(jù),周期不小于1.5uS,如果單片機(jī)較快則延時(shí) */ Delay1us( ); /* 因?yàn)镸CS51單片機(jī)較慢所以實(shí)際上無需延時(shí) */ return( CH375_DAT_PORT );
} /* CH375初始化子程序 */ void CH375_Init( ) { /* 設(shè)置USB工作模式, 必要操作 */ CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); CH375_WR_DAT_PORT( 1 ); /* 設(shè)置為使用外置固件的USB設(shè)備方式 */ for ( ;; ) { /* 等待操作成功,通常需要等待10uS-20uS */ if ( CH375_RD_DAT_PORT( )==CMD_RET_SUCCESS ) break; }
/* 下述啟用中斷,假定CH375連接在INT0 */ IT0 = 0; /* 置外部信號為低電平觸發(fā) */ IE0 = 0; /* 清中斷標(biāo)志 */ EX0 = 1; /* 允許CH375中斷 */ } //*********************************************************
//********************************************************* //端點(diǎn)0數(shù)據(jù)上傳 void mCh375Ep0Up(){ unsigned char i,len; if(mVarSetupLength){ //長度不為0傳輸具體長度的數(shù)據(jù) if(mVarSetupLength<=8){ len=mVarSetupLength; mVarSetupLength=0; } //長度小于8則長輸要求的長度 else{ len=8; mVarSetupLength-=8; } //長度大于8則傳輸8個(gè),切總長度減8 CH375_WR_CMD_PORT(CMD_WR_USB_DATA3); //發(fā)出寫端點(diǎn)0的命令 CH375_WR_DAT_PORT(len); //寫入長度 for(i=0;i!=len;i++) CH375_WR_DAT_PORT(request.buffer[i]); //循環(huán)寫入數(shù)據(jù) } else{ CH375_WR_CMD_PORT(CMD_WR_USB_DATA3); //發(fā)出寫端點(diǎn)0的命令 CH375_WR_DAT_PORT(0); //上傳0長度數(shù)據(jù),這是一個(gè)狀態(tài)階段 } }
//*********************************************************
//復(fù)制描述符以便上傳 void mCh375DesUp(){ unsigned char k; for (k=0; k!=8; k++ ) { request.buffer[k]=*VarSetupDescr; //依次復(fù)制8個(gè)描述符, VarSetupDescr++; } }
/* CH375中斷服務(wù)程序INT0,使用寄存器組1 */ void mCH375Interrupt( ) interrupt 0 using 1 { unsigned char InterruptStatus; unsigned char length, c1, len; unsigned char *pBuf; unsigned char mBuf[64]; CH375_WR_CMD_PORT(CMD_GET_STATUS); /* 獲取中斷狀態(tài)并取消中斷請求 */ InterruptStatus =CH375_RD_DAT_PORT(); /* 獲取中斷狀態(tài) */ IE0 = 0; /* 清中斷標(biāo)志,對應(yīng)于INT0中斷 */ switch(InterruptStatus){ // 分析中斷狀態(tài) case USB_INT_EP2_OUT: // 批量端點(diǎn)下傳成功 pBuf=mBuf; //數(shù)據(jù)未處理 CH375_WR_CMD_PORT(CMD_RD_USB_DATA); //發(fā)出讀數(shù)據(jù)命令 length=CH375_RD_DAT_PORT(); //首先讀出的是長度 for(len=0;len!=length;len++,pBuf++)*pBuf=CH375_RD_DAT_PORT(); //將數(shù)據(jù)讀入到緩沖區(qū) pBuf=mBuf; // 演示回傳 CH375_WR_CMD_PORT(CMD_WR_USB_DATA7); //發(fā)出寫上傳端點(diǎn)命令 CH375_WR_DAT_PORT(length); for(len=0;len!=length;len++,pBuf++)CH375_WR_DAT_PORT(*pBuf); //將數(shù)據(jù)寫入上傳端點(diǎn) break; case USB_INT_EP2_IN: //批量端點(diǎn)上傳成功,未處理 CH375_WR_CMD_PORT (CMD_UNLOCK_USB); //釋放緩沖區(qū) break; case USB_INT_EP1_IN: //中斷端點(diǎn)上傳成功,未處理 CH375_WR_CMD_PORT (CMD_UNLOCK_USB); //釋放緩沖區(qū) break; case USB_INT_EP1_OUT: //中斷端點(diǎn)下傳成功,未處理 CH375_WR_CMD_PORT(CMD_RD_USB_DATA); //發(fā)出讀數(shù)據(jù)命令 if(length=CH375_RD_DAT_PORT()){ //長度為0跳出 for(len=0;len!=length;len++)c1=CH375_RD_DAT_PORT(); //取出下傳數(shù)據(jù) } // CH375_WR_CMD_PORT (CMD_UNLOCK_USB); //釋放緩沖區(qū),如果前面沒有CMD_RD_USB_DATA命令則使用本命令 break; case USB_INT_EP0_SETUP: //控制端點(diǎn)建立成功 CH375_WR_CMD_PORT(CMD_RD_USB_DATA); length=CH375_RD_DAT_PORT(); for(len=0;len!=le