阅读:1431回复:1
HID 伟输,帮忙啊
我用ADuC812加usbn9603做的HID设备,参照NS的例子,试做成一每0.5S由终端1发送4个字节的数据到PC,在98下用HIDVIEW可以接收到数据,应用程序中设备信息读取正确,HID报告解析也没有问题,但readfile调用却只返回0字节内容,望大虾们不吝指教。固件如下:
typedef unsigned char byte; #define FALSE 0 #define TRUE -1 #include <intrins.h> #include \"defusb.h\" /*include USB defines */ #include \"def9602.h\" /*include 9602 defines */ /*These are the standard ANSI bit operation macros. They are used by */ /*microcontrollers that don\'t have special bit operation instructions.*/ #define BIT(x) (1 << (x)) /*used by bit op macros */ #define BIT0 0x01 /*used by bit op macros */ #define BIT1 0x02 #define BIT2 0x04 #define BIT3 0x08 #define BIT4 0x10 #define BIT5 0x20 #define BIT6 0x40 #define BIT7 0x80 /* this macro sets a bit in the specified register or memory location */ #define SETBIT(reg,bit) reg|=bit /* this macro clrs a bit in the specified register or memory location */ #define CLRBIT(reg,bit) reg&=(~bit) /* this macro toggles a bit in the spec\'d register or memory location */ #define TGLBIT(reg,bit) reg^=bit /* this macro tests a bit, returning a non-zero val if bit is set *****/ #define TSTBIT(reg,bit) (reg&bit) #include <stdio.h> #include <ADuC812.h> //#define IO_9602 (byte *)0x8000 /* include this line if compiling for bus powered operation */ /* #define BUSPOWER TRUE */ #ifdef BUSPOWER #define VREG_ON TRUE /*use the regulator */ #endif /* if the 9602\'s voltage regulator needs to be turned on, define a */ /* constant named \'VREG_ON\'. Otherwise, the voltage regulator will */ /* remain off, and an external 3.3 Volt source is assumed. */ #define VREG_ST VGE /**********************************************************************/ /* Message related values */ /**********************************************************************/ /* Command message constants */ #define SYNCBYT 0xAA /*sync code expected */ byte sum=0;//test sbit USB_LED=P3^4; sbit INT_LED=P3^3; sbit USB_CS =P2^7;//P3^5; /* these macros do interrupt related things ***************************/ #define INTSON EA=1 /*turn on all ints */ //??? /**********************************************************************/ /* These are system independent macros and defines */ /**********************************************************************/ //#define INTR_TYPE INT_H_P #define INTR_TYPE INT_L_P /* The system clock is the 48 MHz USB clock, divided by this value: */ #define CLKDIV 5 /*USB clock divisor */ /* this macro turns on the USB activity LED ***************************/ #define USB_LED_ON USB_LED=0 #define USB_LED_OFF USB_LED=1 #define HIBYT(x) (x)/256 #define LOBYT(x) (x)%256 #define VID \'N\' /*vendor ID (National) */ #define NORMAL_ALTMSK SD3+RESET_A /*ALTMSK if not in suspend*/ #define SUSPND_ALTMSK RESUME_A+RESET_A /*ALTMSK if in suspend */ /* Enforce a minimum time period active before suspending to make sure*/ /* that the board is detected at power on and restart. The value here*/ /* corresponds to the minimum number of time periods between suspend */ /* events. At half-second intervals, the value here equals 2 seconds */ #define SUSPND_TO 4 /* store the status byte in FIFO0 for the chosen endpoint *************/ #define EPSTATUS(epbit) if(TSTBIT(stalld,epbit)) write_usb(TXD0,1); \\ else write_usb(TXD0,0); break; /* Flush and disable the USB TX0 **************************************/ #define FLUSHTX0 {write_usb(TXC0,FLUSH);} /* Flush and disable the USB TX1 **************************************/ #define FLUSHTX1 {write_usb(TXC1,FLUSH);} /* Flush and disable the USB TX2 **************************************/ #define FLUSHTX2 {write_usb(TXC2,FLUSH);} /* Flush and disable the USB TX3 **************************************/ #define FLUSHTX3 {write_usb(TXC3,FLUSH); CLRBIT(status,RPTBUSY);} /* Flush and disable the USB RX0 **************************************/ #define FLUSHRX0 {write_usb(RXC0,FLUSH);} /* Flush and disable the USB RX1 **************************************/ #define FLUSHRX1 {write_usb(RXC1,FLUSH);} /* Flush and disable the USB RX2 **************************************/ #define FLUSHRX2 {write_usb(RXC2,FLUSH);} /* Flush and disable the USB RX3 **************************************/ #define FLUSHRX3 {write_usb(RXC3,FLUSH); rcount3=0;} /* enable TX0, using the appropriate DATA PID *************************/ #define TXEN0_PID {if(TSTBIT(dtapid,TGL0PID)) write_usb(TXC0,TX_TOGL+TX_EN);\\ else write_usb(TXC0,TX_EN); TGLBIT(dtapid,TGL0PID);} /* enable TX1, using the appropriate DATA PID, but not toggling it ****/ #define TXEN1_PID_NO_TGL {if(TSTBIT(dtapid,TGL1PID)) \\ write_usb(TXC1,TX_TOGL+TX_LAST+TX_EN); else \\ write_usb(TXC1,TX_LAST+TX_EN);} /* enable TX1, using the appropriate DATA PID *************************/ #define TXEN1_PID {TXEN1_PID_NO_TGL; TGLBIT(dtapid,TGL1PID);} /* clears the multi-packet mode bits **********************************/ #define CLR_MLTIPKT {CLRBIT(status,GETDESC); CLRBIT(status,GETRPRT); \\ CLRBIT(status,MLTIPKT);} /* sets status.GETDESC and status.MLTIPKT *****************************/ #define SET_GETDESC {SETBIT(status,GETDESC); SETBIT(status,MLTIPKT);} /* sets status.GETRPRT and status.MLTIPKT *****************************/ #define SET_GETRPRT {SETBIT(status,GETRPRT); SETBIT(status,MLTIPKT);} /* this macro helps with the switch change test ***********************/ #define TSTSWITCH {if(rpt_sw!=report[SWITCHES]) /*if val differs */\\ {report[SWITCHES]=rpt_sw; SETBIT(status,RPTCHNG);}} /**********************************************************************/ /* These are the global variables */ /**********************************************************************/ /*USB related buffers and variables *****************************/ byte usb_buf[8]; /*buffer used for USB */ byte desc_typ, desc_idx; int desc_sze; byte evnt, rxstat, txstat; /*USB status temp storage */ byte usb_cfg; /*usb config. setting */ byte usb_idl; /*usb idle setting */ #define THROTTLE 0 /*throttle value */ /*Misc. variables ***********************************************/ byte ticks; /*real time ticks (10/sec)*/ byte suscntr; /*suspend timeout counter */ byte rcount3; /*cnt of bytes in RX FIFO3*/ byte setaddr; /*SET_ADDRESS state var. */ byte stalld; byte status; byte dtapid; /*these are the bit definitions for the status variable *********/ #define RPTBUSY BIT1 /*set when report changes*/ #define RPTCHNG BIT2 /*set for HID data changes*/ #define DEBUG BIT3 /*set when host listening */ #define MLTIPKT BIT4 /*set for multi-packet ops*/ #define GETDESC BIT5 /*set for get_descr. req. */ #define GETRPRT BIT6 /*set for get_report req. */ #define USB_CMD BIT7 /*set when doing usb cmd */ /*sequence is underway */ /*these are the bit definitions for the dtapid variable *********/ #define TGL0PID BIT0 /*tracks NEXT data PID */ #define TGL1PID BIT1 /*tracks NEXT data PID */ #define TGL2PID BIT2 /*tracks NEXT data PID */ #define TGL3PID BIT3 /*tracks NEXT data PID */ //This is the cmd buffer for cmds received via the cmd channel ** //the order here is critical, and should not change ************* /* byte rsnc; //[+0]sync code (AAh exp) * byte rcmd; //[+1]command op code * byte rdta; //[+2]data for command * byte radh; //[+3]address (msb) * byte radl; //[+4] (lsb) * byte rcks; //[+5]checksum * */ // byte brd_id; /*our unique ID */ #define RPT_DESC_SIZE sizeof(ReportDescriptor) #include \"descrpt.h\" /*dev and cfg descriptors*/ #define DEV_DESC_SIZE sizeof(DEV_DESC) #define CFG_DESC_SIZE sizeof(CFG_DESC) /**********************************************************************/ /* These are the function prototypes */ /**********************************************************************/ void trktim(void); void queue_chngs(void); //void do_cmd(void); /**********************************************************************/ /* This is the real time clock handler, which is set to occur at a */ /* 100 Hz rate: */ /**********************************************************************/ void realtime_ih(void) interrupt 5 //using 1 定时器2中断服务程序 10ms { TF2=0; if (++ticks>50) /*adjust the tick count */ { ticks=0; queue_chngs(); trktim(); /*keep track of real time */ } } /**********************************************************************/ /* This is the code area */ /**********************************************************************/ //char data * xdata zz /*外部RAM指针指向内部RAM数据*/? void write_usb(byte adr, byte dta) { byte xdata * data pt; USB_CS=0; pt=adr; *pt=dta; USB_CS=1; } byte read_usb(byte adr) { byte temp; byte xdata * data pt; USB_CS=0; pt=adr; temp=*pt; USB_CS=1; return (temp); /*return the reg data */ } /**********************************************************************/ /* This subroutine loads a byte from a descriptor or report into the */ /* endpoint 0 fifo. */ /**********************************************************************/ void mlti_pkt(void) { byte pckt_dta; if(desc_sze>0) { if(TSTBIT(status,GETDESC)) switch (desc_typ) /*descriptor **************/ { case DEVICE: pckt_dta=DEV_DESC[desc_idx]; break; case CONFIGURATION: pckt_dta=CFG_DESC[desc_idx]; break; case XSTRING: pckt_dta=STR_DATA[desc_idx]; break; case HID: pckt_dta=CFG_DESC[desc_idx]; break; case HIDREPORT: pckt_dta=ReportDescriptor[desc_idx];//刚改 break; default: /*UNDEFINED */ pckt_dta=0; break; } else switch (desc_typ) /*report ******************/ { default: /*UNDEFINED */ pckt_dta=0; break; } write_usb(TXD0,pckt_dta); /*send data to the FIFO */ desc_sze--; /*decriment size */ desc_idx++; /*increment index */ } } /**********************************************************************/ /* This subroutine loads a byte from a descriptor or report into the */ /* specified fifo. */ /**********************************************************************/ void queue_rpt(byte txd) { write_usb(txd,sum+1); write_usb(txd,sum+2); write_usb(txd,sum+3); write_usb(txd,sum+4); sum+=1; } /**********************************************************************/ /* This subroutine initializes the 9602. */ /**********************************************************************/ void init_usb(void) {byte i; //这两种初始化方式均可工作, 但上一种好象更正常 //toss out any previous state ********************************** CLR_MLTIPKT; //exit multi-packet mode / usb_cfg = 0; for (i = 0; i < 0xff; i++) { write_usb(CCONF, i % 0x10); if (read_usb(CCONF) != (i % 0x10))i=0; } //give a soft reset, then set ints to push pull, active hi or lo/ write_usb(MCNTRL,SRST); while(read_usb(MCNTRL) & 0x01)_nop_(); write_usb(MCNTRL,VREG_ST+INTR_TYPE); //initialize the clock generator ******************************* // prior to this point, the clock output will be 4 Mhz. After, // it will be (48 MHz/CLKDIV) #ifdef BUSPOWER write_usb(CCONF,CODIS+CLKDIV-1); //disable clock output // Enable Halt on suspend, wake from USB, clear pending flags write_usb(WKUP,(HOS|ENUSB|WKMODE)); #else write_usb(CCONF,CLKDIV-1); //set clock freq #endif //--------- Workaround for Voltage Regulator Output issue-------- write_usb(0x1f,0x40); //set default address, enable EP0 only ************************* write_usb(FAR,AD_EN+0); write_usb(EPC0, 0x00); //set up interrupt masks *************************************** write_usb(NAKMSK,NAK_O0+NAK_I1); //NAK evnts write_usb(TXMSK,TXFIFO0+TXFIFO1); //TX events write_usb(RXMSK,RXFIFO0+RXFIFO1); //RX events write_usb(ALTMSK,NORMAL_ALTMSK); //ALT evnts write_usb(MAMSK,(INTR_E+RX_EV+NAK+TX_EV+ALT)); //enable the receiver and go operational *********************** FLUSHTX0; //flush TX0 and disable write_usb(NFSR,OPR_ST); //go operational write_usb(RXC0,RX_EN); //enable the receiver write_usb(MCNTRL,VREG_ST+INTR_TYPE+NAT); //set NODE ATTACH /* //toss out any previous state ********************************** CLR_MLTIPKT; //exit multi-packet mode usb_cfg = 0; for (i = 0; i < 0xff; i++) { write_usb(CCONF, i % 0x10); if (read_usb(CCONF) != (i % 0x10))i=0; } //initialize the clock generator ******************************* write_usb(CCONF,CLKDIV-1); //set clock freq //give a soft reset, then set ints to push pull, active hi or lo write_usb(MCNTRL,SRST); while(read_usb(MCNTRL) & 0x01)_nop_(); write_usb(MCNTRL,VREG_ST+INTR_TYPE); write_usb(MAMSK, 0); //set up interrupt masks *************************************** write_usb(NAKMSK,NAK_O0); //NAK evnts write_usb(TXMSK,TXFIFO0+TXFIFO1); //TX events write_usb(RXMSK,RXFIFO0+RXFIFO1); //RX events write_usb(ALTMSK,NORMAL_ALTMSK); //ALT evnts write_usb(MAMSK,(INTR_E+RX_EV+NAK+TX_EV+ALT)); //--------- Workaround for Voltage Regulator Output issue-------- write_usb(0x1f,0x40); write_usb(FAR,read_usb(FAR)|0); write_usb(FAR,read_usb(FAR)|AD_EN); //enable the receiver and go operational *********************** FLUSHTX0; //flush TX0 and disable write_usb(RXC0,RX_EN); //enable the receiver write_usb(NFSR,OPR_ST); //go operational write_usb(MCNTRL,VREG_ST+INTR_TYPE+NAT); //set NODE ATTACH */ } /**********************************************************************/ /* The CLEAR_FEATURE request is done here */ /**********************************************************************/ void clrfeature(void) { switch (usb_buf[0]&0x03) /*find request target */ { case 0: /*DEVICE */ break; case 1: /*INTERFACE */ break; case 2: /*ENDPOINT */ switch (usb_buf[4]&0x0F) /*find specific endpoint */ { /* (strip off dir. bit) */ case 0: write_usb(EPC0,(read_usb(EPC0)&(~STALL)));//bitclr(EPC0,STALL); CLRBIT(stalld,BIT0); break; case 1: write_usb(EPC0,(read_usb(EPC1)&(~STALL)));//bitclr(EPC1,STALL); CLRBIT(stalld,BIT1); break; case 2: write_usb(EPC0,(read_usb(EPC2)&(~STALL)));//bitclr(EPC2,STALL); CLRBIT(stalld,BIT2); break; default: break; } break; default: /*UNDEFINED */ break; } } /**********************************************************************/ /* The GET_DESCRIPTOR request is done here. */ /**********************************************************************/ void getdescriptor(void) { SET_GETDESC; /*enter GETDESC mode */ desc_typ = usb_buf[3]; /*store the type requested*/ /*select descriptor size and starting index */ switch (desc_typ) { case DEVICE: // desc_idx = 0; desc_sze = DEV_DESC_SIZE; break; case CONFIGURATION: desc_idx = 0; desc_sze = CFG_DESC_SIZE; break; case XSTRING: INT_LED=!INT_LED; desc_idx = usb_buf[2]; desc_sze = STR_DATA[desc_idx]; break; case HID: /*valid if we have only one int: revisit if this changes */ desc_idx = CFG_LENGTH+INT_LENGTH; desc_sze = CFG_DESC[(CFG_LENGTH+INT_LENGTH)]; break; case HIDREPORT://刚改 desc_idx = 0; desc_sze = RPT_DESC_SIZE; break; default: /*UNDEFINED */ desc_idx = 0; desc_sze = 0; break; } /*adjust size, if the host has asked for less than we want to */ /*send. Note that we only check the low order byte of the */ /*wlength field. If we ever need to send back descriptors */ /*longer than 256 bytes, we\'ll need to revisit this */ if (usb_buf[7]==0) /*if less than 256 req\'d */ if (desc_sze > usb_buf[6]) desc_sze = usb_buf[6]; /*send the first data chunk back */ mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); } /**********************************************************************/ /* The GET_STATUS request is done here */ /**********************************************************************/ void getstatus(void) { switch (usb_buf[0]&0x03) /*find request target */ { case 0: /*DEVICE */ //write_usb(TXD0,0); /*first byte is reserved */ write_usb(TXD0,1); //自供电 D1:远程唤醒; D0:自给电源 break; case 1: /*INTERFACE */ write_usb(TXD0,0); /*first byte is reserved */ break; case 2: /*ENDPOINT */ switch (usb_buf[4]&0x0F) /*find specific endpoint */ { /* (strip off dir. bit) */ case 0: EPSTATUS(BIT0); case 1: EPSTATUS(BIT1); case 2: EPSTATUS(BIT2); default: break; } break; default: /*UNDEFINED */ write_usb(TXD0,0); /*first byte is reserved */ break; } write_usb(TXD0,0); /*second byte is reserved */ } /**********************************************************************/ /* The SET_CONFIGURATION request is done here */ /**********************************************************************/ void setconfiguration(void) { usb_cfg = usb_buf[2]; /*set the configuration # */ if (usb_buf[2]!=0) /*set the configuration */ { dtapid = 0; /*FIRST PID is DATA0 */ stalld = 0; /*nothing stalled */ FLUSHTX1; /*flush TX1 and disable */ write_usb(EPC1,EP_EN+01); /*enable EP1 at adr 1 */ FLUSHRX1; /*flush RX1 and disable */ write_usb(EPC2,EP_EN+02); /*enable EP2 at adr 2 */ write_usb(RXC1,RX_EN); /*enable RX1 */ } else /*unconfigure the device */ { write_usb(EPC1,0); /*disable EP1 */ write_usb(EPC2,0); /*disable EP2 */ } } /**********************************************************************/ /* The SET_FEATURE request is done here */ /**********************************************************************/ void setfeature(void) { switch (usb_buf[0]&0x03) /*find request target */ { case 0: /*DEVICE */ break; case 1: /*INTERFACE */ break; case 2: /*ENDPOINT */ switch (usb_buf[4]&0x0F) /*find specific endpoint */ { /* (strip off dir. bit) */ case 0: /*control pipes must accept setup requests even if */ /*stalled, so we log the stall here, but don\'t */ /*actually do it */ /*bitset(EPC0,STALL);*///write_usb(EPC0,(read_usb(EPC0)|(STALL))); SETBIT(stalld,BIT0); break; case 1: write_usb(EPC1,(read_usb(EPC1)|(STALL)));//bitset(EPC1,STALL); SETBIT(stalld,BIT1); break; case 2: write_usb(EPC2,(read_usb(EPC2)|(STALL)));//bitset(EPC2,STALL); SETBIT(stalld,BIT2); break; default: break; } break; default: /*UNDEFINED */ break; } } /**********************************************************************/ /* The HID class specific GET_REPORT request is done here */ /**********************************************************************/ void getreport(void) { desc_typ = usb_buf[3]; /*store the type requested*/ queue_rpt(TXD0); /*queue up the report */ } /**********************************************************************/ /* The HID class specific SET_REPORT request is done here */ /**********************************************************************/ void setreport(void) { desc_typ = usb_buf[3]; /*store the report req\'d */ } /**********************************************************************/ /* The HID class specific GET_IDLE request is done here */ /**********************************************************************/ void getidle(void) { write_usb(TXD0,usb_idl); /*send back idle value */ } /**********************************************************************/ /* The HID class specific SET_IDLE request is done here */ /**********************************************************************/ void setidle(void) { usb_idl = usb_buf[3]; /*store the idle value */ } /**********************************************************************/ /* This subroutine handles RX events for FIFO0 (endpoint 0) */ /**********************************************************************/ void rx_0(void) { rxstat=read_usb(RXS0); //get receiver status //is this a setup packet? ************************************** if(rxstat & SETUP_R) { //read data payload into buffer then flush/disble the RX *** for(desc_idx=0; desc_idx<8; desc_idx++) usb_buf[desc_idx] = read_usb(RXD0); FLUSHRX0; //make sure the RX is off FLUSHTX0; //make sure the TX is off write_usb(EPC0,(read_usb(EPC0)&(~STALL))); // bitclr(EPC0,STALL); //turn off stall switch (usb_buf[0]&0x60) //decode request type //D6..5: 种类:0=标准;1=类;2=厂商;3=保留 //D4..0: 接受者:0=设备;1=接口;2=端点;3=其他;4..31=保留 { case 0x00: //standard request switch (usb_buf[1]) //decode request code { case CLEAR_FEATURE: clrfeature(); break; case GET_CONFIGURATION: write_usb(TXD0,usb_cfg);//load the config val break; case GET_DESCRIPTOR: getdescriptor(); break; case GET_INTERFACE: write_usb(TXD0,0); //load the intf. val break; case GET_STATUS: getstatus(); break; case SET_ADDRESS: //save the new address, but don\'t actually store it into FAR until later //(when status handshake completes during tx_0). Note that the 9602 has // a DEF bit in EPC0 designed for this purpose, but it only works if the //default address is initially in effect. Therefore it can\'t be used for //multiple SET_ADDRESS commands in sequence. This will work regardless of //initial address. INT_LED=0; setaddr = (usb_buf[2] | AD_EN); break; case SET_CONFIGURATION: setconfiguration(); break; case SET_FEATURE: setfeature(); break; case SET_INTERFACE: if(usb_buf[2]) //if the requested intf!=0 write_usb(EPC0,(read_usb(EPC0)|(STALL)));//bitset(EPC0,STALL); //stall the endpoint break; default: //unsupported standard req write_usb(EPC0,(read_usb(EPC0)|(STALL)));//bitset(EPC0,STALL); //stall the endpoint break; } break; case 0x20: //class request switch (usb_buf[1]) //decode request code { case GET_REPORT: getreport(); break; case SET_REPORT: setreport(); break; case GET_IDLE: getidle(); break; case SET_IDLE: setidle(); break; default: //unsupported standard req write_usb(EPC0,(read_usb(EPC0)|(STALL)));// bitset(EPC0,STALL); //stall the endpoint break; } break; default: //unsupported req type write_usb(EPC0,(read_usb(EPC0)|(STALL)));// bitset(EPC0,STALL); //stall the endpoint break; } //the following is done for all setup packets. Note that if //no data was stuffed into the FIFO, the result of the fol- //lowing will be a zero-length response. write_usb(TXC0,TX_TOGL+TX_EN); //enable the TX (DATA1) CLRBIT(dtapid,TGL0PID); //store NEXT PID state } //if not a setup packet, it must be an OUT packet ************** // Note that there is no RX_ERR bit in RXS0, so we don\'t look // for and handle them the way we do in the other RX event // handlers. else { if (TSTBIT(status,MLTIPKT)) //multi-pkt status stage? { //test for errors (zero length, correct PID) if ((rxstat& 0x5F)!=0x10) //length error?? { } CLR_MLTIPKT; //exit multi-packet mode FLUSHTX0; //flush TX0 and disable } write_usb(RXC0,RX_EN); //re-enable the receiver } //we do this stuff for all rx_0 events ************************* } /**********************************************************************/ /* This subroutine handles RX events for FIFO1 (endpoint 2) */ /**********************************************************************/ void rx_1(void) { rxstat=read_usb(RXS1); /*get receiver status */ if(rxstat & SETUP_R) { } else if (rxstat & RX_ERR) { } else { /*check to see if this is a valid command packet **************/ /*we don\'t have to worry about the UART receiver stomping on */ /*us because it has a lower priority interrupt. The USB might*/ /*well stomp the UART\'s data, but the assumption is that any */ /*debug activity on the RS-232 port is stompable */ SETBIT(status,USB_CMD); /*select USB command mode */ /* rsnc=read_usb(RXD1); //move data from FIFO rcmd=read_usb(RXD1); rdta=read_usb(RXD1); radh=read_usb(RXD1); radl=read_usb(RXD1); rcks=read_usb(RXD1); if (rsnc==SYNCBYT) //if sync code is valid if (rcks==(unsigned char)(rsnc+rcmd+rdta+radh+radl)) { FLUSHTX1; //flush TX1 and disable do_cmd(); //do the command TXEN1_PID_NO_TGL; //enable TX, choose PID }*/ CLRBIT(status,USB_CMD); //exit USB command mode } FLUSHRX1; /*flush RX1 and disable */ write_usb(RXC1,RX_EN); /*re-enable the receiver */ } /**********************************************************************/ /* This subroutine handles TX events for FIFO0 (endpoint 0) */ /**********************************************************************/ void tx_0(void) { txstat=read_usb(TXS0); /*get transmitter status */ if(txstat & TX_DONE) /*if transmit completed */ { FLUSHTX0; /*flush TX0 and disable */ if(txstat & ACK_STAT) /*ACK received: xmit ok */ { /*if in multi-packet mode, queue next piece if nec. */ if(TSTBIT(status,MLTIPKT)) { /*move the data into the FIFO */ mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); mlti_pkt(); TXEN0_PID; /*enable TX, choose PID */ } else /*not in multi-packet mode*/ { if(setaddr) /*if SET_ADDRESS in progr.*/ { write_usb(FAR,setaddr); /*load new address */ setaddr=0; /*clear state */ } write_usb(RXC0,RX_EN); /*re-enable the receiver */ } } else /*no ACK: xmit failed */ /*this probably means we issued a stall handshake */ { CLR_MLTIPKT; /*exit multi-packet mode */ write_usb(RXC0,RX_EN); /*re-enable the receiver */ } } /*otherwise something must have gone wrong with the previous ****/ /*transmission, or we got here somehow we shouldn\'t have ********/ else /*xmit didn\'t complete?? */ { } /*we do this stuff for all tx_0 events **************************/ } /**********************************************************************/ /* This subroutine handles TX events for FIFO1 (endpoint 1) */ /**********************************************************************/ void tx_1(void) { txstat=read_usb(TXS1); /*get transmitter status */ /*if a transmission has completed successfully, update the data */ /*toggle and queue up a dummy packet ****************************/ if ((txstat & ACK_STAT) && (txstat & TX_DONE)) { // TGLBIT(dtapid,TGL1PID); /*flip the data toggle */ // FLUSHTX1; /*flush the FIFO */ // write_usb(TXD1,0x0aa); /*send data to the FIFO */ // write_usb(TXD1,0x0aa); /*send data to the FIFO */ // write_usb(TXD1,0x0aa); /*send data to the FIFO */ // write_usb(TXD1,0x0aa); /*send data to the FIFO */ // queue_rpt(TXD1); // TXEN1_PID_NO_TGL; /*enable TX, choose PID */ INT_LED=!INT_LED; } else { } } /**********************************************************************/ /* This subroutine handles OUT NAK events for FIFO0 (endpoint 0) */ /**********************************************************************/ void onak0(void) { /*important note: even after servicing a NAK, another NAK */ /*interrupt may occur if another \'OUT\' or \'IN\' packet comes in */ /*during our NAK service. */ /*if we\'re currently doing something that requires multiple \'IN\'*/ /*transactions, \'OUT\' requests will get NAKs because the FIFO is*/ /*busy with the TX data. Since the \'OUT\' here means a premature*/ /*end to the previous transfer, just flush the FIFO, disable the*/ /*transmitter, and re-enable the receiver. */ if (TSTBIT(status,MLTIPKT)) /*multi-pkt status stage? */ { CLR_MLTIPKT; /*exit multi-packet mode */ FLUSHTX0; /*flush TX0 and disable */ write_usb(RXC0,RX_EN); /*re-enable the receiver */ } /*we do this stuff for all onak0 events **************************/ } /**********************************************************************/ /* This subroutine puts the board to sleep, to reduce the overall */ /* current consumption in the suspend mode. */ /**********************************************************************/ void deep_sleep(void) { //USB_LED=0;INT_LED=0; #ifdef BUSPOWER /*Turn everything extraneous on the board off. The analog sub- */ /*section will be turned off, so all signals going into it must */ /*be driven low, including the CS*. */ PORTDD.BIT4= 1; PORTDD.BIT7= 1; /*turn LEDs OFF */ MWSR = 0; /*drive SO low */ A2DCSON; /*drive CS* low */ ANALGOFF; /*turn off analog power */ /*Set up the wake input */ WKEN.UWK = 0; /*disable the wake input */ WKEDG.UWK = 0; /*wake on falling edge */ WKPND.UWK = 0; /*clear any pending wake */ WKEN.UWK = 1; /*enable the wake input */ /*Stop everything, including the processor clock */ halt: PORTGD.BIT7= 1; /*halt processor */ int i; for (i=0;i<2;i++); /*We get here only when awakened. Start everything back up. */ wake: ANALGON; /*turn on analog power */ A2DCSOFF; /*restore analog CS* */ write_usb(WKUP,(HOS|ENUSB|WKMODE)); /*clear pending wake evnt */ write_usb(ALTMSK,NORMAL_ALTMSK); /*adjust interrupts */ write_usb(NFSR,OPR_ST); /*go operational */ #endif } /**********************************************************************/ /* This subroutine handles USB \'alternate\' events. */ /**********************************************************************/ void usb_alt(void) { evnt = read_usb(ALTEV); /*check the events */ if(evnt & RESET_A) /*reset event */ { write_usb(NFSR,RST_ST); //enter reset state write_usb(FAR,AD_EN+0); //set default address write_usb(EPC0, 0x00); //enable EP0 only FLUSHTX0; //flush TX0 and disable //adjusting ints is nec. here in case we were in suspend write_usb(ALTMSK,NORMAL_ALTMSK);//adjust interrupts write_usb(NFSR,OPR_ST); //go operational write_usb(RXC0,RX_EN); //enable the receiver //下面的程序有问题 /* write_usb(EPC0, read_usb(EPC0) & ~STALL); write_usb(NFSR,RST_ST); //enter reset state while(read_usb(MCNTRL) & 0x01)_nop_(); write_usb(EPC0, 0x00); write_usb(FAR,read_usb(FAR)|0); write_usb(FAR,read_usb(FAR)|AD_EN); FLUSHTX0; FLUSHRX0; write_usb(ALTMSK,NORMAL_ALTMSK);//adjust interrupts write_usb(NFSR,OPR_ST); //go operational write_usb(RXC0,RX_EN); */ } else if(evnt & RESUME_A) /*resume event */ { write_usb(ALTMSK,NORMAL_ALTMSK);/*adjust interrupts */ write_usb(NFSR,OPR_ST); /*go operational */ } else if((evnt & SD3)&&(suscntr==0)) /*suspend event */ { write_usb(ALTMSK,SUSPND_ALTMSK);/*adj interrupts */ write_usb(NFSR,SUS_ST); /*enter suspend state */ deep_sleep(); /*reduce power cons. */ suscntr=SUSPND_TO; /*start suspend cntr */ } else /*spurious alt. event! */ { } } /**********************************************************************/ /* This is the interrupt service routine for USB operations */ /**********************************************************************/ void usb_isr(void)interrupt 0 //using 2 { evnt = read_usb(MAEV); /*check the events */ if (evnt & RX_EV) { evnt=read_usb(RXEV); /*check the RX events */ if (evnt&RXFIFO0) {rx_0(); }/*endpoint 0 */ else if (evnt&RXFIFO1) {rx_1(); } /*endpoint 2 */ else /*some other RX event */ { } } else if (evnt & TX_EV) { evnt=read_usb(TXEV); /*check the TX events */ if (evnt&TXFIFO0) tx_0(); /*endpoint 0 */ else if (evnt&TXFIFO1) tx_1(); /*endpoint 1 */ else /*some other TX event */ { } } else if (evnt & ALT) /*alternate event? */ { usb_alt(); } /*NAKs can come so fast and furious (especially with OHCI hosts)*/ /*that they MUST have a lower priority than the other events. If*/ /*they did not, the other events could get starved out. */ else if (evnt & NAK) { evnt=read_usb(NAKEV); /*check the NAK events */ if (evnt&NAK_O0) onak0(); /*endpoint 0 */ // else if (evnt&NAK_O1) onak1(); /*endpoint 2 */ else /*some other NAK event */ { } } else /*spurious event! */ { } /*the 9602 produces interrupt LEVELS, the COP looks for edges. */ /*So we have to fool the 9602 into producing new edges for us */ /*when we are ready to look for them. We do this by temporarily*/ /*disabling the interrupts, then re-enabling them. */ evnt=read_usb(MAMSK); /*save old mask contents */ write_usb(MAMSK,0); /*disable interrupts */ write_usb(MAMSK,evnt); /*re-enable interrupts */ } /**********************************************************************/ /* This subroutine updates the given a/d report variable as necessary.*/ /**********************************************************************/ /*void update(byte chnl, byte *val) { chnl = A2D_conv(chnl); //convert the channel if (chnl<MINJOY) chnl=MINJOY; //check and fix the limits if (chnl>MAXJOY) chnl=MAXJOY; chnl-=MINJOY; //adjust for offset chnl=JOY_DATA[chnl]; //linearize result if(chnl!=*val) //if value is different { *val=chnl; //store the new value SETBIT(status,RPTCHNG); //flag the value change } }*/ /**********************************************************************/ /* This subroutine queues changes, if anyreport variable as necessary.*/ /**********************************************************************/ void queue_chngs(void) { /*This procedure uses the microwire port, which is also used by */ /*the interrupt routines. Since this procedure is called from */ /*the main loop, we must temporarily disable interrupts to en- */ /*sure that we don\'t step on ourselves. */ /*if there is new data to report and the xmitter is not loaded */ if((TSTBIT(status,RPTCHNG)) && (!TSTBIT(status,RPTBUSY))) { TGLBIT(dtapid,TGL1PID); /*flip the data toggle */ FLUSHTX1; /*flush the FIFO */ EA=0; //dsable global interrupt queue_rpt(TXD1); //queue a report TXEN1_PID_NO_TGL; //enable TX, choose PID EA=1; //enable global interrupt } ; } /**********************************************************************/ /* This is the handler for keeping track of the real time. This proc.*/ /* is called every 0.5 seconds. */ /**********************************************************************/ void trktim(void) { WDR1=1; WDR2=1; //看门狗定时器刷新 USB_LED=!USB_LED; /*heartbeat (1 Hz flash) */ SETBIT(status,RPTCHNG); /*do regular report */ if(suscntr>0) suscntr--; /*decriment until 0 */ } /**********************************************************************/ /* This subroutine parses commands received through the cmd channel: */ /**********************************************************************/ /*void do_cmd(void) { switch (rcmd) { case \'p\': //look for 9602 prog (wr) write_usb(radl,rdta); //write the spec. 9602 reg//将接收到的命令写入指定的USB寄存器中 break; case \'i\': //look for init USB cmd init_usb(); //initialize the 9602 break; default: write_usb(TXD1,\'?\'); //we\'re confused... help!! } //end of switch ; }*/ /**********************************************************************/ /* This is the main program loop: **/ /**********************************************************************/ main() { /*Misc. Initialization ******************************************/ /*Make sure that the stack is initialized before any function */ /*calls. This is microcontroller and compiler dependent. */ // INITREGS; /*init stack and mem regs */ // rcks = 0; /*clear receive buffer */ status = 0; /*clear status bits */ setaddr = 0; /*clear SET_ADDRESS state */ ticks = 0; /*clear real time ticks */ suscntr = SUSPND_TO; /*clear sus. timeout cntr */ rcount3 = 0; /*clear RX FIFO3 count */ IT0=1; //外部中断0设置:IT0=1:下降沿触发;IT0=0:低电平触发 EX0=1; //开外部中断0 T2CON=0; //定时器2控制寄存器清0 TL2=0xB5; TH2=0xDC; RCAP2L=0xB5; RCAP2H=0xDC; //100Hz中断 ET2=1; //定时器2中断允许 TR2=1; //定时器2定时允许 WDCON=0xE0; //看门狗定时器设置:2.048s复位 //WDE=1; //看门狗使能 init_usb(); /*initialize 9602 */ /*Turn on interrupts now ****************************************/ INTSON; /*turn on interrupts */ /*This is the primary code loop *********************************/ //queue_rpt(TXD1); while (TRUE) /*then loop forever */ { // update(0,&report[JOYX]); /*update X channel */ // update(1,&report[JOYY]); /*update Y channel */ //queue_chngs(); /*queue changes, if any */ // queue_chngs(); } return(0); /*make the compiler happy */ } Hid report定义为: unsigned char idata ReportDescriptor[22]= { 0x06, 0x00,/*0xa0*/ 0xff, // USAGE_PAGE (vendor defined) 0x09, /*0xa5*/0x01, //Usage (vendor defined) 0xa1, 0x01, //Collection (Application) 0x09, /*0xa6*/0x02, // USAGE (vendor defined) 0x09, /*0xa7*/0x03, // USAGE (vendor defined) 0x15, 0x80, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (128) 0x75, 0x08, // REPORT_SIZE (8 bits) 0x95, 0x04, // REPORT_COUNT (1 fields) 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 0xc0 /* END_COLLECTION */ }; |
|
沙发#
发布于:2003-05-24 10:25
你好!!!
我用的班子和你的一样,情况也是一样的,我也不明白是为什么??? 你的问题解决了吗???我们能探讨一下吗??? qq:121144437 |
|