📄 usbcore.lst
字号:
C51 COMPILER V7.06 USBCORE 11/16/2008 16:00:31 PAGE 1
C51 COMPILER V7.06, COMPILATION OF MODULE USBCORE
OBJECT MODULE PLACED IN UsbCore.OBJ
COMPILER INVOKED BY: d:\Keil\C51\BIN\C51.EXE UsbCore.c BROWSE DEBUG OBJECTEXTEND TABS(1)
stmt level source
1 /******************************************************************
2 本程序只供学习使用,未经作者许可,不得用于其它任何用途
3
4 欢迎访问我的USB专区:http://group.ednchina.com/93/
5 欢迎访问我的blog: http://www.ednchina.com/blog/computer00
6 http://computer00.21ic.org
7
8 感谢PCB赞助商——电子园: http://bbs.cepark.com/
9
10 UsbCore.c file
11
12 作者:电脑圈圈
13 建立日期: 2008.06.29
14 修改日期: 2008.07.14
15 版本:V1.1
16 版权所有,盗版必究。
17 Copyright(C) 电脑圈圈 2008-2018
18 All rights reserved
19 *******************************************************************/
20
21 #include "config.h"
22 #include "pdiusbd12.h"
23 #include "uart.h"
24 #include "usbcore.h"
25 #include "led.h"
26
27 idata uint8 Buffer[16]; //读端点0用的缓冲区
28
29 //USB设备请求的各字段
30 uint8 bmRequestType;
31 uint8 bRequest;
32 uint16 wValue;
33 uint16 wIndex;
34 uint16 wLength;
35 //当前发送数据的位置
36 uint8 * pSendData;
37 //需要发送数据的长度
38 uint16 SendLength;
39 //是否需要发送0数据包的标志。在USB控制传输的数据过程中,
40 //当返回的数据包字节数少于最大包长时,会认为数据过程结束。
41 //当请求的字节数比实际需要返回的字节数长,而实际返回的字节
42 //数又刚好是端点0大小的整数倍时,就需要返回一个0长度的数据包
43 //来结束数据过程。因此这里增加一个标志,供程序决定是否需要返回
44 //一个0长度的数据包。
45 uint8 NeedZeroPacket;
46
47 //当前的配置值。只有在设置非0配置后
48 uint8 ConfigValue;
49
50 //端点1缓冲是否忙的标志。当缓冲区中有数据时,该标志为真。
51 //当缓冲区中空闲时,该标志为假。
52 uint8 Ep1InIsBusy;
53
54 //USB设备描述符的定义
55 code uint8 DeviceDescriptor[0x12]= //设备描述符为18字节
C51 COMPILER V7.06 USBCORE 11/16/2008 16:00:31 PAGE 2
56 {
57 //bLength字段。设备描述符的长度为18(0x12)字节
58 0x12,
59
60 //bDescriptorType字段。设备描述符的编号为0x01
61 0x01,
62
63 //bcdUSB字段。这里设置版本为USB1.1,即0x0110。
64 //由于是小端结构,所以低字节在先,即0x10,0x01。
65 0x10,
66 0x01,
67
68 //bDeviceClass字段。我们不在设备描述符中定义设备类,
69 //而在接口描述符中定义设备类,所以该字段的值为0。
70 0x00,
71
72 //bDeviceSubClass字段。bDeviceClass字段为0时,该字段也为0。
73 0x00,
74
75 //bDeviceProtocol字段。bDeviceClass字段为0时,该字段也为0。
76 0x00,
77
78 //bMaxPacketSize0字段。PDIUSBD12的端点0大小的16字节。
79 0x10,
80
81 //idVender字段。厂商ID号,我们这里取0x8888,仅供实验用。
82 //实际产品不能随便使用厂商ID号,必须跟USB协会申请厂商ID号。
83 //注意小端模式,低字节在先。
84 0x88,
85 0x88,
86
87 //idProduct字段。产品ID号,由于是第二个实验,我们这里取0x0002。
88 //注意小端模式,低字节应该在前。
89 0x02,
90 0x00,
91
92 //bcdDevice字段。我们这个USB键盘刚开始做,就叫它1.0版吧,即0x0100。
93 //小端模式,低字节在先。
94 0x00,
95 0x01,
96
97 //iManufacturer字段。厂商字符串的索引值,为了方便记忆和管理,
98 //字符串索引就从1开始吧。
99 0x01,
100
101 //iProduct字段。产品字符串的索引值。刚刚用了1,这里就取2吧。
102 //注意字符串索引值不要使用相同的值。
103 0x02,
104
105 //iSerialNumber字段。设备的序列号字符串索引值。
106 //这里取3就可以了。
107 0x03,
108
109 //bNumConfigurations字段。该设备所具有的配置数。
110 //我们只需要一种配置就行了,因此该值设置为1。
111 0x01
112 };
113 //////////////////////////设备描述符完毕//////////////////////////////
114
115 //USB报告描述符的定义
116 code uint8 ReportDescriptor[]=
117 {
C51 COMPILER V7.06 USBCORE 11/16/2008 16:00:31 PAGE 3
118 //每行开始的第一字节为该条目的前缀,前缀的格式为:
119 //D7~D4:bTag。D3~D2:bType;D1~D0:bSize。以下分别对每个条目注释。
120
121 //这是一个全局(bType为1)条目,将用途页选择为普通桌面Generic Desktop Page(0x01)
122 //后面跟一字节数据(bSize为1),后面的字节数就不注释了,
123 //自己根据bSize来判断。
124 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
125
126 //这是一个局部(bType为2)条目,说明接下来的集合用途用于键盘
127 0x09, 0x06, // USAGE (Keyboard)
128
129 //这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示
130 //该集合是一个应用集合。它的性质在前面由用途页和用途定义为
131 //普通桌面用的键盘。
132 0xa1, 0x01, // COLLECTION (Application)
133
134 //这是一个全局条目,选择用途页为键盘(Keyboard/Keypad(0x07))
135 0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)
136
137 //这是一个局部条目,说明用途的最小值为0xe0。实际上是键盘左Ctrl键。
138 //具体的用途值可在HID用途表中查看。
139 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
140
141 //这是一个局部条目,说明用途的最大值为0xe7。实际上是键盘右GUI键。
142 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
143
144 //这是一个全局条目,说明返回的数据的逻辑值(就是我们返回的数据域的值)
145 //最小为0。因为我们这里用Bit来表示一个数据域,因此最小为0,最大为1。
146 0x15, 0x00, // LOGICAL_MINIMUM (0)
147
148 //这是一个全局条目,说明逻辑值最大为1。
149 0x25, 0x01, // LOGICAL_MAXIMUM (1)
150
151 //这是一个全局条目,说明数据域的数量为八个。
152 0x95, 0x08, // REPORT_COUNT (8)
153
154 //这是一个全局条目,说明每个数据域的长度为1个bit。
155 0x75, 0x01, // REPORT_SIZE (1)
156
157 //这是一个主条目,说明有8个长度为1bit的数据域(数量和长度
158 //由前面的两个全局条目所定义)用来做为输入,
159 //属性为:Data,Var,Abs。Data表示这些数据可以变动,Var表示
160 //这些数据域是独立的,每个域表示一个意思。Abs表示绝对值。
161 //这样定义的结果就是,当某个域的值为1时,就表示对应的键按下。
162 //bit0就对应着用途最小值0xe0,bit7对应着用途最大值0xe7。
163 0x81, 0x02, // INPUT (Data,Var,Abs)
164
165 //这是一个全局条目,说明数据域数量为1个
166 0x95, 0x01, // REPORT_COUNT (1)
167
168 //这是一个全局条目,说明每个数据域的长度为8bit。
169 0x75, 0x08, // REPORT_SIZE (8)
170
171 //这是一个主条目,输入用,由前面两个全局条目可知,长度为8bit,
172 //数量为1个。它的属性为常量(即返回的数据一直是0)。
173 //该字节是保留字节(保留给OEM使用)。
174 0x81, 0x03, // INPUT (Cnst,Var,Abs)
175
176 //这是一个全局条目。定义位域数量为6个。
177 0x95, 0x06, // REPORT_COUNT (6)
178
179 //这是一个全局条目。定义每个位域长度为8bit。
C51 COMPILER V7.06 USBCORE 11/16/2008 16:00:31 PAGE 4
180 //其实这里这个条目不要也是可以的,因为在前面已经有一个定义
181 //长度为8bit的全局条目了。
182 0x75, 0x08, // REPORT_SIZE (8)
183
184 //这是一个全局条目,定义逻辑最小值为0。
185 //同上,这里这个全局条目也是可以不要的,因为前面已经有一个
186 //定义逻辑最小值为0的全局条目了。
187 0x15, 0x00, // LOGICAL_MINIMUM (0)
188
189 //这是一个全局条目,定义逻辑最大值为255。
190 0x25, 0xFF, // LOGICAL_MAXIMUM (255)
191
192 //这是一个全局条目,选择用途页为键盘。
193 //前面已经选择过用途页为键盘了,所以该条目不要也可以。
194 0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)
195
196 //这是一个局部条目,定义用途最小值为0(0表示没有键按下)
197 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
198
199 //这是一个局部条目,定义用途最大值为0x65
200 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
201
202 //这是一个主条目。它说明这六个8bit的数据域是输入用的,
203 //属性为:Data,Ary,Abs。Data说明数据是可以变的,Ary说明
204 //这些数据域是一个数组,即每个8bit都可以表示某个键值,
205 //如果按下的键太多(例如超过这里定义的长度或者键盘本身无法
206 //扫描出按键情况时),则这些数据返回全1(二进制),表示按键无效。
207 //Abs表示这些值是绝对值。
208 0x81, 0x00, // INPUT (Data,Ary,Abs)
209
210 //以下为输出报告的描述
211 //逻辑最小值前面已经有定义为0了,这里可以省略。
212 //这是一个全局条目,说明逻辑值最大为1。
213 0x25, 0x01, // LOGICAL_MAXIMUM (1)
214
215 //这是一个全局条目,说明数据域数量为5个。
216 0x95, 0x05, // REPORT_COUNT (5)
217
218 //这是一个全局条目,说明数据域的长度为1bit。
219 0x75, 0x01, // REPORT_SIZE (1)
220
221 //这是一个全局条目,说明使用的用途页为指示灯(LED)
222 0x05, 0x08, // USAGE_PAGE (LEDs)
223
224 //这是一个局部条目,说明用途最小值为数字键盘灯。
225 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
226
227 //这是一个局部条目,说明用途最大值为Kana灯。
228 0x29, 0x05, // USAGE_MAXIMUM (Kana)
229
230 //这是一个主条目。定义输出数据,即前面定义的5个LED。
231 0x91, 0x02, // OUTPUT (Data,Var,Abs)
232
233 //这是一个全局条目。定义位域数量为1个。
234 0x95, 0x01, // REPORT_COUNT (1)
235
236 //这是一个全局条目。定义位域长度为3bit。
237 0x75, 0x03, // REPORT_SIZE (3)
238
239 //这是一个主条目,定义输出常量,前面用了5bit,所以这里需要
240 //3个bit来凑成一字节。
241 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
C51 COMPILER V7.06 USBCORE 11/16/2008 16:00:31 PAGE 5
242
243 //下面这个主条目用来关闭前面的集合。bSize为0,所以后面没数据。
244 0xc0 // END_COLLECTION
245 };
246 //通过上面的报告描述符的定义,我们知道返回的输入报告具有8字节。
247 //第一字节的8个bit用来表示特殊键是否按下(例如Shift、Alt等键)。
248 //第二字节为保留值,值为常量0。第三到第八字节是一个普通键键值的
249 //数组,当没有键按下时,全部6个字节值都为0。当只有一个普通键按下时,
250 //这六个字节中的第一字节值即为该按键的键值(具体的键值请看HID的
251 //用途表文档),当有多个普通键同时按下时,则同时返回这些键的键值。
252 //如果按下的键太多,则这六个字节都为0xFF(不能返回0x00,这样会让
253 //操作系统认为所有键都已经释放)。至于键值在数组中的先后顺序是
254 //无所谓的,操作系统会负责检查是否有新键按下。我们应该在中断端点1
255 //中按照上面的格式返回实际的键盘数据。另外,报告中还定义了一个字节
256 //的输出报告,是用来控制LED情况的。只使用了低7位,高1位是保留值0。
257 //当某位的值为1时,则表示对应的LED要点亮。操作系统会负责同步各个
258 //键盘之间的LED,例如你有两块键盘,一块的数字键盘灯亮时,另一块
259 //也会跟着亮。键盘本身不需要判断各种LED应该何时亮,它只是等待主机
260 //发送报告给它,然后根据报告值来点亮相应的LED。我们在端点1输出中断
261 //中读出这1字节的输出报告,然后对它取反(因为学习板上的LED是低电平时
262 //亮),直接发送到LED上。这样main函数中按键点亮LED的代码就不需要了。
263 ///////////////////////////报告描述符完毕////////////////////////////
264
265 //USB配置描述符集合的定义
266 //配置描述符总长度为9+9+9+7+7字节
267 code uint8 ConfigurationDescriptor[9+9+9+7+7]=
268 {
269 /***************配置描述符***********************/
270 //bLength字段。配置描述符的长度为9字节。
271 0x09,
272
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -