基于STM32的USB键盘制作(保姆级)(二)

这篇具有很好参考价值的文章主要介绍了基于STM32的USB键盘制作(保姆级)(二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

系列文章目录 第一节  USB协议及建立USB-HID工程

第二节  配置描述符及HID报文格式

第三节  PCB按键映射(基于稚晖君开源)


 文章来源地址https://www.toymoban.com/news/detail-485801.html

文章目录

  • 系列文章目录
  • 前言
  • 一、配置函数定位的汇总
  • 二、具体配置
    • 1.设备配置报文的修改
    • 2.键盘报文描述修改
    • 3.键盘报文数据发送及实现
    • 4.值得注意的几点
    • 5.附录
  • 总结

 


前言

本文主要在上一节的基础上,对相关的设备以及报文描述符配置,实现USB键盘。


 

一、配置函数的定位汇总

这里只是汇总各个配置在哪个文件中,方便笔者后续复习时,方便查找。可先看下一部分,再回来看这。

生成后的工程文件夹如下图:(划斜线的为笔者自己创建的)

基于STM32的USB键盘制作(保姆级)(二)

在USB_DEVICE/App路径下的usbd_desc.c及其头文件包含了设备描述符。

即配置VID信息,USB版本以及速度等信息,保持默认即可(如下图),还有一些其他描述符,具体有什么用,需了解USB协议发送的具体过程。这里笔者没深究。

 基于STM32的USB键盘制作(保姆级)(二)

usb_device.c主要写的USB初始化的相关操作,其中定义了USB的句柄,后续在main函数以及其他函数要用时需要声明(extern USBD_HandleTypeDef hUsbDeviceFS;)

usbd_custom.hid_if.c文件则是配置后续要发送报文的格式(即要送的报文代表什么含义,要发送多少个字节)。(需要修改的文件)。

在Middlewares文件夹下的usbd_customhid.c文件则包含了配置描述符(PC要对该USB口配置成什么类型,输出电流大小等信息,是否支持3.0,配置为HS、FS、或其他速度)。其头文件还定义各种报文以及缓冲区的大小。(需要修改的文件)。

基于STM32的USB键盘制作(保姆级)(二)

基于STM32的USB键盘制作(保姆级)(二)

二、具体配置

1.设备配置报文的修改

打开usbd_customhid.c文件,找到如下代码,每一行配置的什么,后面都有注释详解的。

因为笔者这款芯片只支持FS模式,且在cubemx中也选择的FS模式,故修改FS这个数组,若为HS或其他速度模式,则在C文件下翻,找到对应的修改即可。

__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
  USB_CUSTOM_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*/
  0xC0,         /*bmAttributes: bus powered */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

  /************** Descriptor of CUSTOM HID interface ****************/
  /* 09 */
  0x09,         /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
  0x00,         /*bInterfaceNumber: Number of Interface*/
  0x00,         /*bAlternateSetting: Alternate setting*/
  0x02,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: CUSTOM_HID*/
  0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
  0,            /*iInterface: Index of string descriptor*/
  /******************** Descriptor of CUSTOM_HID *************************/
  /* 18 */
  0x09,         /*bLength: CUSTOM_HID Descriptor size*/
  CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/
  0x11,         /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  USBD_CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of Custom HID endpoints ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/

  CUSTOM_HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,          /*bInterval: Polling Interval */
  /* 34 */

  0x07,          /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
  CUSTOM_HID_EPOUT_ADDR,  /*bEndpointAddress: Endpoint Address (OUT)*/
  0x03, /* bmAttributes: Interrupt endpoint */
  CUSTOM_HID_EPOUT_SIZE,  /* wMaxPacketSize: 2 Bytes max  */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,  /* bInterval: Polling Interval */
  /* 41 */
};

修改此三行

  0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/

  0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/

  0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/

0x32表示为该口提供的最大输出电流。(0x32换算十进制即50,再×2 即100)即这里提供最大100ma输出电流。USB2.0最大提供输出500ma电流,即最大设置为0xFA;

这里使用的开发板且只有一个按键,0x32绰绰有余。若单独画PCB制作键盘,设置0xFA

0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/这里设置有无BOOT

笔者还不太了解这块,故给的0x00

0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/这里设置0x01表示键盘。

其他不变

 

2.键盘报文描述符设置

在usbd_custom.hid_if.c这个文件中。

题外话:具体为什么这样配置,参考这篇文章:HID报文讲解_skdev的博客-CSDN博客

