⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb in a nutshell - chapter 7 - pdiusbd11 and pic16f87x example.htm

📁 altra下载线资料。max7000系列
💻 HTM
📖 第 1 页 / 共 4 页
字号:
          maximum data to send. In each case we check the actual length against 
          that of what the host has asked for and trim the size if required. 
          Then we call WriteBuffertoEndpoint which loads the first 8 bytes into 
          the endpoint buffer and increment the pointer ready for the next 8 
          byte packet. </P><PRE>        case TYPE_STRING_DESCRIPTOR:
            printf("\n\rString Descriptor: LANGID = 0x%04x, Index %d\n\r", \
                SetupPacket-&gt;wIndex, SetupPacket-&gt;wValue &amp; 0xFF);
            switch (SetupPacket-&gt;wValue &amp; 0xFF){

                case 0 :  pSendBuffer = (const unsigned char *)&amp;LANGID_Descriptor;
                          BytesToSend = sizeof(LANGID_Descriptor);
                          break;

                case 1 :  pSendBuffer = (const unsigned char *)&amp;Manufacturer_Descriptor;
                          BytesToSend = sizeof(Manufacturer_Descriptor);
                          break;

                default : pSendBuffer = NULL;
                          BytesToSend = 0;
            }
            if (BytesToSend &gt; SetupPacket-&gt;wLength)
                BytesToSend = SetupPacket-&gt;wLength;
            WriteBufferToEndPoint();
            break;
</PRE>
          <P>If any string descriptors are included, there must be a string 
          descriptor zero present which details what languages are supported by 
          the device. Any non zero string requests have a LanguageID specified 
          in wIndex telling what language to support. In our case we cheat 
          somewhat and ignore the value of wIndex (LANGID) returning the string, 
          no matter what language is asked for. </P><PRE>       default:
            ErrorStallControlEndPoint();
            break;
    }
}

void ErrorStallControlEndPoint(void)
{
    unsigned char Buffer[] = { 0x01 };
    /* 9.2.7 RequestError - return STALL PID in response to next DATA Stage Transaction */
    D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP0_IN, Buffer, 1); 
    /* or in the status stage of the message. */
    D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP0_OUT, Buffer, 1);
}
</PRE>
          <P>When we are faced with an invalid request, invalid parameter or a 
          request the device doesn't support, we must report a request error. 
          This is defined in 9.2.7 of the specification. A request error will 
          return a STALL PID in response to the next data stage transaction or 
          in the status stage of the message. However it notes that to prevent 
          unnecessary bus traffic the error should be reported at the next data 
          stage rather than waiting until the status stage. </P><PRE>unsigned char D11ReadEndpoint(unsigned char Endpoint, unsigned char *Buffer)
{
    unsigned char D11Header[2];
    unsigned char BufferStatus = 0;

    /* Select Endpoint */
    D11CmdDataRead(Endpoint, &amp;BufferStatus, 1);

    /* Check if Buffer is Full */
    if(BufferStatus &amp; 0x01)
    {
        /* Read dummy header - D11 buffer pointer is incremented on each read */
        /* and is only reset by a Select Endpoint Command */
        D11CmdDataRead(D11_READ_BUFFER, D11Header, 2);
        if(D11Header[1]) D11CmdDataRead(D11_READ_BUFFER, Buffer, D11Header[1]);
        /* Allow new packets to be accepted */
        D11CmdDataWrite(D11_CLEAR_BUFFER, NULL, 0);
    }
    return D11Header[1];
}

