【沁恒 CH58x 应用】利用CH582M将有线键盘改为无线键盘

兼容芯片:CH582、CH583

代码以及固件 gitee 仓库:https://gitee.com/wenlilili/ch582m-bluetoothkbd

固件在其中 obj 文件夹中的 USBhidtoBLE.hex。

 

代码具体思路:

1. 阅读CH582M官方例程---HID-Keyboard

【沁恒RISC-V内核 CH582】蓝牙HID键盘代码解读:http://bbs.eeworld.com.cn/thread-1198402-1-1.html

关键部分在hidkbd.c中:

uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events)
{
    static uint8_t send_char = 4;
    
    /*省略其余无关部分*/
    
      if(events & START_REPORT_EVT)
    {
        hidEmuSendKbdReport(send_char);//发送字符
        send_char++;
        if(send_char >= 29)
            send_char = 4;
        hidEmuSendKbdReport(0x00);
        tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 2000);
        return (events ^ START_REPORT_EVT);
    }
}

其中 send_char 是HID字符代码,如下所示:可见send_char=4 的时候,对应的字符为a

图1 HID键盘键值对应码

2. 阅读CH582M官方例程---USB_U2Host

【沁恒RISC-V内核 CH582】CH582 USB HOST 代码解读 http://bbs.eeworld.com.cn/thread-1198831-1-1.html

关键部分在 main() 函数中usb枚举和读取 usb设备数据的部分。

/* 如果设备是键盘 */
        loc = U2SearchTypeDevice(DEV_TYPE_KEYBOARD); // 在ROOT-HUB以及外部HUB各端口上搜索指定类型的设备所在的端口号
        if(loc != 0xFFFF)
        { // 找到了,如果有两个KeyBoard如何处理?
            i = (uint8_t)(loc >> 8);
            len = (uint8_t)loc;
            SelectU2HubPort(len);                                                 // 选择操作指定的ROOT-HUB端口,设置当前USB速度以及被操作设备的USB地址
            endp = len ? DevOnU2HubPort[len - 1].GpVar[0] : ThisUsb2Dev.GpVar[0]; // 中断端点的地址,位7用于同步标志位
            if(endp & USB_ENDP_ADDR_MASK)
            {                                                                                                        // 端点有效
                s = USB2HostTransact(USB_PID_IN << 4 | endp & 0x7F, endp & 0x80 ? RB_UH_R_TOG | RB_UH_T_TOG : 0, 0); // 传输事务,获取数据,NAK不重试
                if(s == ERR_SUCCESS)
                {
                    endp ^= 0x80; // 同步标志翻转
                    if(len)
                        DevOnU2HubPort[len - 1].GpVar[0] = endp; // 保存同步标志位
                    else
                        ThisUsb2Dev.GpVar[0] = endp;
                    len = R8_USB2_RX_LEN; // 接收到的数据长度
                    if(len)
                    {
                        U2SETorOFFNumLock(RxBuffer);
                        PRINT("keyboard data: ");
                        for(i = 0; i < len; i++)//此处打印出所有接收到的 USB 键盘发送来的数据
                        {
                            PRINT("x%02X ", (uint16_t)(RxBuffer));
                        }
                        PRINT("\n");
                    }
                }
                else if(s != (USB_PID_NAK | ERR_USB_TRANSFER))
                {
                    PRINT("keyboard error %02x\n", (uint16_t)s); // 可能是断开了
                }
            }
            else
            {
                PRINT("keyboard no interrupt endpoint\n");
            }

 

3-蓝牙HID和USB_HOST的例程结合在一起

具体思路就是:

  1. 键盘通过USB,向CH582M发送数据,CH582通过一个缓存(RxBuffer)接收数据;(CH582M 此时为USB主机,键盘为USB设备)
  2. CH582接收到键盘的数据后,通过自身的蓝牙,发送给电脑数据。
  3. 电脑接收到数据之后,打印出相应的字符。

实现代码可以看文章:

【沁恒RISC-V内核 CH582】CH582 有线键盘转蓝牙键盘 http://bbs.eeworld.com.cn/thread-1199038-1-1.html

关键部分是按照上面的具体思路,将缓存接收到的数据,在HID-Keyboard中调用HID设备发送报文函数:HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, RxBuffer);

if(events & START_REPORT_EVT)
    {
        if (need_send) {
            HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, RxBuffer);//这行代码是关键
            need_send = 0;
        }
        tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 1);//提高发送频率,设置为1ms执行一次
        return (events ^ START_REPORT_EVT);
    }

 

 

附录:

1. 《键盘按键名称及HID扫描码及VK虚拟键码对照表》:https://blog.csdn.net/kKmaro/article/details/130256738

posted @ 2023-12-21 23:32  FBshark  阅读(454)  评论(0编辑  收藏  举报