STM32 USB HID通讯模式下的双向数据传输及参数配置详解

目录

一、 usb_desc.c

1.配置描述符

2.报文描述符

二、usb_prop.c

三、usb_conf.h

四、usb_endp.c


#define USB_HID_IN_SIZE    26         /*发送数据大小*/

#define USB_HID_OUT_SIZE  0x08   /*接收数据大小*/

  • 一、 usb_desc.c

  • 1.配置描述符

  • const uint8_t XXXX_ConfigDescriptor[XXXX_SIZ_CONFIG_DESC] =
    {
        0x09,         /* bLength: Configuration Descriptor size */
        USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
        XXXX_SIZ_CONFIG_DESC,          /* wTotalLength: Bytes returned */
        0x00,
        0x01,         /*bNumInterfaces: 1 interface*/
        0x01,         /*bConfigurationValue: Configuration value*/
        0x00,         /*iConfiguration: Index of string descriptor describing
                                        the configuration*/
        0x80,         /*bmAttributes: Self powered */
        0x64,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
    
        /************** Descriptor of XXXX Mouse interface ****************/
        /* 09 */
        0x09,         /*bLength: Interface Descriptor size*/
        USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
        0x00,         /*bInterfaceNumber: Number of Interface*/
        0x00,         /*bAlternateSetting: Alternate setting*/
        0x02,         /*bNumEndpoints*/
        0x03,         /*bInterfaceClass: HID*/
        0x14,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
        0x04,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
        0,            /*iInterface: Index of string descriptor*/
        /******************** Descriptor of XXXX Mouse HID ********************/
        /* 18 */
        0x09,         /*bLength: HID Descriptor size*/
        HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
        0x10,         /*bcdHID: HID Class Spec release number*/
        0x01,
        0x00,         /*bCountryCode: Hardware target country*/
        0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
        0x22,         /*bDescriptorType*/
        XXXX_SIZ_REPORT_DESC,/*wItemLength: Total length of Report descriptor*/
        0x00,
        /******************** Descriptor of XXXX Mouse endpoint ********************/
        /* 27 */
        0x07,          /*bLength: Endpoint Descriptor size*/
        USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:  */
    
        0x81,          /*bEndpointAddress: Endpoint Address (IN)*/
        0x03,          /*bmAttributes: Interrupt endpoint*/
        USB_HID_IN_SIZE,          /*wMaxPacketSize: 20 Byte max */
        0x00,
        0x05,          /*bInterval: Polling Interval (5 ms)*/
        /* 34 */
    	0x07,          /*bLength: Endpoint Descriptor size*/
        USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
    
        0x02,          /*bEndpointAddress: Endpoint Address (OUT)*/
        0x03,          /*bmAttributes: Interrupt endpoint*/
        USB_HID_OUT_SIZE,          /*wMaxPacketSize: 16 Byte max */
        0x00,
        0x14,          /*bInterval: Polling Interval (20 ms)*/
        /* 41 */
    }; /* XXXX_ConfigDescriptor */
    

            配置USB设备为HID设备,配置IN端点1,发送数据;OUT端点2接收数据;并定义收发的字节数大小;

    2.报文描述符

    const uint8_t XXXX_ReportDescriptor[XXXX_SIZ_REPORT_DESC] =
    {
    	0x05,0x01,           /*Usage Page(Generic Desktop)*/
        0x09,0x00,           /*Usage(Vendor defined)*/   
        0xA1,0x01,           /*Collection(Application)*/
    	
    	0x09,0x00,          /*	Usage(Vendor defined)*/  
        0x75,0x08,          /*	Report Size(8)*/
    	0x95,USB_HID_IN_SIZE,   		/*	Report Count(20)*/   
    	0x81,0x02,          /*	Input(Variable, Data)*/
    
    	0x09,0x00,           /*	Usage(Vendor defined)*/
        0x75,0x08,           /*	Report Size(8)*/  
        0x95,USB_HID_OUT_SIZE,  		/*	Report Count(8)*/  
    	0x91,0x02, 		   	/*	Output(Variable, Data)*/
    	
        0xC0		   		/*	End Collection*/
    }; /* XXXX_ReportDescriptor */
    

            配置IN、OUT端点数据的大小和个数;

    二、usb_prop.c

    void XXXX_Reset(void)
    {
      /* Set XXXX_DEVICE as not configured */
      pInformation->Current_Configuration = 0;
      pInformation->Current_Interface = 0;/*the default Interface*/
    
      /* Current Feature initialization */
      pInformation->Current_Feature = XXXX_ConfigDescriptor[7];
      SetBTABLE(BTABLE_ADDRESS);
      /* Initialize Endpoint 0 */
      SetEPType(ENDP0, EP_CONTROL);
      SetEPTxStatus(ENDP0, EP_TX_STALL);
      SetEPRxAddr(ENDP0, ENDP0_RXADDR);
      SetEPTxAddr(ENDP0, ENDP0_TXADDR);
      Clear_Status_Out(ENDP0);
      SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
      SetEPRxValid(ENDP0);
    
      /* Initialize Endpoint 1 */
      SetEPType(ENDP1, EP_INTERRUPT);
      SetEPTxAddr(ENDP1, ENDP1_TXADDR);
      SetEPTxCount(ENDP1, USB_HID_IN_SIZE);
      SetEPRxStatus(ENDP1, EP_RX_DIS);
      SetEPTxStatus(ENDP1, EP_TX_NAK);
    
      /* Initialize Endpoint 2 */
      SetEPType(ENDP2, EP_INTERRUPT);
      SetEPRxAddr(ENDP2, ENDP2_RXADDR);
      SetEPRxCount(ENDP2, USB_HID_OUT_SIZE);
      SetEPTxStatus(ENDP2, EP_TX_DIS);
      SetEPRxStatus(ENDP2, EP_RX_VALID);
      
      /* Set this device to response on default address */
      SetDeviceAddress(0);
      bDeviceState = ATTACHED;
    }
    

            复位时,需要初始化对应的端点;端点0用于枚举、端点1用于发送、端点2用于接收。

    三、usb_conf.h

    /*-------------------------------------------------------------*/
    /* EP_NUM */
    /* defines how many endpoints are used by the device */
    /*-------------------------------------------------------------*/
    #define EP_NUM     (3)
    
    /*-------------------------------------------------------------*/
    /* --------------   Buffer Description Table  -----------------*/
    /*-------------------------------------------------------------*/
    /* buffer table base address */
    /* buffer table base address */
    #define BTABLE_ADDRESS      (0x00)
    
    /* EP0  */
    /* rx/tx buffer base address */
    #define ENDP0_RXADDR        (0x18)
    #define ENDP0_TXADDR        (0x58)
    
    /* EP1  */
    /* tx buffer base address */
    #define ENDP1_RXADDR        (0x98)
    #define ENDP1_TXADDR        (0xD8)
    
    /* EP2  */
    #define ENDP2_RXADDR        (0x118)
    #define ENDP2_TXADDR        (0x158)
    
    
    /*-------------------------------------------------------------*/
    /* -------------------   ISTR events  -------------------------*/
    /*-------------------------------------------------------------*/
    /* IMR_MSK */
    /* mask defining which events has to be handled */
    /* by the device application software */
    #define IMR_MSK (CNTR_CTRM  | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM  | CNTR_SOFM \
                     | CNTR_ESOFM | CNTR_RESETM )
    
    /* CTR service routines */
    /* associated to defined endpoints */
    /* #define  EP1_IN_Callback   NOP_Process*/
    #define  EP2_IN_Callback   NOP_Process
    #define  EP3_IN_Callback   NOP_Process
    #define  EP4_IN_Callback   NOP_Process
    #define  EP5_IN_Callback   NOP_Process
    #define  EP6_IN_Callback   NOP_Process
    #define  EP7_IN_Callback   NOP_Process
    
    #define  EP1_OUT_Callback   NOP_Process
    /*#define  EP2_OUT_Callback   NOP_Process*/
    #define  EP3_OUT_Callback   NOP_Process
    #define  EP4_OUT_Callback   NOP_Process
    #define  EP5_OUT_Callback   NOP_Process
    #define  EP6_OUT_Callback   NOP_Process
    #define  EP7_OUT_Callback   NOP_Process
    

            配置端点地址宏定义、端点数宏定义、端点用到的回调函数需要注释掉,即启用该回调函数

    四、usb_endp.c

    /*******************************************************************************
    * Function Name  : EP1_OUT_Callback.
    * Description    : EP1 OUT Callback Routine.
    * Input          : None.
    * Output         : None.
    * Return         : None.
    ****************************************************************************/
    void EP1_IN_Callback(void)
    {
      /* Set the transfer complete token to inform upper layer that the current 
      transfer has been complete */
      PrevXferComplete = 1; 
    }
    void EP2_OUT_Callback(void)
    {
    	uint8_t  rece_buffer[USB_HID_OUT_SIZE]  =  {0};
    	/* 将接收数据从PMA缓冲区复制到rece_buffer中 */
    	USB_SIL_Read(ENDP2, rece_buffer);
    	/* 设置端点的接收状态为有效,因为端点完成接收后会自动设置成停止状态 */
    	SetEPRxStatus(ENDP2, EP_RX_VALID);
    	/* 数据处理 */
    	if(rece_buffer[0] == 0xEE){}
    }
    /*******************************************************************************
    * Function Name : XXXX_Send.
    * Description   : prepares buffer to be sent containing XXXX event infos.
    * Input          : Keys: keys received from terminal.
    * Output        : None.
    * Return value   : None.
    ******************************************************************************/
    void XXXX_Send(u8 *buffer, u16 len)
    {    
    	/* Copy mouse position info in ENDP1 Tx Packet Memory Area*/
    	USB_SIL_Write(EP1_IN, buffer, len); 
    	/* Enable endpoint for transmission */
    	SetEPTxValid(ENDP1);  
    }
    

            在接收回调函数中读取接收到的数据、自定义发送函数。

            已上是调试过程中的一些总结,还有一些其他常见的USB问题如时钟配置、D+上拉、中断配置等均未列出。

            个人调试总结,欢迎指正!

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 USB HID通讯模式下的双向数据传输及参数配置详解

    发表回复