基于RISC-V CH32V103的鼠标键盘摇杆手柄Joystick学习开发板--实例Eg3_KeyBoard

基于RISC-V CH32V103的鼠标键盘摇杆手柄Joystick学习开发板–实例Eg3_KeyBoard

3.3 实例Eg3_KeyBoard

本节我们目标是实现模拟键盘的功能,枚举一个具有Shift键+1~8键的模拟键盘功能;

3.3.1硬件设计

同第一章节

3.3.2 软件设计

在上一章节的基础上,我们在USB_DevTransProcess中找到报告描述符的获取,并修改为如下内容

case USB_DESCR_TYP_REPORT:
if(((pSetupReqPak->wIndex)&0xff) == 0)     //接口0报表描述符
{
    pDescr = KeyboardRepDesc;                      //数据准备上传
    len = sizeof(KeyboardRepDesc);
    Ready = 1;             //如果有更多接口,该标准位应该在最后一个接口配置完成后有效
}
else len = 0xff;                                //本程序只有2个接口,这句话正常不可能执行
break;

另外Keyboard的报告描述符KeyboardRepDesc如下

const UINT8  MouseRepDesc[]=
{
        0x05, 0x01, // USAGE_PAGE (Generic Desktop)
        0x09, 0x06, // USAGE (Keyboard)
        0xa1, 0x01, // COLLECTION (Application)
        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, 0xFF, // LOGICAL_MAXIMUM (255)
        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
};

然后是报文数据的处理如下:

uint8_t Keyboad_Buf[8]={0};
uint8_t lastshift=0,currentshift=0;
uint8_t lastkeycode[8]={0},currentkeycode[8]={0};
static uint8_t KdataFL=0;
//处理并上报数据
void Keyboard_Handle(void)
{	
    memset(Keyboad_Buf,0,8);
    uint8_t i=0;uint8_t idx=2;

    if(SW1==1)
    {
        currentshift|=0x02;
        Keyboad_Buf[0]=currentshift;
    }else{

        currentshift&=(~0x02);
        Keyboad_Buf[0]=currentshift;
    }

    if(UPKEY==0)
    {
        currentkeycode[0]=CODE1;
    }else{
        currentkeycode[0]=0x00;
    }
    if(DNKEY==0)
    {
        currentkeycode[1]=CODE2;
    }else{
        currentkeycode[1]=0x00;
    }
    if(LFKEY==0)
    {
        currentkeycode[2]=CODE3;
    }else{
        currentkeycode[2]=0x00;
    }
    if(RGKEY==0)
    {
        currentkeycode[3]=CODE4;
    }else{
        currentkeycode[3]=0x00;
    }
    if(BKKEY==0)
    {
        currentkeycode[4]=CODE5;
    }else{
        currentkeycode[4]=0x00;
    }
    if(MDKEY==0)
    {
        currentkeycode[5]=CODE6;
    }else{
        currentkeycode[5]=0x00;
    }
    if(STKEY==0)
    {
        currentkeycode[6]=CODE7;
    }else{
        currentkeycode[6]=0x00;
    }
    if(TBKEY==0)
    {
        currentkeycode[7]=CODE8;
    }else{
        currentkeycode[7]=0x00;
    }

    for(i=0;i<8;i++)
    {
        if(currentkeycode[i]!=lastkeycode[i])
        {
            Keyboad_Buf[idx]=currentkeycode[i];
            if(++idx>=8)
            {
                idx=2;
            }
            KdataFL=1;
        }else{
            Keyboad_Buf[idx]=0x00;
        }
    }
    if(currentshift!=lastshift)
    {
        KdataFL=1;
    }

    if(KdataFL!=0)
    {
        KdataFL=0;
        while( Endp1Busy )
        {
            ;                                               //如果忙(上一包数据没有传上去),则等待。
        }
        Endp1Busy = 1;                                      //设置为忙状态
        memcpy(pEP1_IN_DataBuf, Keyboad_Buf, 8);
        DevEP1_IN_Deal(8);

    }
    Delay_Ms(5);
    memcpy(lastkeycode,currentkeycode,8);
    lastshift=currentshift;
}

最后是main函数,只改了while中的Keyboard_Handle();

/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Return         : None
*******************************************************************************/
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);

    printf("SystemClk:%d\r\n",SystemCoreClock);
    printf("USBHD Device Test\r\n");

    pEP0_RAM_Addr = EP0_Databuf;
    pEP1_RAM_Addr = EP1_Databuf;
    pEP2_RAM_Addr = EP2_Databuf;

    USBHD_ClockCmd(RCC_USBCLKSource_PLLCLK_1Div5,ENABLE);
    USB_DeviceInit();
    NVIC_EnableIRQ( USBHD_IRQn );
    ADC_DMA_CONF();
    KEY_INIT();

    while(1)
    {
        printf("X=%d,Y=%d\r\n",ADC_ConvertedValue[0],ADC_ConvertedValue[1]);
        if(Ready)
        {
            Keyboard_Handle();
        }
    }
}
3.3.3 下载验证

我们把固件程序下载进去可以,打开“设备与打印机”可以看到USB设备枚举成了一个“LD Keyboard”,如下图。
image

我们打开一个键盘测试网页,地址如下:
https://keyboard.bmcx.com/
按摇杆按键SW1即为shift键按下,其他键分别对应主键盘的1~8;shift+1-8键也可以组合;

视频教程:https://www.bilibili.com/video/BV17r4y1z758/

猜你喜欢

转载自blog.csdn.net/qq_36250901/article/details/123841424