想做其他操作,可以配合手册和生成软件,实现其他HID类设备

基于STM32的USB键盘制作(保姆级)(二)

具体配置:找到   __ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =  这个数组

将其中内容修改为:

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
        0x05, 0x01,         //   Usage Page (Generic Desktop),
        0x09, 0x06,         //   Usage (Keyboard),
        0xA1, 0x01,         //   Collection (Application),
        0x85, 0x01,                    //     REPORT_ID (1)
        // bitmap of modifiers
        0x75, 0x01,         //   Report Size (1),
        0x95, 0x08,         //   Report Count (8),
        0x05, 0x07,       //   Usage Page (Key Codes),
        0x19, 0xE0,       //   Usage Minimum (224),
        0x29, 0xE7,       //   Usage Maximum (231),
        0x15, 0x00,       //   Logical Minimum (0),
        0x25, 0x01,       //   Logical Maximum (1),
        0x81, 0x02,       //   Input (Data, Variable, Absolute), ;Modifier byte
        // bitmap of keys
        0x95, 0x78,       //   Report Count (120),
        0x75, 0x01,       //   Report Size (1),
        0x15, 0x00,       //   Logical Minimum (0),
        0x25, 0x01,       //   Logical Maximum(1),
        0x05, 0x07,       //   Usage Page (Key Codes),
        0x19, 0x00,       //   Usage Minimum (0),
        0x29, 0x77,       //   Usage Maximum (),
        0x81, 0x02,       //   Input (Data, Variable, Absolute),
  0xC0    /*     END_COLLECTION	             */      
};

 细数一共有41个字节,故USBD_CUSTOM_HID_REPORT_DESC_SIZE这个宏定义要修改为41

即这个描述数组有多少个字节,USBD_CUSTOM_HID_REPORT_DESC_SIZE这个宏定义就必须是多少,有一点误差都会导致识别失败。

在usbd_conf.h这个头文件里面修改USBD_CUSTOM_HID_REPORT_DESC_SIZE的大小

基于STM32的USB键盘制作(保姆级)(二)

修改为41,数字后面的U表示无符号数。

此时,我们保存编译下载到单片机。

基于STM32的USB键盘制作(保姆级)(二)

会发现,识别到键盘设备,到此,成功一大半了。接下来进行按键发送报文。

上述报文描述符格式对应下图这种表。(已打包到资源文件)

基于STM32的USB键盘制作(保姆级)(二)

3.按键发送报文数据

首先单独新建一个C文件和一个头文件,写报文发送函数。

新建一个枚举体,存放要放入的HID报文数据。

(枚举体小知识点:未给初始值时,默认值由0开始,之后自加1赋值

即:下列枚举体中的RESERVED=0,则ERROR_ROLL_OVER=1,POST_FAIL=2...以此类推。)

  typedef enum 
    {
        /*------------------------- HID report data -------------------------*/
        LEFT_CTRL = -8,LEFT_SHIFT = -7,LEFT_ALT = -6,LEFT_GUI = -5,
        RIGHT_CTRL = -4,RIGHT_SHIFT = -3,RIGHT_ALT = -2,RIGHT_GUI = -1,

        RESERVED = 0,ERROR_ROLL_OVER,POST_FAIL,ERROR_UNDEFINED,
        A,B,C,D,E,F,G,H,I,J,K,L,M,
        N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
        NUM_1/*1!*/,NUM_2/*2@*/,NUM_3/*3#*/,NUM_4/*4$*/,NUM_5/*5%*/,
        NUM_6/*6^*/,NUM_7/*7&*/,NUM_8/*8**/,NUM_9/*9(*/,NUM_0/*0)*/,
        ENTER,ESC,BACKSPACE,TAB,SPACE,
        MINUS/*-_*/,EQUAL/*=+*/,LEFT_U_BRACE/*[{*/,RIGHT_U_BRACE/*]}*/,
        BACKSLASH/*\|*/,NONE_US/**/,SEMI_COLON/*;:*/,QUOTE/*'"*/,
        GRAVE_ACCENT/*`~*/,COMMA/*,<*/,PERIOD/*.>*/,SLASH/*/?*/,
        CAP_LOCK,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,
        PRINT,SCROLL_LOCK,PAUSE,INSERT,HOME,PAGE_UP,DELETE,END,PAGE_DOWN,
        RIGHT_ARROW,LEFT_ARROW,DOWN_ARROW,UP_ARROW,PAD_NUM_LOCK,
        PAD_SLASH,PAD_ASTERISK,PAD_MINUS,PAD_PLUS,PAD_ENTER,
        PAD_NUM_1,PAD_NUM_2,PAD_NUM_3,PAD_NUM_4,PAD_NUM_5,
        PAD_NUM_6,PAD_NUM_7,PAD_NUM_8,PAD_NUM_9,PAD_NUM_0,
        PAD_PERIOD , NONUS_BACKSLASH,APPLICATION,POWER,PAD_EQUAL,
        F13,F14,F15,F16,F17,F18,F19,F20,F21,F22,F23,F24, EXECUTE,
        HELP,MENU,SELECT,STOP,AGAIN,UNDO,CUT,COPY,PASTE,FIND,MUTE,VOLUME_UP,VOLUME_DOWN,
        FN = 1000
        /*------------------------- HID report data -------------------------*/
    }KeyCode_t;