void D11WriteEndpoint(unsigned char Endpoint, const unsigned char *Buffer, unsigned char Bytes)
{
    unsigned char D11Header[2];
    unsigned char BufferStatus = 0;
    D11Header[0] = 0x00;
    D11Header[1] = Bytes;

    /* Select Endpoint */
    D11CmdDataRead(Endpoint, &amp;BufferStatus, 1);
    /* Write Header */
    D11CmdDataWrite(D11_WRITE_BUFFER, D11Header, 2);
    /* Write Packet */
    if (Bytes) D11CmdDataWrite(D11_WRITE_BUFFER, Buffer, Bytes);
    /* Validate Buffer */
    D11CmdDataWrite(D11_VALIDATE_BUFFER, NULL, 0);
}
</PRE>
          <P>D11ReadEndpoint and D11WriteEndpoint are PDIUSBD11 specific 
          functions. The PDIUSBD11 has two dummy bytes prefixing any data read 
          or write operation. The first byte is reserved, while the second byte 
          indicates the number of bytes received or to be transmitted. These two 
          functions take care of this header. </P><PRE>void WriteBufferToEndPoint(void)
{
    if (BytesToSend == 0) { 
        /* If BytesToSend is Zero and we get called again, assume buffer is smaller */
        /* than Setup Request Size and indicate end by sending Zero Lenght packet */
        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);
    } else if (BytesToSend &gt;= 8) {
        /* Write another 8 Bytes to buffer and send */
        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, 8);
        pSendBuffer += 8;
        BytesToSend -= 8;
    } else {
        /* Buffer must have less than 8 bytes left */
        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, BytesToSend);
        BytesToSend = 0;
    }
}
</PRE>
          <P>As we have mentioned previously, WriteBufferToEndPoint is 
          responsible for loading data into the PDIUSBD11 in 8 byte chunks and 
          adjusting the pointers ready for the next packet. It is called once by 
          the handler of a request to load the first 8 bytes into the endpoint 
          buffer. The host will then send an IN token, read this data and the 
          PDIUSBD11 will generate an interrupt. The EP0 IN handler will then 
          call WriteBufferToEndpoint to load in the next packet in readiness for 
          the next IN token from the host. </P>
          <P>A transfer is considered complete if all requested bytes have been 
          read, if a packet is received with a payload less than bMaxPacketSize 
          or if a zero length packet is returned. Therefore if the BytesToSend 
          counter hits zero, we assume the data to be sent was a multiple of 8 
          bytes and we send a zero length packet to indicate this is the last of 
          the data. However if we have less than 8 bytes left to send, we send 
          only the remaining bytes. There is no need to pad the data with zeros. 
          </P><PRE>void loadfromcircularbuffer(void)
{
   unsigned char Buffer[10];
   unsigned char count;

   // Read Buffer Full Status
   D11CmdDataRead(D11_ENDPOINT_EP1_IN, Buffer, 1);

   if (Buffer[0] == 0){
      // Buffer Empty
      if (inpointer != outpointer){
         // We have bytes to send
         count = 0;
         do {
             Buffer[count++] = circularbuffer[outpointer++];
             if (outpointer &gt;= MAX_BUFFER_SIZE) outpointer = 0;
             if (outpointer == inpointer) break; // No more data
            } while (count &lt; 8); // Maximum Buffer Size
         // Now load it into EP1_In
         D11WriteEndpoint(D11_ENDPOINT_EP1_IN, Buffer, count);
         }
   }
}
</PRE>
          <P>The loadfromcircularbuffer() routine handles the loading of data 
          into the EP1 IN endpoint buffer. It is normally called after an EP1 IN 
          interrupt to reload the buffer ready for the next IN token on EP1. 
          However in order to send out first packet, we need to load the data 
          prior to receiving the EP1 IN interrupt. Therefore the routine is also 
          called after data is received on EP1 OUT. </P>
          <P>By also calling the routine from the handler for EP1 OUT, we are 
          likely to overwrite data in the IN Buffer regardless of whether it has 
          been sent or not. To prevent this, we determine if the EP1 IN buffer 
          is empty, before we attempt to reload it with new data. </P><PRE>void D11CmdDataWrite(unsigned char Command, const unsigned char *Buffer, unsigned char Count)
{
    I2C_Write(D11_CMD_ADDR, &amp;Command, 1);
    if(Count) I2C_Write(D11_DATA_ADDR_WRITE, Buffer, Count);
}

void D11CmdDataRead(unsigned char Command, unsigned char Buffer[], unsigned char Count)
{
    I2C_Write(D11_CMD_ADDR, &amp;Command, 1);
    if(Count) I2C_Read(D11_DATA_ADDR_READ, Buffer, Count);
}
</PRE>
          <P>D11CmdDataWrite and D11CmdDataRead are two PDIUSBD11 specific 
          functions which are responsible for sending the I2C Address/Command 
          first and then send or received data on the I2C Bus. Additional lower 
          level functions are included in the source code but have not been 
          reproduced here as it is the intend to focus on the USB specific 
          details. </P>
          <P>This example can be used with the bulkUSB.sys example as part of 
          the Windows DDK's. To load the bulkUSB.sys driver either change the 
          code to identify itself with a VID of 0x045E and a PID of 0x930A or 
          change the bulkUSB.inf file accompanying bulkUSB.sys to match the 
          VID/PID combination you use in this example. </P>
          <P>It is then possible to use the user mode console program, 
          rwbulk.exe to send and receive packets from the circular buffer. Use 
          </P><PRE>	rwbulk -r 80 -w 80 -c 1 -i 1 -o 0
</PRE>
          <P>to send 80 byte chunks of data to the PIC16F876. Using payloads 
          greater than 80 bytes is going to overflow the PIC's circular buffer 
          in BANK1. </P>
          <P>This example has been coded for readability at the expense of code 
          size. It compiles in 3250 words of FLASH (39% capacity of the 
          PIC16F876). </P></UL><A name=Acknowledgments><FONT color=green 
        size=3><B>Acknowledgments</B></FONT></A> 
        <P>A special acknowledgment must go to Michael DeVault of <A 
        href="http://www.devasys.com/">DeVaSys Embedded Systems</A>. This 
        example has been based upon code written by Michael and been 
        effortlessly developed on the <A 
        href="http://www.devasys.com/pd11.htm">USBLPT-PD11</A> DeVaSys USB 
        development board</A> before being ported to the PIC. </P><A 
        name=SourceCode><FONT color=green size=3><B>Downloading the Source 
        Code</B></FONT></A> 
        <UL>
          <P>
          <LI><A 
          href="http://www.beyondlogic.org/usbnutshell/usbpicc12.zip">Version 
          1.2</A>, 14k bytes 
          <P></P>
          <UL><B>Revision History</B><BR><BR>
            <UL>
              <LI>6th April 2002 - Version 1.2 - Increased I2C speed to match 
              that of comment. Improved PDIUSBD11 IRQ Handling 
              <LI>7th January 2002 - Version 1.1 - Added EP1 IN and EP1 OUT Bulk 
              handler routines and made descriptors load from FLASH 
              <LI>31st December 2001 - Version 1.0. </LI></UL></UL></LI></UL>
        <CENTER>
        <TABLE width="80%">
          <TBODY>
          <TR bgColor=green>
            <TD width="50%"><A id=TITLEBLOCK 
              href="http://www.beyondlogic.org/usbnutshell/usb6.htm">&nbsp;<IMG 
              src="USB in a NutShell - Chapter 7 - PDIUSBD11 and PIC16F87x Example.files/HM_More_white_left.gif" 
              border=0>&nbsp;<B> Chapter 6 : USB Requests</B></A> </TD>
            <TD align=right width="50%"><A id=TITLEBLOCK 
              href="http://www.beyondlogic.org/usbnutshell/"><B>Chapter 8 : A 
              Generic USB Driver</B>&nbsp;<IMG 
              src="USB in a NutShell - Chapter 7 - PDIUSBD11 and PIC16F87x Example.files/HM_More_white_right.gif" 
              border=0>&nbsp;</A> </TD></TR>
          <TR><BR><BR><BR><BR>
            <TD vAlign=center bgColor=#ffff80>
              <UL><BR>
                <LI><A 
                href="http://www.beyondlogic.org/usbnutshell/usb6.htm#SetupPacket">The 
                Setup Packet</A> 
                <LI><A 
                href="http://www.beyondlogic.org/usbnutshell/usb6.htm#StandardDeviceRequests">Standard 
                Device Requests</A> 
                <LI><A 
                href="http://www.beyondlogic.org/usbnutshell/usb6.htm#StandardInterfaceRequests">Standard 
                Interface Requests</A> 
                <LI><A 
                href="http://www.beyondlogic.org/usbnutshell/usb6.htm#StandardEndpointRequests">Standard 
                Endpoint Requests</A></LI></UL></TD>
            <TD vAlign=center bgColor=#ffff80><BR><BR>
              <CENTER><FONT color=red>Coming Soon</FONT></CENTER>
              <UL>
                <LI>Chapter 8: Generic USB Driver 
                <LI>Chapter 9: HID Class Description and Example 
          </LI></UL><BR></TD></TR></TBODY></TABLE>
        <TABLE width="80%">
          <TBODY>
          <TR bgColor=green>
            <TD colSpan=2><FONT color=white>
              <CENTER><B>Comments and Feedback?</B></CENTER></FONT></TD></TR>
          <TR bgColor=#ffff80>
            <TD align=right width="30%">
              <FORM action=/cgi-sys/cgiemail/feedback.txt method=post><INPUT 
              type=hidden value=http://www.beyondlogic.org/thanks.html 
              name=success> Comments :<BR>Email Address : </TD>
            <TD width="70%"><INPUT size=60 name=Comments><BR><INPUT size=40 
              name=EmailAddress> (Optional) &nbsp;<INPUT type=submit value=Send> 
            </TD></TR>
          <TR bgColor=#ffff80>
            <TD colSpan=2>
              <CENTER><FONT size=2><I>Copyright 2001-2005 <A 
              href="http://www.beyondlogic.org/about.htm">Craig Peacock</A>, 
              15th June 2005.</I></FONT> 
      </CENTER></TD></TR></TBODY></TABLE></CENTER></UL></TD></TR></TBODY></TABLE></CENTER></FORM></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -