STM32 USB 从机HID分析

4 篇文章 0 订阅

STM32 USB 从机HID分析

芯片:STM32F407VE

编译器:KEIL5

作者:SY

日期:2017-7-20 16:01:26

概述

STM32USB初始化为USB从机,使用标准HID协议。控制板自带VBUS供电,因此不需要VBUSGND引脚。

只要连接2根数据线到电脑即可。

源码分析

当使用USB线连接电脑端后,收到电脑端的USB复位包

USBD_OTG_ISR_Handler -->
    DCD_HandleSof_ISR -->
        /* Clear interrupt */
        OTG_HS_GINTSTS->SOF:在设备模式下,模块将该位置 1 时,指示 USB 上已接收到一个 SOF 令牌。应用程序可通过读取设备状态寄存器来获得当前的帧编号。只有在模块以 FS 模式运行时,才会出现此中断。
        GINTSTS.d32 = 0;
        GINTSTS.b.sofintr = 1;
        USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, GINTSTS.d32);

    DCD_HandleUsbReset_ISR -->
        /* Clear the Remote Wake-up Signaling */
        OTG_HS_DCTL->RWUSIG:应用程序将此位置 1 时,模块会启动远程发送信号,以唤醒 USB 主机。应用程序必须将此位置 1 以使模块退出挂起状态。根据 USB 2.0 规范,应用程序必须在将此位置 1 之后的 1 ms 到15 ms 内将其清零。
        dctl.b.rmtwkupsig = 1;
        USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, 0 );

        /* Reset Device Address */
        复位后,设备地址默认为0
        OTG_HS_DCFG->DAD: 设备地址(7位, 范围:0~128),0地址为公共地址
        dcfg.d32 = USB_OTG_READ_REG32( &pdev->regs.DREGS->DCFG);
        dcfg.b.devaddr = 0;
        USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DCFG, dcfg.d32);

        /* setup EP0 to receive SETUP packets */
        USB_OTG_EP0_OutStart(pdev);

        /* Clear interrupt */
        OTG_HS_GINTSTS->USBRST: USB 复位 (USB reset)
        模块将该位置 1 时,指示在 USB 上检测到复位信号。注意: 仅可在设备模式下访问。
        gintsts.d32 = 0;
        gintsts.b.usbreset = 1;
        USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32);

        /*Reset internal state machine */
        USBD_DCD_INT_fops->Reset(pdev);

STM32USB库将SETUP包放在一起处理,首先是枚举阶段

USBD_OTG_ISR_Handler -->
    gintr_status.b.outepintr -->
        DCD_HandleOutEP_ISR -->
            /* inform the upper layer that a setup packet is available */
            /* SETUP COMPLETE */
            USBD_DCD_INT_fops->SetupStage(pdev); -->
                USBD_ParseSetupRequest -->
                    USBD_StdDevReq -->
                        USBD_GetDescriptor -->
                            USBD_USR_DeviceDescriptor -->

主机获取设备描述符,下面是设备描述符的定义:

/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END =
{
  0x12,                       /*bLength */
  USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
  0x00,                       /*bcdUSB */
  0x02,
  0x00,                       /*bDeviceClass*/
  0x00,                       /*bDeviceSubClass*/
  0x00,                       /*bDeviceProtocol*/
  USB_OTG_MAX_EP0_SIZE,      /*bMaxPacketSize*/
  LOBYTE(USBD_VID),           /*idVendor*/
  HIBYTE(USBD_VID),           /*idVendor*/
  LOBYTE(USBD_PID),           /*idVendor*/
  HIBYTE(USBD_PID),           /*idVendor*/
  0x00,                       /*bcdDevice rel. 2.00*/
  0x02,
  USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
  USBD_IDX_PRODUCT_STR,       /*Index of product string*/
  USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
  USBD_CFG_MAX_NUM            /*bNumConfigurations*/
} ; /* USB_DeviceDescriptor */

#define USB_SIZ_DEVICE_DESC                     18
#define USBD_VID                     0x0483
#define USBD_PID                     0x5710

从设备描述符中,我们只能知道配置描述符的个数为1,并不知道他的具体细节。还知道VIDPID

主机发送设置地址:

USBD_SetAddress -->
    DCD_EP_SetAddress -->

以后设备将使用新的地址与主机通信。

