[APM32F0]APM32F072 USB键盘+鼠标

这次给大家介绍一下如何用APM32F072的USB HID配置一个 USB键盘+鼠标 复合设备的过程。
首先我们需要1个USB键盘的例程(官方有例程)
第二步我们需要1个USB 鼠标的例程  (官方有例程)
第三步将他们结合起来变成USB 键盘+鼠标
 


这里我们用USB鼠标的例程基础上添加键盘的功能。

第亿、打开USB_HID例程,修改USBD_ConfigDesc中的(USBD_CONFIG_DESCRIPTOR_SIZE)。
如下图所示的宏定义。配置集合的长度,由之前的34,改为41.
 


 


第二、USBD_ConfigDesc函数继续往下走找到
1、端点个数:由0x01变成0x02.
2、接口协议:由0x02(鼠标)变成0x01(键盘)。
这里主要还是以键盘功能为主,鼠标只是以一个附属功能加入到了键盘里。
 


3、在原来的鼠标例程上的最下面增加了一个输出端点的描述符:
 


第三,在usbd_hid.c修改USBD_HIDReportDesc函数报告描述符的长度:之前这里是鼠标的报告描述符,长度是74 改成117
 


 


接下来就是将键盘和鼠标的报告描述符合并为一个数组,分别在键盘和鼠标的报告描述符中放一个报告ID,
键盘的报告ID是1,鼠标的报告ID是2。这样USB主机就可以区分开收到的数据是键盘或是鼠标的数据。
 


 


这是加入后HID键盘+鼠标里的完整报告描述符

复制

uint8_t USBD_HIDReportDesc[USBD_HID_MOUSE_REPORT_DESC_SIZE] =

{



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

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

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

    0x85, 0x01,                    //   REPORT_ID (1)

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

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

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

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

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

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

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

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

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

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

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

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

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

    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)

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

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

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

    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)

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

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

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

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

    0xc0,                           // END_COLLECTION

                

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

    0x09, 0x02,                    // USAGE (Mouse)

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

    0x85, 0x02,                    //   REPORT_ID (2)

    0x09, 0x01,                    //   USAGE (Pointer)

    0xa1, 0x00,                    //   COLLECTION (Physical)

    0x05, 0x09,                    //     USAGE_PAGE (Button)

    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)

    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)

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

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

    0x95, 0x03,                    //     REPORT_COUNT (3)

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

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

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

    0x75, 0x05,                    //     REPORT_SIZE (5)

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

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

    0x09, 0x30,                    //     USAGE (X)

    0x09, 0x31,                    //     USAGE (Y)

    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)

    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)

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

    0x95, 0x02,                    //     REPORT_COUNT (2)

    0x81, 0x06,                    //     INPUT (Data,Var,Rel)

    0xc0,                          //   END_COLLECTION

    0xc0                           // END_COLLECTION

};


这样,我们USB键盘+鼠标二合一就改好了, 那么需要怎么使用呢?
第三、鼠标和键盘的使用属性简单介绍:
1、Mouse 鼠标:
我们用的鼠标主要就四个属性:键位(左键、右键、中键),左右移动、上下移动、滑轮
第 1 个字节(buff[0]):按钮状态    0x01左键   0x02右键   0x04中键(滚轮按钮)
第 2 个字节(buff[1]):X 轴移动量
第 3 个字节(buff[2]):Y 轴移动量
第 4 个字节(buff[3]):滚轮移动量  0x01表示滚轮向前滚动一格;0xFF表示滚轮向后滚动一格;0x80是个中间值,不滚动。
以下是一个简单的鼠标使用发送函数示例:

复制

void HidMouse_Write(uint8_t key)

{

    int8_t x = 0;

    int8_t y = 0;

        

    int8_t Button = 0;

    int8_t Wheel = 0;

        

    uint8_t buffer[4] = {0, 0, 0, 0};



    switch (key)

    {

        case HID_MOUSE_KEY_LEFT:

            x -= 10;                        

        break;



        case HID_MOUSE_KEY_RIGHT:

            x += 10;

        break;



        case HID_MOUSE_KEY_UP:

            y -= 10;                

        break;



        case HID_MOUSE_KEY_DOWN:

            y += 10;

        break;



        case HID_MOUSE_BUTTON:

            Button = 0x01;                        //0x01左键   0x02右键   0x04中键(滚轮按钮)

        break;

                                

        case HID_MOUSE_WHEEL:

            Wheel = 0xff;                //0x01表示滚轮向前滚动一格;0xFF表示滚轮向后滚动一格;0x80是个中间值,不滚动。

        break;                                

        default:

            return;

    }

    buffer[0] = Button;

    buffer[1] = x;

    buffer[2] = y;

    buffer[3] = Wheel;

                

    s_statusEP = 0;



    USBD_TxData(USBD_EP_1, buffer, sizeof(buffer));

}


2、Keyboard 键盘:
在键盘 HID 报告格式中,每个字节代表不同的含义:
第 1 个字节(buff[0]) 修饰键的状态(如 Ctrl、Alt、Shift 等)。
0x01 表示左 Ctrl 按下。
0x02 表示左 Shift 按下。
0x04 表示左 Alt 按下。
依此类推。
第 2 个字节(buff[1]):保留字节,通常为 0,不使用。
第 3 到第 8 个字节(buff[2] - buff[7]):按键代码,最多可以同时报告 6 个按键。
例如:
0x04 表示字母 'A' 键。
0x05 表示字母 'B' 键。
依此类推。
以下是一个简单的键盘使用发送函数示例:A-Z

复制

void USB_DevUserApplication(void)

{

    static uint8_t userAppState = USER_APP_INIT;

    static uint8_t interval = 0;

    static uint8_t report[8] = { 0 };

    static uint8_t i = 4;



    switch (userAppState)

    {

        case USER_APP_INIT:

            interval = USBD_CUSTOM_HID_ReadInterval(&gUsbDeviceFS);



            report[0] = 0;

            report[1] = 0;

            report[2] = 0;

            report[3] = 0;

            userAppState = USER_APP_RUN;

            break;



        case USER_APP_RUN:

            if (!APM_MINI_PBGetState(BUTTON_KEY1))

            {

                APM_DelayMs(10);

                if (!APM_MINI_PBGetState(BUTTON_KEY1))

                {

                    if(i > 29)

                    {

                        i = 4;

                        report[2] = KEYBOARD_ENTER;

                        USBD_CUSTOM_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);

                        APM_DelayMs(20);

                        report[2] = 0;

                        USBD_CUSTOM_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);

                        APM_DelayMs(20);

                    }

                    

                    report[2] = i;

                    USBD_CUSTOM_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);

                    

                    APM_DelayMs(20);

                    

                    report[2] = 0;

                    USBD_CUSTOM_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);

                    

                    i++;

                    

                    while(!APM_MINI_PBGetState(BUTTON_KEY1));

                }

            }



            APM_DelayMs(interval);

            break;

    }

}


现在我们将它结合起来向USB主机发送数据的时候就需要做出改变了,现在的数组的第一个元素是报告ID,后面才是键盘数据或鼠标数据。
在上面的两个示例中,USB键盘我们定义了一个8元素的数组,USB鼠标我们定义了一个4元素的数组。
现在我们需要一个数组,在同一时间的时候只发送一种数据,再加上报告ID,所以变成9个.
以下是一个简单的键+鼠标使用发送函数示例

复制

void USB_DevUserApplication(void)

{

    static uint8_t userAppState = USER_APP_INIT;

    static uint8_t interval = 0;



    uint8_t KeyBoard[9] = {1,0,0,0,0,0,0,0,0};

    uint8_t Mouse[9] = {2,0,0,0,0,0,0,0,0};

    static uint8_t i = 4;                



    switch (userAppState)

    {

        case USER_APP_INIT:

            interval = USBD_HID_ReadInterval(&gUsbDeviceFS);



            KeyBoard[0] = 0;

            KeyBoard[1] = 0;

            KeyBoard[2] = 0;

            KeyBoard[3] = 0;

            userAppState = USER_APP_RUN;

            break;



        case USER_APP_RUN:

            if (!APM_MINI_PBGetState(BUTTON_KEY1))

            {

                APM_DelayMs(10);

                if (!APM_MINI_PBGetState(BUTTON_KEY1))

                {

                    if(i > 29)

                    {

                        i = 4;

                        KeyBoard[3] = KEYBOARD_ENTER;

                        USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)KeyBoard, sizeof(KeyBoard));

                        APM_DelayMs(20);

                        KeyBoard[3] = 0;

                        USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)KeyBoard, sizeof(KeyBoard));

                        APM_DelayMs(20);

                    }

                                                                                KeyBoard[3] = i;

                    USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)KeyBoard, sizeof(KeyBoard));

                    

                    APM_DelayMs(20);

                    

                    KeyBoard[3] = 0;

                    USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)KeyBoard, sizeof(KeyBoard));

                    

                    i++;

                    

                    while(!APM_MINI_PBGetState(BUTTON_KEY1));

                }

            }



            if (!APM_MINI_PBGetState(BUTTON_KEY2))

            {

                APM_DelayMs(10);

                if (!APM_MINI_PBGetState(BUTTON_KEY2))

                {

                                                                                Mouse[3] -= 10;

                    USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)Mouse, sizeof(Mouse));

                }

            }



            APM_DelayMs(interval);

            break;

    }

}


---------------------
作者:Peixu
链接:https://bbs.21ic.com/icview-3392870-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值