shixt
驱动牛犊
驱动牛犊
  • 注册日期2002-04-26
  • 最后登录2005-04-21
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1432回复:1

HID 伟输,帮忙啊

楼主#
更多 发布于:2003-05-23 23:47
我用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                */
};
zyzyzyzy
驱动牛犊
驱动牛犊
  • 注册日期2003-05-24
  • 最后登录2003-05-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-05-24 10:25
你好!!!
我用的班子和你的一样,情况也是一样的,我也不明白是为什么???
你的问题解决了吗???我们能探讨一下吗???
qq:121144437
游客

返回顶部