主机发送请求全部设备地址:

主机发送获取配置描述符:

/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
  USB_HID_CONFIG_DESC_SIZ,
  /* wTotalLength: Bytes returned */
  0x00,
  0x01,         /*bNumInterfaces: 1 interface*/
  0x01,         /*bConfigurationValue: Configuration value*/
  0x00,         /*iConfiguration: Index of string descriptor describing
  the configuration*/
  0xE0,         /*bmAttributes: bus powered and Support Remote Wake-up */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

  /************** Descriptor of Joystick 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*/
  0x01,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: HID*/
  0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x02,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
  0,            /*iInterface: Index of string descriptor*/
  /******************** Descriptor of Joystick Mouse HID ********************/
  /* 18 */
  0x09,         /*bLength: HID Descriptor size*/
  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
  0x11,         /*bcdHID: HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of Mouse endpoint ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/

  HID_IN_EP,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_IN_PACKET, /*wMaxPacketSize: 4 Byte max */
  0x00,
  HID_FS_BINTERVAL,          /*bInterval: Polling Interval (10 ms)*/
  /* 34 */
} ;

#define USB_HID_CONFIG_DESC_SIZ       34

配置描述符本身占前9字节,配置描述符集合占34字节。

配置描述符:配置描述符中的bNumInterfaces字段定义了接口的个数,一般作为一个HID产品,要么他是键盘,要么他是鼠标,不太可能有跨界产品,所以接口个数一般为1。现在主机只知道我们有一个接口,但是还不知道这一类接口是鼠标还是键盘,或是其他什么。。。

接口描述符:后面紧跟着接口描述符9字节。接口描述符定义了某一类事物的集合,如鼠标,只要是鼠标,不管是什么品牌,什么特征,都需要向上提供相同的接口。现在主机知道了该接口的细节,nInterfaceProtocol字段表示我是鼠标。bInterfaceClass字段表示使用的是HID类,bNumEndpoints字段表示这个接口上只有一个端点,端点相当于TCP/IP协议栈的端口,代表着一个实际的设备。

HID描述符:在接口描述符中说到使用HID类,从机需要对这个类做相应的解释,并交给主机。

bNumDescriptors字段表示只有一个HID描述符

wItemLength字段表示报告描述符的大小,只要是HID设备,都是以报告的形式上传。

#define HID_MOUSE_REPORT_DESC_SIZE    74

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
  0x05,   0x01,
  0x09,   0x02,
  0xA1,   0x01,
  0x09,   0x01,

  0xA1,   0x00,
  0x05,   0x09,
  0x19,   0x01,
  0x29,   0x03,

  0x15,   0x00,
  0x25,   0x01,
  0x95,   0x03,
  0x75,   0x01,

  0x81,   0x02,
  0x95,   0x01,
  0x75,   0x05,
  0x81,   0x01,

  0x05,   0x01,
  0x09,   0x30,
  0x09,   0x31,
  0x09,   0x38,

  0x15,   0x81,
  0x25,   0x7F,
  0x75,   0x08,
  0x95,   0x03,

  0x81,   0x06,
  0xC0,   0x09,
  0x3c,   0x05,
  0xff,   0x09,

  0x01,   0x15,
  0x00,   0x25,
  0x01,   0x75,
  0x01,   0x95,

  0x02,   0xb1,
  0x22,   0x75,
  0x06,   0x95,
  0x01,   0xb1,

  0x01,   0xc0
};

报告描述符定义了报告的格式,是个重点,后面专门分析!

端点描述符:在接口描述符中提到只有一个端点,这里给出端点的解释。

bEndpointAddress字段告诉主机端点的地址,以后主机就可以直接发送数据包到这个端点,找到当前设备

wMaxPacketSize字段告诉主机上传的报告大小

bInterval字段告诉主机,设备上传报告的周期

主机获取字符串描述符:

设备序列号

Get_SerialNum -->
    deviceserial0 = *(uint32_t*)DEVICE_ID1;
    deviceserial1 = *(uint32_t*)DEVICE_ID2;
    deviceserial2 = *(uint32_t*)DEVICE_ID3;

#define         DEVICE_ID1          (0x1FFF7A10)
#define         DEVICE_ID2          (0x1FFF7A14)
#define         DEVICE_ID3          (0x1FFF7A18)

语言