一共128个位,即16个字节(对应上文的报文描述数组)。一个位表示一个按键。接下来定义uint8_t hidbuffer[17];一个17位的数组。有17位的原因:第一个字节表示是ID号,后16个字节表示按键的状态,即128位,一位对应一个按键。(比如hidbuffer[1]=0x01,其他均为0,就表示LEFT_RIGHT这个按键被按下了。)(发送的报文: 0表示没按下,1表示没按下)

现在就可以写按键检测并发送函数了:

uint8_t hidbuffer[17];
extern USBD_HandleTypeDef hUsbDeviceFS;

void keyboard()
{
    memset(hidbuffer,0,17);
    hidbuffer[0] = 1;
    if((HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5))==0)
    {
        DelayUs(100);
       if((HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5))==0)
       {
         hidbuffer[3] = 0x01;
       }
    }
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,hidbuffer,17);
}

memset函数在"string.h"这个头文件中,这个函数的作用是将hidbuffer这个数组全部请0。

hidbuffer【0】=1;即ID号等于1,即是键盘的ID号(在上面报文描述数组中0x85,0x01这一句设置的)。这里因为我用的开发板只用了一个按键,故我把这个按键表示为E,"E"键在枚举体中是第17个,即在hidbuffer数组中就是hidbuffer【3】的第0位。

DelayUs(100);是为了按键消抖,让hidbuffer【3】=0x01,即表示按键按下时,让对应"E"这位等于1.然后发送报文即可(利USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,hidbuffer,17);这个函数,该函数在 "usbd_customhid.h"中)

注:需要hUsbDeviceFS这个结构体不是在main中定义的,而是在USB_DEVICE.H中,故需要写 extern USBD_HandleTypeDef hUsbDeviceFS;

main函数调用即可,延时1ms表示1ms扫描一次按键。

基于STM32的USB键盘制作(保姆级)(二)

 然后编译烧录进单片机,开始测试

基于STM32的USB键盘制作(保姆级)(二)

测试正常。至此实现完成。

4.值得注意的几个点

发送报文数据需要及时发送。否则PC机一直读的上一次报文,导致按键一直在被打印。

将HAL_DELAY(1)改为1000,相当于1秒扫描一次,并发送报文。此时烧录进单片机,按下按键一次会发现"e"键在一直被打印,因为没有即使更新报文(即以及松开了,没发送过去)。

消抖若过久,会导致有时候按下,并没有反应。因为有可能按下这个时间,程序还在上一次消抖那里延时。

笔者曾想,按下一个按键实现给主机保送多个不同的数据,比如按下一个按键就输入了密码这种操作,但在多次发送过程中,要么乱序,要么一直发送,目前未解决。(想了下,如果一个按键就输入了全部密码,那还要密码干嘛,就没继续研究了)

附录:工程代码下载链接:https://download.csdn.net/download/qq_21566881/87078754

HID手册及配置工具下载链接:https://download.csdn.net/download/qq_21566881/87073789?spm=1001.2014.3001.5503

(审核完成后上传)

 

2022.11.21补充:

基于STM32的USB键盘制作(保姆级)(二)

推荐下载这个软件 查看电脑接受到的报文数据,根据接受的数据来调试

软件叫BUS HOUND 几MB大小,上手很快 

 

 


总结

本文实现了STM32的USB-HID键盘的应用,下一篇文章将介绍基于稚晖君开源DIY的瀚文键盘的按键映射源码分析,看完下一篇后,便可动手画PCB板,DIY自己的一个USB键盘。

 

 

 

到了这里,关于基于STM32的USB键盘制作(保姆级)(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 教你STM32做USB鼠标、键盘

    使用CubeMX软件傻瓜式的配置,一键生成USB的HID驱动。 ①、选择相对应的芯片  ②、配置时钟和Debug和debug      ③、配置USB    ④、生成代码          最好把这个也勾上,勾上以后每个外设配置不再都给你塞到main.c里,而是建一个.c.h,这样感觉舒服多了         USB协议

    2024年01月23日
    浏览(41)
  • STM32 CubeMX USB_(HID 鼠标和键盘)

    STM32 CubeMX 自动生成的USB_HID是鼠标类型的:键盘类型要做一点小修改; 参考: STM32CubeMX学习笔记 USB鼠标HID描述符以及数据格式

    2024年02月14日
    浏览(35)
  • STM32。USB HID,如何发送标准键盘的按键报告?

    我们要求STM32芯片的usb和windows电脑的USB接口进行连接,然后STM32芯片发送usb数据给windows电脑,实现电脑上按下一个f按键的效果。 下面开始操作: 使用STM32CubeMX生成代码,先选择对应的usb口 然后选择第三方软件,选择HID 然后点击生成代码,这时候就会生成usbd_hid.c相关的代码

    2024年02月12日
    浏览(46)
  • stm32 USB HID+CDC 鼠标键盘串口 组合设备配置解析

    查阅网上的博客与代码,很多都是关于USB的鼠标配置、USB的键盘配置、USB的虚拟串口配置,稍微深入一点的会将鼠标键盘合在一起,但移植起来就会报很多错误,要么是检测不到,要么是警告,这很正常,因为不理解这些数字代表着什么。但只要理解每个数字代表什么意思,

    2024年02月13日
    浏览(41)
  • 第10课【STM32 USB通讯协议实战】HID键盘+CDC虚拟串口组合设备

    文章中的部分概念可参考第9课【USB协议】USB总线 接口 端点 管道 数据包 枚举 STM32_USB-FS-Device_Lib V4.1.0 USB协议中为了提供对多样设备的支持,定义了许多外部设备子类,常见的包括: 人机交互类设备HID(Human Interface Device) 通信类设备CDC(Communicate Device Class) 大容量存储设备

    2024年02月04日
    浏览(59)
  • STM32CubeMX教程31 USB_DEVICE - HID外设_模拟键盘或鼠标

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 USB_OTG_FS为工作在Human Interface Device Class (HID)(人机接口设备类)模式下的USB_DEVICE(USB从机),利用上下左右四

    2024年02月19日
    浏览(40)
  • stm32 USB复合设备 cubeMX库一键生成 多路CDC串口 HID鼠标键盘 Composite Device

    最近有个需求,需要同时用usb键盘鼠标和虚拟串口等,因为平时没怎么研究过usb协议,所以自己写复合设备一直没有成功,然后正巧在github上看到了一个stm32的一个usb复合设备库,可以快速配置usb组合设备,并且支持超级多路串口 Gihub地址 https://github.com/alambe94/I-CUBE-USBD-Compo

    2024年02月09日
    浏览(63)
  • 【正点原子STM32连载】 第六十章 USB鼠标键盘(Host)实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html 4)对正点原子STM32感兴趣的同学可以加群讨论:879133275 本章我们介绍如何使用STM32H750的USB HOST来驱动USB鼠

    2024年02月09日
    浏览(46)
  • 基于STM32讲USB

    USB接口是我们日常生活中最常见到的一种接口了,在电脑,手机,键盘,鼠标上都会见到。现常用的是 USB2.0 和 USB3.0 规格的。 VCC(一般+5V)、GND、D+、D-。而D+、D-是两个数据线,学过模电的我们都知道差分电路的好处是可以抑制共模信号也就是抑制干扰,以保证信号传输的质量

    2024年02月16日
    浏览(43)
  • 基于STM32CubeMx配置FreeRtos以及USB虚拟串口步骤详解

       Debug:推荐选择 Serial Wire (方便使用STLink打断点在线调试) 中间两项默认Disable就好 TimeBase Source:若需要配置FreeRtos则不能选择SysTick,随机选择一个TIM定时器即可,这里我选择TIM1定时器。 (解释:裸机的时钟源默认是SysTick,但是开启FreeRtos后,FreeRtos会占用SysTick,用于任

    2024年02月05日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包