#申请原创# @21小跑堂
7.基于官方USB例程和矩阵按键实现数字小键盘
上个帖子已经实现了对鼠标的模拟,接下来再做个键盘的,官方已经提供了一个键盘的例程,但是是针对MINI board的并且用的IO也与TINY board的不同,先以TINY board的鼠标例程为基础改一个针对TINY board的键盘例程出来
需要改动的地方不多,都在usbd_descriptor.c这个文件里,首先是USBD_HS_PID要改为1004
之后把USBD_HID_ITF_PORTOCOL_MOUSE换为USBD_HID_ITF_PORTOCOL_KEYBOARD,USBD_HID_MOUSE_REPORT_DESC_SIZE换为USBD_HID_KEYBOARD_REPORT_DESC_SIZE,这两个都有两处要替换,注意查找
之后将usbd_hid_keyboard.c加入工程并删掉原来的usbd_hid.c
最后将键盘消息处理函数复制过来替换掉原来鼠标的就行了,注意把里面的MINI替换成TINY
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_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_TINY_PBGetState(BUTTON_KEY1))
{
APM_DelayMs(10);
if (!APM_TINY_PBGetState(BUTTON_KEY1))
{
if(i > 29)
{
i = 4;
report[2] = KEYBOARD_ENTER;
USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);
APM_DelayMs(20);
report[2] = 0;
USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);
APM_DelayMs(20);
}
report[2] = i;
USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);
APM_DelayMs(20);
report[2] = 0;
USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)report, 8);
i++;
while(!APM_TINY_PBGetState(BUTTON_KEY1));
}
}
APM_DelayMs(interval);
break;
}
}
实现效果
再来实现一下矩阵按键的驱动
矩阵按键和普通按键不一样,不是一个IO对应一个按键,我用的这个是4行4列,在行线和列线的每个交叉点上设置一个按键,使用8个IO口来进行16个按键的控制读取
读取键值的方法:
先把行配置成上拉输入模式,列配置成输出模式并输出低电平,有按键按下的那一行IO输入为低电平
再把列配置成上拉输入模式,行配置成输出模式并输出低电平,有按键按下的那一列IO输入为低电平
当然上面的检测方法中你也可以输入配置成下拉输入,输出配置为推挽输出高电平,检测IO为高电平
通过行和列就能确定是哪个按键被按下了
代码实现
uint8_t lastkey = 0xFF;
void matrixkeyinit()
{
GPIO_Config_T GPIO_InitStructure;
RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOD);
GPIO_InitStructure.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
GPIO_InitStructure.mode = GPIO_MODE_OUT;
GPIO_InitStructure.otype = GPIO_OTYPE_OD;
GPIO_InitStructure.pupd = GPIO_PUPD_UP;
GPIO_Config(GPIOD, &GPIO_InitStructure);
}
uint8_t readmatrixkey()
{
uint8_t col = 0,row = 0,i,j;
GPIOD->MODE &= 0xFFFF0000;
GPIOD->MODE |= 0x00005500;
GPIOD->ODATA &= 0xFF0F;
APM_DelayUs(50);
row = GPIOD->IDATA;
GPIOD->ODATA |= 0x00F0;
GPIOD->MODE &= 0xFFFF0000;
GPIOD->MODE |= 0x00000055;
GPIOD->ODATA &= 0xFFF0;
APM_DelayUs(50);
col = GPIOD->IDATA >> 4;
GPIOD->ODATA |= 0x000F;
for(i = 0;i<4;i++)
{
if(!(row & 0x01))
break;
row >>= 1;
}
for(j = 0;j<4;j++)
{
if(!(col & 0x01))
break;
col >>= 1;
}
if(i == 4 || j == 4)
return 0xFF;
return i*4+j;
}
串口打印一下键值
得到键值分布图
接下来做个这样的小键盘
代码实现
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;
uint8_t key;
switch (userAppState)
{
case USER_APP_INIT:
interval = USBD_HID_ReadInterval(&gUsbDeviceHS);
report[0] = 0;
report[1] = 0;
report[2] = 0;
report[3] = 0;
userAppState = USER_APP_RUN;
break;
case USER_APP_RUN:
key = readmatrixkey();
report[0] = 0;
if(key != lastkey)
{
switch(key)
{
case 0:
report[2] = KEYBOARD_1_EXCLAMATION;
break;
case 1:
report[2] = KEYBOARD_2_AT;
break;
case 2:
report[2] = KEYBOARD_3_NUMBER_SIGN;
break;
case 3:
report[0] = 0x01;
report[2] = KEYBOARD_C;
break;
case 4:
report[2] = KEYBOARD_4_DOLLAR;
break;
case 5:
report[2] = KEYBOARD_5_PERCENT;
break;
case 6:
report[2] = KEYBOARD_6_CARET;
break;
case 7:
report[0] = 0x01;
report[2] = KEYBOARD_V;
break;
case 8:
report[2] = KEYBOARD_7_AMPERSAND;
break;
case 9:
report[2] = KEYBOARD_8_ASTERISK;
break;
case 10:
report[2] = KEYBOARD_9_OPARENTHESIS;
break;
case 11:
report[2] = KEYBOARD_ENTER;
break;
case 12:
report[0] = 0x02;
report[2] = KEYBOARD_8_ASTERISK;
break;
case 13:
report[2] = KEYBOARD_10_CPARENTHESIS;
break;
case 14:
report[0] = 0x02;
report[2] = KEYBOARD_3_NUMBER_SIGN;
break;
case 15:
report[2] = KEYBOARD_DOT_GREATER;
break;
default:
report[2] = 0;
break;
}
USBD_HID_TxReport(&gUsbDeviceHS, (uint8_t*)report, 8);
}
lastkey = key;
APM_DelayMs(interval);
break;
}
}
效果展示
数字符号输入
复制粘贴快捷键
上面这个例程里只能识别一个按键的按下,如何识别多个按键这里暂时先不展开了,有兴趣的可以自己尝试下
|