STM32做一个鼠标键盘复合设备求救@computer00
https://bbs.21ic.com/forum.php?mod=viewthread&tid=631382&fromuid=745651
由于论坛中同样的问题没有最终解决,因此重开帖。
目的:通过修改报告描述符,利用报告ID的方法,实现单接口的HID USB键盘和鼠标复合设备;
方法:借鉴《圈圈教你学USB》;
问题描述:
①已识别为复合设备,并安装驱动成功;
②但是按按键时,鼠标和键盘数据PC无法识别;
③已通过串口读取到需要发送的数据,因此判定按键数据采集过程正常;怀疑USB设备问题;
使用BUS HOUND检测到设备重启6次后挂起!劳烦大家帮忙分析下,集思广益!
const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
/*****************************keyboard ReportDescriptor**************/
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, //REPORT ID(1)
0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
/* 16 */
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
/* 32 */
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM(0)
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
0x05, 0x07, // USAGE_PAGE(keboard/Keypad)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
/* 52 */
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3) ÐÞ¸ÄÄÚÈÝ
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0xc0, // END_COLLECTION
/* 67 */
/*****************************Mouse ReportDescriptor**************/
0x05,0x01, //USAGE_PAGE(Generic Desktop)
0x09,0x02, //USAGE(MOUSE)
0xa1,0x01, //COLLECTION
0X85,0X02, //REPORT ID(2)
0x09,0x01, /*Usage(Pointer)*/
0xa1,0x00, /*Collection(Linked)*/
0x05,0x09, /*Usage Page(Buttons)*/
0x19,0x01, /*Usage Minimum(1)*/
/* 16 */
0x29,0x03, /*Usage Maximum(3)*/
0x15,0x00, /*Logical Minimum(0)*/
0x25,0x01, /*Logical Maximum(1)*/
0x95,0x03, /*Report Count(3)*/
0x75,0x01, /*Report Size(1)*/
0x81,0x02, /*Input(Variable)*/
0x95,0x01, /*Report Count(1)*/
0x75,0x05, /*Report Size(5)*/
/* 32 */
0x81,0x01, /*Input(Constant,Array)*/
0x05,0x01, /*Usage Page(Generic Desktop)*/
0x09,0x30, /*Usage(X axis)*/
0x09,0x31, /*Usage(Y axis)*/
0x09,0x38, /*Usage(Wheel)*/
0x15,0x81, /*Logical Minimum(-127)*/
0x25,0x7F, /*Logical Maximum(127)*/
0x75,0x08, /*Report Size(8)*/
/* 48 */
0x95,0x03, /*Report Count(3)*/
0x81,0x06, /*Input(Variable, Relative)*/
0xC0, /*End Collection*/
0xc0 //End Collection again
/* 54 */
}
; /* Joystick_ReportDescriptor */
描述符的代码大家应该很熟悉,是书中的源码!
void Joystick_Send(u8 buf0,u8 buf1,u8 buf2,u8 buf3,u8 buf4,u8 buf5,u8 buf6,u8 buf7,u8 buf8)
{
u8 Keyboard_Buffer[9] = {0, 0, 0, 0,0,0,0,0,0};
/* prepare buffer to send */
Keyboard_Buffer[0]=buf0;
Keyboard_Buffer[1]=buf1;
Keyboard_Buffer[2]=buf2;
Keyboard_Buffer[3]=buf3;
Keyboard_Buffer[4]=buf4;
Keyboard_Buffer[5]=buf5;
Keyboard_Buffer[6]=buf6;
Keyboard_Buffer[7]=buf7;
Keyboard_Buffer[8]=buf8;
/*copy mouse position info in ENDP1 Tx Packet Memory Area*/
UserToPMABufferCopy(Keyboard_Buffer, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
}
USB数据传输键盘数据程序段如上,由于含ID为因此数据结构为1+8;
主函数中的程序端如下;
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "string.h"
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h"
#include "I2C.h"
#include "mpu6050.h"
#include "24l01.h"
u32 usb_abs(u32 x1,u32 x2)
{
if(x1>x2)return x1-x2;
else return x2-x1;
}
void usb_port_set(u8 enable)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
if(enable)_SetCNTR(_GetCNTR()&(~(1<<1)));
else
{
_SetCNTR(_GetCNTR()|(1<<1));
GPIOA->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X00033000;
PAout(12)=0;
}
}
int main(void)
{
u8 Keyboard_Buffer[8] ={0,0,0,0,0,0,0,0};
u8 key;
short X,Y,X1,Y1;
u8 keysta;
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
NVIC_Configuration(); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶
uart_init(9600); //´®¿Ú³õʼ»¯Îª9600
printf("´®¿Ú³õʼ»¯Íê±Ï\r\n");
KEY_Init(); //°´¼ü³õʼ»¯
printf("°´¼ü³õʼ»¯Íê±Ï\r\n");
usb_port_set(0); //USBÏȶϿª
delay_ms(300);
usb_port_set(1); //USBÔÙ´ÎÁ¬½Ó
USB_Interrupts_Config();
Set_USBClock();
USB_Init();
printf("USB¶¼³õʼ»¯Íê±ÏÁË£¬É§Ä꣬¿ªÊ¼½ÓÊÕ°É£¡£¡£¡\r\n");
while(1)
{
key=KEY_Scan(1);//Ö§³ÖÁ¬°´
if(key==WKUP_PRES) Keyboard_Buffer[3]=0x15; //r
if(key==KEY1_PRES) Keyboard_Buffer[3]=0x16; //s
if(key==KEY0_PRES) Keyboard_Buffer[3]=0x17; //t
// printf(" %8d%8d\r\n",Keyboard_Buffer[0],Keyboard_Buffer[1]);
Joystick_Send(0x01,Keyboard_Buffer[0],0,Keyboard_Buffer[3],0,0,0,0,0);
Keyboard_Buffer[3]=0x00;
}
}
为实现方便性,主函数暂时只考虑发送键盘数据;
|