一、前言

一般来说使用IO作为设备的按键输入就够用了 ,但是我就是想实现制作的按键键盘就像按实际键盘的某些按键一样,这样在上位机处理就容易很多,直接调用键盘类函数就可以了。

而且自己根据需求可以自定义按键数量,按键功能,我这里制作一个小数字键盘,增加了Delete按键,使用的是红轴机械按键,效果如下



二、环境

 stm32f1

keil

window10 

三、正文

我画的原理图如下



pcb



核心程序


#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "delay.h"
#include <stdio.h>
#include "string.h"
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h"
//键盘配置按键
BUTTON_STATE key_all[232]=
{
    0,0,0,0, //0  00  //Fn键的偏移位置
    0,0,0,0, //1  01  Keyboard ErrorRollOver
    0,0,0,0, //2  02  Keyboard POSTFail
    0,0,0,0, //3  03  Keyboard ErrorUndefined
    0,0,0,0, //4  04  Keyboard a and A
    0,0,0,0, //5  05  Keyboard b and B
    0,0,0,0, //6  06  Keyboard c and C
    0,0,0,0, //7  07  Keyboard d and D
    0,0,0,0, //8  08  Keyboard e and E
    0,0,0,0, //9  09  Keyboard f and F
    0,0,0,0, //10 0A  Keyboard g and G
    0,0,0,0, //11 0B  Keyboard h and H
    0,0,0,0, //12 0C  Keyboard i and I
    0,0,0,0, //13 0D  Keyboard j and J
    0,0,0,0, //14 0E  Keyboard k and K
    0,0,0,0, //15 0F  Keyboard l and L
    0,0,0,0, //16 10  Keyboard m and M
    0,0,0,0, //17 11  Keyboard n and N
    0,0,0,0, //18 12  Keyboard o and O
    0,0,0,0, //19 13  Keyboard p and P
    0,0,0,0, //20 14  Keyboard q and Q
    0,0,0,0, //21 15  Keyboard r and R
    0,0,0,0, //22 16  Keyboard s and S
    0,0,0,0, //23 17  Keyboard t and T
    0,0,0,0, //24 18  Keyboard u and U
    0,0,0,0, //25 19  Keyboard v and V
    0,0,0,0, //26 1A  Keyboard w and W
    0,0,0,0, //27 1B  Keyboard x and X
    0,0,0,0, //28 1C  Keyboard y and Y
    0,0,0,0, //29 1D  Keyboard z and Z
    0,GPIOA,GPIO_Pin_7,0, //30 1E  Keyboard 1 and !
    0,GPIOB,GPIO_Pin_1,0, //31 1F  Keyboard 2 and @
    0,GPIOB,GPIO_Pin_13,0, //32 20  Keyboard 3 and #
    0,GPIOA,GPIO_Pin_6,0, //33 21  Keyboard 4 and $
    0,GPIOB,GPIO_Pin_0,0, //34 22  Keyboard 5 and %
    0,GPIOB,GPIO_Pin_12,0, //35 23  Keyboard 6 and ^
    0,GPIOA,GPIO_Pin_5,0, //36 24  Keyboard 7 and &
    0,GPIOC,GPIO_Pin_5,0, //37 25  Keyboard 8 and *
    0,GPIOB,GPIO_Pin_11,0, //38 26  Keyboard 9 and (
    0,GPIOC,GPIO_Pin_4,0, //39 27  Keyboard 0 and )
    0,GPIOB,GPIO_Pin_14,0, //40    28  Keyboard Return (ENTER)
    0,0,0,0, //41    29  Keyboard ESCAPE
    0,GPIOA,GPIO_Pin_0,0, //42    2A  Keyboard DELETE (Backspace)
    0,0,0,0, //43    2B  Keyboard Tab
    0,0,0,0, //44    2C  Keyboard Spacebar
    0,0,0,0, //45    2D  Keyboard - and (underscore)
    0,0,0,0, //46    2E  Keyboard = and +
    0,0,0,0, //47    2F  Keyboard [ and {
    0,0,0,0, //48    30  Keyboard ] and }
    0,0,0,0, //49    31  Keyboard \ and |
    0,0,0,0, //50    32  Keyboard Non-US # and ~
    0,0,0,0, //51    33  Keyboard ; and :
    0,0,0,0, //52    34  Keyboard ‘ and “
    0,0,0,0, //53     35  Keyboard Grave Accent and Tilde
    0,0,0,0, //54     36  Keyboard, and <
    0,GPIOB,GPIO_Pin_10,0, //55     37  Keyboard . and >
    0,0,0,0, //56     38  Keyboard / and ?
    0,0,0,0, //57     39  Keyboard Caps Lock
    0,0,0,0, //58     3A  Keyboard F1
    0,0,0,0, //59     3B  Keyboard F2
    0,0,0,0, //60     3C  Keyboard F3
    0,0,0,0, //61     3D  Keyboard F4
    0,0,0,0, //62     3E  Keyboard F5
    0,0,0,0, //63     3F  Keyboard F6
    0,0,0,0, //64     40  Keyboard F7
    0,0,0,0, //65     41  Keyboard F8
    0,0,0,0, //66     42  Keyboard F9
    0,0,0,0, //67     43  Keyboard F10
    0,0,0,0, //68     44  Keyboard F11
    0,0,0,0, //69     45  Keyboard F12
    0,0,0,0, //70  46  Keyboard PrintScree n 
    0,0,0,0, //71  47  Keyboard Scroll Lock
    0,0,0,0, //72  48  Keyboard Pause 
    0,0,0,0, //73  49  Keyboard Insert
    0,0,0,0, //74  4A  Keyboard Home
    0,0,0,0, //75  4B  Keyboard PageUp
    0,0,0,0, //76  4C  Keyboard Delete Forward
    0,0,0,0, //77  4D  Keyboard End
    0,0,0,0, //78  4E  Keyboard PageDown
    0,0,0,0, //79  4F  Keyboard RightArrow
    0,0,0,0, //80  50  Keyboard LeftArrow
    0,0,0,0, //81  51  Keyboard DownArrow
    0,0,0,0, //82  52  Keyboard UpArrow
    0,0,0,0, //83  53  Keypad Num Lock and Clear
    0,GPIOA,GPIO_Pin_1,0, //84  54  Keypad /
    0,GPIOA,GPIO_Pin_2,0, //85  55  Keypad *
    0,GPIOA,GPIO_Pin_3,0, //86  56  Keypad -
    0,GPIOA,GPIO_Pin_4,0, //87  57  Keypad +
    0,0,0,0, //88  58  Keypad ENTER
    0,0,0,0, //89  59  Keypad 1 and End
    0,0,0,0, //90  5A  Keypad 2 and Down Arrow
    0,0,0,0, //91  5B  Keypad 3 and PageDn 
    0,0,0,0, //92  5C  Keypad 4 and Left Arrow
    0,0,0,0, //93  5D  Keypad 5
    0,0,0,0, //94  5E  Keypad 6 and Right Arrow
    0,0,0,0, //95  5F  Keypad 7 and Home
    0,0,0,0, //96  60  Keypad 8 and Up Arrow
    0,0,0,0, //97  61  Keypad 9 and PageUp 
    0,0,0,0, //98  62  Keypad 0 and Insert
    0,0,0,0, //99  63  Keypad . and Delete
    0,0,0,0, //100 64  Keyboard Non-US \ and | 3;
    0,0,0,0, //101 65  Keyboard Application
    0,0,0,0, //102 66  Keyboard Power
    0,0,0,0, //103 67  Keypad =
    0,0,0,0, //104 68  Keyboard F13
    0,0,0,0, //105 69  Keyboard F14
    0,0,0,0, //106 6A  Keyboard F15
    0,0,0,0, //107 6B  Keyboard F16
    0,0,0,0, //108 6C  Keyboard F17
    0,0,0,0, //109 6D  Keyboard F18
    0,0,0,0, //110 6E  Keyboard F19
    0,0,0,0, //111 6F  Keyboard F20
    0,0,0,0, //112 70  Keyboard F21
    0,0,0,0, //113 71  Keyboard F22
    0,0,0,0, //114 72  Keyboard F23
    0,0,0,0, //115 73  Keyboard F24
    0,0,0,0, //116 74  Keyboard Execute  √
    0,0,0,0, //117 75  Keyboard Help  √
    0,0,0,0, //118 76  Keyboard Menu  √
    0,0,0,0, //119 77  Keyboard Select  √
    0,0,0,0, //120 78  Keyboard Stop  √
    0,0,0,0, //121 79  Keyboard Again  √
    0,0,0,0, //122 7A  Keyboard Undo  √
    0,0,0,0, //123 7B  Keyboard Cut  √
    0,0,0,0, //124 7C  Keyboard Copy  √
    0,0,0,0, //125 7D  Keyboard Paste  √
    0,0,0,0, //126 7E  Keyboard Find  √
    0,0,0,0, //127 7F  Keyboard Mute  √
    0,0,0,0, //128 80  Keyboard Volume Up  √
    0,0,0,0, //129 81  Keyboard Volume Down  √
    0,0,0,0, //130 82  Keyboard Locking Caps Lock 12 √
    0,0,0,0, //131 83  Keyboard Locking Num Lock 12 √
    0,0,0,0, //132 84  Keyboard Locking Scroll Lock 12 √
    0,0,0,0, //133 85  Keypad Comma 27 107
    0,0,0,0, //134 86  Keypad Equal Sign 29
    0,0,0,0, //135 87  Keyboard International1 15,28 56
    0,0,0,0, //136 88  Keyboard International2 16
    0,0,0,0, //137 89  Keyboard International3 17
    0,0,0,0, //138 8A  Keyboard International4 18
    0,0,0,0, //139 8B  Keyboard International5 19
    0,0,0,0, //140 8C  Keyboard International6 20
    0,0,0,0, //141 8D  Keyboard International7 21
    0,0,0,0, //142 8E  Keyboard International8 22
    0,0,0,0, //143 8F  Keyboard International9 22
    0,0,0,0, //144 90  Keyboard LANG1 25
    0,0,0,0, //145 91  Keyboard LANG2 26
    0,0,0,0, //146 92  Keyboard LANG3 30
    0,0,0,0, //147 93  Keyboard LANG4 31
    0,0,0,0, //148 94  Keyboard LANG5 32
    0,0,0,0, //149 95  Keyboard LANG6 8
    0,0,0,0, //150 96  Keyboard LANG7 8
    0,0,0,0, //151 97  Keyboard LANG8 8
    0,0,0,0, //152 98  Keyboard LANG9 8
    0,0,0,0, //153 99  Keyboard Alternate Erase 7
    0,0,0,0, //154 9A  Keyboard SysReq/Attention 1
    0,0,0,0, //155 9B  Keyboard Cancel
    0,0,0,0, //156 9C  Keyboard Clear
    0,0,0,0, //157 9D  Keyboard Prior
    0,0,0,0, //158 9E  Keyboard Return
    0,0,0,0, //159 9F  Keyboard Separator
    0,0,0,0, //160 A0  Keyboard Out
    0,0,0,0, //161 A1  Keyboard Oper
    0,0,0,0, //162 A2  Keyboard Clear/Again
    0,0,0,0, //163 A3  Keyboard CrSel/Props
    0,0,0,0, //164 A4  Keyboard ExSel
    0,0,0,0, //165 A5-CF  Reserved
    0,0,0,0, //166 A5-CF  Reserved
    0,0,0,0, //167 A5-CF  Reserved
    0,0,0,0, //168 A5-CF  Reserved
    0,0,0,0, //169 A5-CF  Reserved
    0,0,0,0, //170 A5-CF  Reserved
    0,0,0,0, //171 A5-CF  Reserved
    0,0,0,0, //172 A5-CF  Reserved
    0,0,0,0, //173 A5-CF  Reserved
    0,0,0,0, //174 A5-CF  Reserved
    0,0,0,0, //175 A5-CF  Reserved
    0,0,0,0, //176 Keypad 00
    0,0,0,0, //177 Keypad 000
    0,0,0,0, //178 Thousands Separator  33
    0,0,0,0, //179 Decimal Separator  33
    0,0,0,0, //180 Currency Unit  34
    0,0,0,0, //181 Currency Sub-unit  34
    0,0,0,0, //182 Keypad (
    0,0,0,0, //183 Keypad )
    0,0,0,0, //184 Keypad {
    0,0,0,0, //185 Keypad }
    0,0,0,0, //186 Keypad Tab
    0,0,0,0, //187 Keypad Backspace
    0,0,0,0, //188 Keypad A
    0,0,0,0, //189 Keypad B
    0,0,0,0, //190 Keypad C
    0,0,0,0, //191 Keypad D
    0,0,0,0, //192 Keypad E
    0,0,0,0, //193 Keypad F
    0,0,0,0, //194 Keypad XOR
    0,0,0,0, //195 Keypad ^
    0,0,0,0, //196 Keypad %
    0,0,0,0, //197 Keypad <
    0,0,0,0, //198 Keypad >
    0,0,0,0, //199 Keypad &
    0,0,0,0, //200 Keypad &&
    0,0,0,0, //201 Keypad |
    0,0,0,0, //202 Keypad ||
    0,0,0,0, //203 Keypad :
    0,0,0,0, //204 Keypad #
    0,0,0,0, //205 Keypad Space
    0,0,0,0, //206 Keypad @
    0,0,0,0, //207 Keypad !
    0,0,0,0, //208 Keypad Memory Store
    0,0,0,0, //209 Keypad Memory Recall
    0,0,0,0, //210 Keypad Memory Clear
    0,0,0,0, //211 Keypad Memory Add
    0,0,0,0, //212 Keypad Memory Subtract
    0,0,0,0, //213 Keypad Memory Multiply
    0,0,0,0, //214 Keypad Memory Divide
    0,0,0,0, //215 Keypad +/-
    0,0,0,0, //216 Keypad Clear
    0,0,0,0, //217 Keypad Clear Entry
    0,0,0,0, //218 Keypad Binary
    0,0,0,0, //219 Keypad Octal
    0,0,0,0, //220 Keypad Decimal
    0,0,0,0, //221 Keypad Hexadecimal
    0,0,0,0, //222 DE  Reserved
    0,0,0,0, //223 DF  Reserved
    0,0,0,0, //224 LeftControl
    0,0,0,0, //225 LeftShift
    0,0,0,0, //226 LeftAlt
    0,0,0,0, //227 LeftGUI
    0,0,0,0, //228 RightControl
    0,0,0,0, //229 RightShift
    0,0,0,0, //230 RightAlt
    0,0,0,0, //231 RightGUI
};

