<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
一、移植过程分析
1、移植前的准备工作
现在我们实现一个系统,很少是从0开始,都是在已有的系统上借鉴和修改,这是软件可重用性的表现。
(1)我的USB键盘的目标
摇杆的“上、右、下、左”分别代表“a b c d”,OK键表示“左GUI键”,PB2表示“左CTRL键”。
我的实现完全是在“JoyStickMouse”例程的基础上进行修改。
(2)需要修改的地方
首先是描述符:要多使用一个端点、因此接口描述符要修改,增加一个端点描述符,报告描述符也要修改成键盘数据集合。
其次是要增加中断输出端点处理。分析数据,并控制LED灯(把它当成大小写指示灯。
2、移植前的准备工作
开始进行移植。
(1)增加命令ukey。
鼠标是用的命令umouse,这里改成ukey,由于这两个现在还不能同时实现,所以命令数不用增加,直接在原来的基础上修改。这里甚至连命令处理函数的名称我都不修改了。
(2)修改usb_desc.c
将设备描述符里的产品序列号由02 00 改为 02 01。
将HID接口描述符所用的端点数目 由1个 改为 2个。
增加了一个端点描述符:
0x07, /*bLength: Endpoint Descriptor size*/
USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
0x01, /*使用1号的输出端点*/
0x03, /*中断端点*/
0x04, /*wMaxPacketSize: 4 Byte max */
0x00,
0x20,
加了这个端点描述符后,要改变配置集合描述符的长度。加上7就行了,这个在头文件中用“define”重新定义就行了。
最重要的修改报告描述符:
上一篇博文这个工作已经做好了。改过之后的描述符变为61=0x3D个字节,所以要修改报告描述符的长度,这个也是在头文件中修改。
修改字符串描述符,产品名称改为“ntsc2004的小键盘”。产品序列号改变为“stm2004”。
改变之后,先单独编译一下,没有发生错误。
(3)增加一个usb_endp.c
这个函数专门用于处理中断输出端点数据的接收和处理。
中断端点1输出处理是调用:
void (*pEpInt_OUT[7])(void) =
{
EP1_OUT_Callback,
EP2_OUT_Callback,
EP3_OUT_Callback,
EP4_OUT_Callback,
EP5_OUT_Callback,
EP6_OUT_Callback,
EP7_OUT_Callback,
};
第一个函数进行处理的,所以我们在这个文件里就实现这个函数。
先包含必须的头文件。
在usb_conf.h中,先把以下语句注释掉。
//#define EP1_OUT_Callback NOP_Process。因为我们接下来要实现它。
先不具体实现功能,只加了以下代码:
void EP1_OUT_Callback(void){
#if usb_debug
Uart_PutString("端点1中断输出\r\n" );
#endif
}
既然用到了端点1的中断输出,则必须先进行初始化,包括端点类型的设置(中断类型)、端点描述符表的初始化(给它设置接收缓冲区的地址和大小)。这个是在用户提供的初始化代码中完成的。
初始化代码在Device_Properti->Reset()函数中。
SetEPType(ENDP1, EP_INTERRUPT);
SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送缓冲区。
SetEPRxAddr(ENDP1, ENDP1_RXADDR); //设置接收缓冲区,接收报告一个字节。
SetEPTxCount(ENDP1, 2); //发送的最大数组2个。
SetEPRxCount(ENDP1,64); //接收的最大数值64个。
SetEPRxStatus(ENDP1, EP_RX_NAK);
SetEPTxStatus(ENDP1, EP_TX_NAK); //设置端点状态,现在为不响应。
那么端点什么时候变得有效呢?
(4)修改usbmouse.c
我这里就不改变文件名称了。
(5)改变Joystick_Send(KeyAct)的行为。
void Joystick_Send(u8 Keys)
{
u8 Mouse_Buffer[2] = {0, 0};
switch (Keys)
{
case 'a':
Mouse_Buffer[1]=0x59; //对应小键盘上的“<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1”。
break;
case 'b':
Mouse_Buffer[1]=0x5A; // “2”
break;
case 'c':
Mouse_Buffer[1]=0x5B;
break;
case 'd':
Mouse_Buffer[1]=0x5C;;
break;
case 1:
Mouse_Buffer[0] |= 0x01; //左Ctrl键。
break;
case 4:
Mouse_Buffer[0] |= 0x08; //左GUI键
break;
default:
return;
}
UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 2);
SetEPTxValid(ENDP1);
Mouse_Buffer[0] = 0;
Mouse_Buffer[1] = 0;
}
(6)编写usb_endp.c
在端点1输出中断中如下处理:
void EP1_OUT_Callback(void){
u8 OutBuf;
#if usb_debug
Uart_PutString("端点1数据:" );
#endif
PMAToUserBufferCopy(&OutBuf, GetEPRxAddr(ENDP1), 1); //读取一个字节的数据到用户缓冲区 OutBuf。
#if usb_debug
Uart_PutHex(OutBuf);
Uart_PutString("\r\n" );
#endif
if ( OutBuf & 0x01 )
GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);
else
GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET);
SetEPRxValid(ENDP1);
}
3、下载测试。
整个工程编译下载,很快就成功了。在设备管理器发现了该设备如下所示:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
但按键测试的时候,发现了这样的问题:
打开一个word文档,定位光标。然后按下一个键“UP”,结果发现文档一直持续不停的写入“1”。
想了想,应该是没有发送按键释放消息,在按键松开以后,键盘还应该发一个“对应按键位置数据清0”的消息。
这样程序稍微改一下,再次下载,程序已经正常工作了。
还有没有实现“abcd”的输入,而是取代以小键盘上的“1234”。因为我不知道abcd的HID对应键值,而1234在《圈圈》书上有,所以我也懒得去测试abcd的代码了,直接就用1234
用户377235 2015-8-27 11:58
用户973744 2011-11-5 07:22