新闻中心

EEPW首页>嵌入式系统>设计应用> STM32的USB键盘及鼠标的例程介绍

STM32的USB键盘及鼠标的例程介绍

作者: 时间:2012-10-14 来源:网络 收藏

本文引用地址://m.amcfsurvey.com/article/170774.htm

//***************端点1输出描述***************

0x07,

_ENDPOINT_DESCRIPTOR_TYPE,

0x01,

0x03,

0x0A,

0x00,

0x20,

};

// MOUSE ConfigDescriptor

const u8 HID_ReportDescriptor[HID_SIZE_REPORT_DESC]=

{

/************************部分报告描述符**********************/

/*******************************************************************/

//这是一个全局(bType为1)条目,将用途页选择为普通桌面Generic Desktop Page(0x01)

//后面跟一字节数据(bSize为1),后面的字节数就不注释了,

//自己根据bSize来判断。

0x05, 0x01, // USAGE_PAGE (Generic Desktop)

//这是一个局部(bType为2)条目,说明接下来的集合用途用于

0x09, 0x06, // USAGE (Keyboard)

//这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示

//该集合是一个应用集合。它的性质在前面由用途页和用途定义为

//普通桌面用的

0xa1, 0x01, // COLLECTION (Application)

//报告ID,这里定义键盘报告的ID为1(报告ID 0是保留的)

0x85, 0x01, //Report ID (1)

//这是一个全局条目,选择用途页为键盘(Keyboard/Keypad(0x07))

0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)

//这是一个局部条目,说明用途的最小值为0xe0。实际上是键盘左Ctrl键。

//具体的用途值可在HID用途表中查看。

0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)

//这是一个局部条目,说明用途的最大值为0xe7。实际上是键盘右GUI键。

0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)

//这是一个全局条目,说明返回的数据的逻辑值(就是我们返回的数据域的值)

//最小为0。因为我们这里用Bit来表示一个数据域,因此最小为0,最大为1。

0x15, 0x00, // LOGICAL_MINIMUM (0)

//这是一个全局条目,说明逻辑值最大为1。

0x25, 0x01, // LOGICAL_MAXIMUM (1)

//这是一个全局条目,说明数据域的数量为八个。

0x95, 0x08, // REPORT_COUNT (8)

//这是一个全局条目,说明每个数据域的长度为1个bit。

0x75, 0x01, // REPORT_SIZE (1)

//这是一个主条目,说明有8个长度为1bit的数据域(数量和长度

//由前面的两个全局条目所定义)用来做为输入,

//属性为:Data,Var,Abs。Data表示这些数据可以变动,Var表示

//这些数据域是独立的,每个域表示一个意思。Abs表示绝对值。

//这样定义的结果就是,当某个域的值为1时,就表示对应的键按下。

//bit0就对应着用途最小值0xe0,bit7对应着用途最大值0xe7。

0x81, 0x02, // INPUT (Data,Var,Abs)

//这是一个全局条目,说明数据域数量为1个

0x95, 0x01, // REPORT_COUNT (1)

//这是一个全局条目,说明每个数据域的长度为8bit。

0x75, 0x08, // REPORT_SIZE (8)

//这是一个主条目,输入用,由前面两个全局条目可知,长度为8bit,

//数量为1个。它的属性为常量(即返回的数据一直是0)。

//该字节是保留字节(保留给OEM使用)。

0x81, 0x03, // INPUT (Cnst,Var,Abs)

//这是一个全局条目。定义位域数量为6个。

0x95, 0x06, // REPORT_COUNT (6)

//这是一个全局条目。定义每个位域长度为8bit。

//其实这里这个条目不要也是可以的,因为在前面已经有一个定义

//长度为8bit的全局条目了。

0x75, 0x08, // REPORT_SIZE (8)

//这是一个全局条目,定义逻辑最小值为0。

//同上,这里这个全局条目也是可以不要的,因为前面已经有一个

//定义逻辑最小值为0的全局条目了。

0x15, 0x00, // LOGICAL_MINIMUM (0)

//这是一个全局条目,定义逻辑最大值为255。