u8 keys_index[232];
int keys_none0=0; //非零个数
//按键初始化函数
void KeyBoard_Init(void) //IO初始化
{
     GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF|RCC_APB2Periph_GPIOG,ENABLE);//使能PORTA,PORTE时钟
    for(int i = 0; i < sizeof(key_all)/sizeof(BUTTON_STATE); i++){
        if(key_all[i].port==0||key_all[i].pin==0) continue;
        GPIO_InitStructure.GPIO_Pin |= key_all[i].pin;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成输入,默认下拉
        //初始化index
        keys_index[keys_none0]=i;
        keys_none0++;
    }
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIO
    GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化GPIO
}
u8 keybuf[8]={0,0,0,0,0,0,0,0}; //按键发送缓存
int keybufp=2; //位置
void putkey(u32 key) //发现一个键按下
{
    if(keybufp==8){//若已经超过6个了
        memset(keybuf,0xff,8);//发送0xffff;
        keybufp++;
        return ;
    }
    else if(keybufp>8){
        return ;
    }
    keybuf[keybufp++]=key;
}
u32 SYS_time=0;

void check_press(BUTTON_STATE *bts) //判断按键是否按下
{
    if(bts->port==0||bts->pin==0){
        return ;
    }
    if(GPIO_ReadInputDataBit(bts->port,bts->pin)==1){//判断按键是否按下
        if(bts->tick==0){//上次未按下的按键tick次数增加
            bts->tick++;
            bts->state=0;//清除按下状态
            LED0=0;
        }
        else{
            bts->state=1;
            LED0=1;
        }
    }
    else{//若释放了
        bts->tick=0;
        bts->state=0;
        LED0=0;
    }
}
void key_scan(void) //100Hz
{
    keybufp=2; //位置
    memset(keybuf,0,8);
    //首先轮询所有位置
    for(int i = 0; i < keys_none0; i++)
        check_press(key_all+keys_index[i]);
    //去抖动 
    delay_ms(10);//去抖动 
    //再次轮询所有位置
    for(int i = 0; i < keys_none0; i++)
        check_press(key_all+keys_index[i]);
    //特殊键直接置位
    if(key_all[LeftControl].state) { keybuf[0] |= (1<<0); }
    if(key_all[LeftShift].state) { keybuf[0] |= (1<<1); }
    if(key_all[LeftAlt].state) { keybuf[0] |= (1<<2); }
    if(key_all[LeftGUI].state) { keybuf[0] |= (1<<3); }
    if(key_all[RightAlt].state) { keybuf[0] |= (1<<6); }
    //普通键追加到buf
    for(int i = 0; i < keys_none0; i++){
        int j=keys_index[i];
        if(key_all[j].state){
            putkey(j);
        }
    }
    UserToPMABufferCopy(keybuf, GetEPTxAddr(ENDP1), 8);
    SetEPTxValid(ENDP1);
}

程序框架简单清晰,不混乱,无其他乱起八糟的功能,只有usb键盘功能,易扩展

折腾了也有2个晚上,我的程序和板子工程文件如下:下载点这里,有意想不到的惊喜噢

四、结语

嘿嘿!