使用375做HID設(shè)備和電腦通訊 有以下兩個問題: 1. 使用查詢方式正常,使用中斷方式 電腦提示無法識別USB設(shè)備 2..上傳數(shù)據(jù)長度必須是64 否則不行 測試軟件是你們 HID KEY BOARD
下面是C代碼 //#pragma NOAREGS #include #include "CH375INC.H" #include "stdio.h" unsigned char idata buf[64]; typedef union _REQUEST_PACK{ unsigned char buffer[8]; struct{ unsigned char bmReuestType; //標準請求字 unsigned char bRequest; //請求代碼 unsigned int wValue; //特性選擇高 unsigned int wIndx; //索引 unsigned int wLength; //數(shù)據(jù)長度 }r; } mREQUEST_PACKET, *mpREQUEST_PACKET; //設(shè)備的描述符包含設(shè)備描述符、配置描述符、字符描述符;識別描述符的類型就是根據(jù)它的第二個字節(jié)值來識別; //一般情況下設(shè)備描述符不需要用戶去配置,因為可以直接用軟件從現(xiàn)有的設(shè)備中讀??;同種設(shè)備的描述符都相同;如優(yōu)盤描述符都一樣 /*以下是設(shè)備描述符,(為什么是這些數(shù)值,可查閱USB協(xié)議書籍)*/ unsigned char code DevDes[]={ 0x12 //描述符大小,即此數(shù)組的長度 ,0x01 //常數(shù)表示描述符的類型;(數(shù)值為0x01表示設(shè)備描述符) ,0x10 ,0x01 //USB規(guī)范版本信息;2個字節(jié);0x10、0x01表示USB1.1;USB2.0為0X00、0X02; ,0x00 //類別碼,數(shù)值0X01~0XFE為USB定義的類,如打印機等,0XFF是由廠商指定的類別;0為HID類,它的類別在配置描述符中的接口描述符指定; ,0x00 //子類別碼;這些碼值的具體含義根據(jù)bDeviceClass 域來看如bDeviceClass 域為零此域也須為零;如bDeviceClass 域為FFH此域的所有值保留 ,0x00 //協(xié)議碼 ,0x08 //端點0的最大信息包大小 ,0x31 //廠商ID ,0x51 ,0x07 //產(chǎn)品ID ,0x20 ,0x00 //設(shè)備版本信息 ,0x03 ,0x01 //索引值 ,0x02 ,0x00 ,0x00 //可能配置的數(shù)目 }; //配置描述符;包括配置描述符、接口描述符、端點描述符,HID設(shè)備還包括HID描述符; unsigned char code ConDes[]={ 0x09, 0x02, 0x29, 0x00, 0x01, 0x01, 0x04, 0xa0, 0x23,//配置描述符;第二字節(jié)為0X02 0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x05,//接口描述符;第二字節(jié)為0X04 0x09, 0x21, 0x00, 0x01, 0x00, 0x01, 0x22, 0x22, 0x00,//HID描述符;第二字節(jié)為0X21 0x07, 0x05, 0x82, 0x03, 0x40, 0x00, 0x18, //端點描述符;第二字節(jié)為0X05 0x07, 0x05, 0x02, 0x03, 0x40, 0x00, 0x18 //端點描述符; }; //字符串描述符,報表描述符; //作鍵盤設(shè)備時,報表描述符描述了數(shù)據(jù)格式;如鍵盤,則必須發(fā)送8個字節(jié)的數(shù)據(jù);其中第3個字節(jié)是要在 //各種文本里顯示的數(shù)據(jù)(如WORD文擋);其余字節(jié)全為0; unsigned char code Hid_des[]={ 0x06, 0x00,0xff, 0x09, 0x01, 0xa1, 0x01, //集合開始 0x09, 0x02, //Usage Page 用法 0x15, 0x00, //Logical Minimun 0x26, 0x00,0xff, //Logical Maximun 0x75, 0x08, //Report Size 0x95, 0x40, //Report Counet 0x81, 0x06, //Input 0x09, 0x02, //Usage Page 用法 0x15, 0x00, //Logical Minimun 0x26, 0x00,0xff, //Logical Maximun 0x75, 0x08, //Report Size 0x95, 0x40, //Report Counet 0x91, 0x06, //Output
0xC0 }; unsigned char code LangDes[]={0x04,0x03,0x09,0x04}; //語言描述符 unsigned char code SerDes[]={0x28,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x49,0x00,0x43,0x00,0x42 ,0x00,0x43,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00 }; //字符串描述符
unsigned char mVarSetupRequest; // ;USB請求碼 unsigned char mVarSetupLength; // ;后續(xù)數(shù)據(jù)長度 unsigned char code * VarSetupDescr; // ;描述符偏移地址 unsigned char buf1[8]; unsigned char VarUsbAddress ; // unsigned char Report_ID=0X01; unsigned char i=0x05; unsigned char length;
sbit CH375_INT_WIRE= P3^2; //P3.2, INT0, 連接CH375的INT#引腳,用于查詢中斷狀態(tài) bit CH375FLAGERR; //錯誤清0 bit CH375CONFLAG; unsigned char flag=0; mREQUEST_PACKET request; sbit CH375_RD = P3^6; sbit CH375_CS = P2^6; sbit CH375_WR = P3^7; sbit CH375_A0 = P2^5; #define CH375_D0_D7 P0 //**************************************************
void Delay2us( ); void delay10ms(); void CH375_WR_CMD_PORT( unsigned char cmd ); void CH375_WR_DAT_PORT( unsigned char dat ); void CH375_Init( ); void mCh375Ep0Up(); void wat_clr();
//**************************************************
void wat_clr() { P1_4=1; delay2us(); P1_4=0; }
void delay10ms() { unsigned char i,j; for(i=10;i!=0;i--) for(j=100;j!=0;j--) ; }
void Delay1us(){;} /* 延時2微秒,不精確 */ void Delay2us( ) { unsigned char i; for ( i=2; i!=0; i-- ); } /* 延時50毫秒,不精確 */ void Delay50ms( ) { unsigned char i, j; for ( i=200; i!=0; i-- ) for ( j=250; j!=0; j-- ); } /*以下是帶P0、P1、P2口的單片機外部讀寫方式、地址的確定和外部擴展I/O口地址一樣,見硬件電路*/ void CH375_WR_CMD_PORT( unsigned char cmd ) { CH375_A0 = 1; // 選擇CH375的命令口 delay2us(); CH375_D0_D7 = cmd;
CH375_RD = 1; // 如果I/O默認電平是高電平,那么這是可選操作 CH375_CS = 0; CH375_WR = 0;
CH375_WR = 1; CH375_CS = 1; CH375_A0 = 0;
CH375_D0_D7 = 0xFF; // 對于準雙向I/O,請在此設(shè)置輸出全高電平
delay2us(); }
void CH375_WR_DAT_PORT( unsigned char dat ) { CH375_D0_D7 = dat;
CH375_CS = 0; CH375_WR = 0;
CH375_WR = 1; CH375_CS = 1;
CH375_D0_D7 = 0xFF;
delay2us(); }
unsigned char CH375_RD_DAT_PORT( void ) { unsigned char dat;
CH375_D0_D7 = 0xFF; // 對于準雙向I/O,請在此設(shè)置輸出全高電平,便于輸入 CH375_CS = 0; CH375_RD = 0; dat=CH375_D0_D7; CH375_RD = 1; CH375_CS = 1; CH375_D0_D7 = 0xFF; // 對于準雙向I/O,請在此設(shè)置輸出全高電平 return( dat );
}
/* CH375初始化子程序; */ void CH375_Init( ) { /* 設(shè)置USB工作模式, 必要操作 */ CH375_WR_CMD_PORT( CMD_SET_USB_MODE );//向數(shù)據(jù)端口寫設(shè)置CH375命令的數(shù)據(jù)CMD_SET_USB_MODE,數(shù)值大小在頭文件中有定義,說明書中有規(guī)定值 CH375_WR_DAT_PORT( 1 ); /* 0X01設(shè)置為使用外置固件的USB設(shè)備方式,說明書中有定義 */ } //端點0數(shù)據(jù)上傳;CH375有端點0、1、2等緩沖區(qū)與計算機通訊,個緩沖區(qū)大小不一樣;詳細見CH375說明書; 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個,切總長度減8 CH375_WR_CMD_PORT(CMD_WR_USB_DATA3); //發(fā)出寫端點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ā)出寫端點0的命令 CH375_WR_DAT_PORT(0); //上傳0長度數(shù)據(jù),這是一個狀態(tài)階段
} } //********************************************************* //復(fù)制描述符以便上傳 void mCh375DesUp(){ unsigned char k; for (k=0; k!=8; k++ ) { request.buffer[k]=*VarSetupDescr; //依次復(fù)制8個描述符, VarSetupDescr++; } } /* CH375中斷服務(wù)程序INT0*/ void mCH375Interrupt( ) // 普通函數(shù) void mCH375Interrupt( ) interrupt 0 using 1 //中斷函數(shù) { unsigned char InterruptStatus,i; unsigned char length, c1, len; unsigned char mBuf[8]; wat_clr(); CH375_WR_CMD_PORT(CMD_GET_STATUS); /* 向CH375芯片發(fā)送獲取中斷狀態(tài)的命令;CMD_GET_STATUS為命令碼,數(shù)值大小在CH375INC.H 頭文件中*/ InterruptStatus =CH375_RD_DAT_PORT(); /* 讀取中斷狀態(tài) */
switch(InterruptStatus){ // 分析中斷狀態(tài), case USB_INT_EP2_OUT: // 批量端點下傳成功 CH375_WR_CMD_PORT(CMD_RD_USB_DATA); //發(fā)出讀數(shù)據(jù)命令 if(length=CH375_RD_DAT_PORT()){ //長度為0跳出 for(len=0;len!=length;len++) { mBuf[len]