0x25, 0xFF, // LOGICAL_MAXIMUM (255)

//这是一个全局条目,选择用途页为键盘。

//前面已经选择过用途页为键盘了,所以该条目不要也可以。

0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)

//这是一个局部条目,定义用途最小值为0(0表示没有键按下)

0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))

//这是一个局部条目,定义用途最大值为0x65

0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)

//这是一个主条目。它说明这六个8bit的数据域是输入用的,

//属性为:Data,Ary,Abs。Data说明数据是可以变的,Ary说明

//这些数据域是一个数组,即每个8bit都可以表示某个键值,

//如果按下的键太多(例如超过这里定义的长度或者键盘本身无法

//扫描出按键情况时),则这些数据返回全1(二进制),表示按键无效。

//Abs表示这些值是绝对值。

0x81, 0x00, // INPUT (Data,Ary,Abs)

//以下为输出报告的描述

//逻辑最小值前面已经有定义为0了,这里可以省略。

//这是一个全局条目,说明逻辑值最大为1。

0x25, 0x01, // LOGICAL_MAXIMUM (1)

//这是一个全局条目,说明数据域数量为5个。

0x95, 0x05, // REPORT_COUNT (5)

//这是一个全局条目,说明数据域的长度为1bit。

0x75, 0x01, // REPORT_SIZE (1)

//这是一个全局条目,说明使用的用途页为指示灯(LED)

0x05, 0x08, // USAGE_PAGE (LEDs)

//这是一个局部条目,说明用途最小值为数字键盘灯。

0x19, 0x01, // USAGE_MINIMUM (Num Lock)

//这是一个局部条目,说明用途最大值为Kana灯。

0x29, 0x05, // USAGE_MAXIMUM (Kana)

//这是一个主条目。定义输出数据,即前面定义的5个LED。

0x91, 0x02, // OUTPUT (Data,Var,Abs)

//这是一个全局条目。定义位域数量为1个。

0x95, 0x01, // REPORT_COUNT (1)

//这是一个全局条目。定义位域长度为3bit。

0x75, 0x03, // REPORT_SIZE (3)

//这是一个主条目,定义输出常量,前面用了5bit,所以这里需要

//3个bit来凑成一字节。

0x91, 0x03, // OUTPUT (Cnst,Var,Abs)

//下面这个主条目用来关闭前面的集合。bSize为0,所以后面没数据。

0xc0, // END_COLLECTION

//以下注释不包括第一字节报告ID。

//通过上面的报告描述符的定义,我们知道返回的输入报告具有8字节。

//第一字节的8个bit用来表示特殊键是否按下(例如Shift、Alt等键)。

//第二字节为保留值,值为常量0。第三到第八字节是一个普通键键值的

//数组,当没有键按下时,全部6个字节值都为0。当只有一个普通键按下时,

//这六个字节中的第一字节值即为该按键的键值(具体的键值请看HID的

//用途表文档),当有多个普通键同时按下时,则同时返回这些键的键值。

//如果按下的键太多,则这六个字节都为0xFF(不能返回0x00,这样会让

//操作系统认为所有键都已经释放)。至于键值在数组中的先后顺序是

//无所谓的,操作系统会负责检查是否有新键按下。我们应该在中断端点1

//中按照上面的格式返回实际的键盘数据。另外,报告中还定义了一个字节

//的输出报告,是用来控制LED情况的。只使用了低7位,高1位是保留值0。

//当某位的值为1时,则表示对应的LED要点亮。操作系统会负责同步各个

//键盘之间的LED,例如你有两块键盘,一块的数字键盘灯亮时,另一块

//也会跟着亮。键盘本身不需要判断各种LED应该何时亮,它只是等待主机

//发送报告给它,然后根据报告值来点亮相应的LED。我们在端点1输出中断

//中读出这1字节的输出报告,然后对它取反(因为学习板上的LED是低电平时

//亮),直接发送到LED上。这样main函数中按键点亮LED的代码就不需要了。

DIY机械键盘相关社区:机械键盘DIY


绝对值编码器相关文章:绝对值编码器原理


评论


相关推荐

技术专区

关闭