#define USBD_LANGID_STRING            0x409

/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] __ALIGN_END =
{
  USB_SIZ_STRING_LANGID,         
  USB_DESC_TYPE_STRING,       
  LOBYTE(USBD_LANGID_STRING),
  HIBYTE(USBD_LANGID_STRING), 
};

USBD_USR_LangIDStrDescriptor -->
    *length =  sizeof(USBD_LangIDDesc);  
    return (uint8_t*)USBD_LangIDDesc;

参考USB LANGSID ,可知0x0409 English (United States), 使用美式英语

产品ID

#define USBD_PRODUCT_FS_STRING        "ST in FS Mode"

主机设置配置:

c
USBD_SetConfig -->
USBD_SetCfg -->
USBD_HID_Init
USBD_CtlSendStatus -->
USB_OTG_EP0_OutStart

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32 USB HID是指STM32系列单片机的一种USB设备协议,在该协议下,STM32单片机可以作为一个USB HID(Human Interface Device)设备与计算机进行数据通信,实现数据传输和设备控制等功能。 在STM32 USB HID通信中,STM32单片机通常使用USB接口作为数据传输的主要通信接口,通过该接口可以实现与计算机的数据交互。在该模式下,STM32单片机作为一个USB设备,可以模拟各种不同的传感器、按键、鼠标等设备,从而实现与计算机的数据交互的目的。 可以使用ST的STM32CubeMX软件来配置STM32USB HID功能,通过配置一些参数,可以支持多种不同的USB HID设备类型,如鼠标、键盘、游戏手柄等。通过自定义USB HID协议,还可以实现更加丰富的功能,例如在游戏开发中,可以使用STM32 USB HID协议来实现游戏手柄控制等。 总之,STM32 USB HIDSTM32系列单片机的一种重要的USB设备协议,可以广泛应用于各种数据传输和设备控制场景,具有易用性、可扩展性以及高效性等优点,在未来的嵌入式系统应用中具有广泛的发展前景。 ### 回答2: STM32 USBHID,是指在STM32单片机上实现USB HID(Human Interface Device)协议的技术。USB HID是一种USB设备通讯协议,它定义了如何在计算机和外设之间传输数据,并规定了外设的功能。比如键盘、鼠标、游戏手柄、触摸屏等都可以通过USB HID协议来实现数据传输。 在STM32单片机上实现USB HID协议,可以使STM32连接计算机时,被识别为一个HID设备,从而完成与计算机之间的数据传输。例如,可以通过STM32实现一个USB键盘,当STM32接入计算机时,相当于插入了一个键盘,可以通过代码控制键盘的按键输出。还可以实现一个USB鼠标,通过控制鼠标指针的坐标和点击事件,实现鼠标操作。 需要注意的是,实现USB HID协议需要使用STM32USB接口,需要进行复杂的USB协议栈和设备驱动的开发。同时,也需要掌握相关的USB HID协议知识。因此,对于初学者来说,需要认真学习STM32USB开发知识,并且根据具体的需求选择合适的开发工具和技术路线。 ### 回答3: STM32 USBHID是指基于STMicroelectronics公司生产的STM32微控制器的USB HID协议接口。USB HID(Human Interface Device)是一种用于支持人机交互的USB协议,它可以用来传输各种输入设备(如鼠标、键盘、游戏手柄等)的数据到计算机中。 STM32 USBHID具有以下特点: 1. 易于使用:STM32 USBHID提供了丰富的软件库和例程,使得开发者可以快速且方便地实现USB HID的功能。 2. 高性能:STM32微控制器具有高速的计算能力和丰富的外设接口,能够满足各种应用需求。 3. 灵活性强:STM32 USBHID支持自定义报告格式和热插拔功能,可以根据应用需求进行灵活配置。 4. 低功耗:STM32微控制器采用低功耗技术,可以实现低功耗运行,并支持强大的省电模式,可以有效延长电池寿命。 在应用方面,STM32 USBHID可以广泛应用于鼠标、键盘、游戏手柄、医疗设备等领域。比如,开发者可以使用STM32 USBHID制作一款自定义的游戏手柄,或者是一种带有安全锁的医疗设备,以实现更好的用户体验和数据安全性。总之,STM32 USBHID是一种功能强大、易于使用的USB协议接口,拥有广泛的应用前景和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值