如何去构建一个键盘
第一步:没有键的键盘
首先让我们做一个发出x字符(基于每秒一次)的USB键盘,Arduino Micro开发板是实现该目标的一个不错的选择,因为它的功能ATmega32U4microcontroller(一种AVR microcrontroller)和相同的处理器是UHK的大脑。
说到USB-capable AVR microcontrollers,用于AVR(LUFA)的轻量级USB框架是库的选择。它使得这些处理器成为打印机、MIDI设备、键盘或任何其他USB设备类型的“大脑”。
当设备插入USB端口时,设备会传递一些被称为USB描述符的特殊数据结构。这些描述符会告知主机所连接设备的类型和性质,并由一个树结构表示。一个设备可以实现的不止一个函数,而是多个。这让事情更加复杂。让我们看看UHK描述符的结构:
- Device descriptor
- Configuration descriptor
- Interface descriptor 0: GenenricHDI
- Endpoint descriptor
- Interface descriptor 1: Keyboard
- Endpoint descriptor
- Interface descriptor 2: Mouse
- Endpoint descriptor
大多数键盘只暴露单一的键盘接口描述符,这是有道理的。然而UHK也会暴露鼠标接口描述符,因为用户可以指令键盘的任意键来控制鼠标指针,所以键盘可以当作鼠标使用。GenericHID接口服务相当于一个为所有特性键盘交换配置信息的通信通道。
现在我们已经创建了描述符,下面代码则演示了其每秒一次发送x字符:
USB是一种查询协议,这意味着主机定期间隔(通常是125次/s)查询设备,以此来找出是否有任何新的数据发送。与此相关的回调是CALLBACK_HID_Device_CreateHIDReport()函数,在isSecondElapsed变量为1情况下向主机发送x字符的扫描码,isSecondElapsed在每秒的基础上循环的设置为1,回调时设置为0。
第二步:四个键的键盘
在这一点上我们的键盘不是非常有用的,如果我们在这上面作出实际类别,那样会很好。为此我们需要一些键,这些键需被置入一个键盘矩阵。一个全尺寸的104键键盘可以有18列6行,而我们必须把它简化为2x2的键盘矩阵,这是示意图:
它在开发板上是这样呈现的:
假设ROW1连接PINA0、ROW2连接PINA1、COL1连接PORTB0以及COL2连接PORTB1,那么扫描代码会是这样:
代码一次扫描一列,并读取个人键开关的状态,然后将这种状态保存到一个数组中,通过我们前文所说的CALLBACK_HID_Device_CreateHIDReport()函数,相关的扫描代码将发送这些基于数组的状态。
第三步:一个键盘两个部分
到目前为止,我们已经构建了一个普通键盘的开端。但是我们的目标是先进的人体工程学,鉴于人都有两只手,我们最好添加另一半键盘。
另一半的键盘将具有另一个键盘矩阵,重复之前的步骤。而其中令人兴奋的是两部分键盘之间的通信,这里有三个最受欢迎的电子设备互连协议:SPI、I2C和UART。在实际当中,我们会在这种情况下用到UART:
UART需要同行使用相同的波特率、数据位和停止位。现在左键盘通过UART将一个字节的信息发送到右键盘,以此代表按下键或释放键,右键盘对这些信息进行半加工并在相应的内存中对这些全键盘矩阵数组的状态进行操作。
左键盘发送信息示例:
右键盘接受信息如下:
KeyboardRxCallback()中断处理程序会在一个字节通过UART被接收时触发,考虑到中断处理程序应该尽快执行,所以收到的信息会放到一个环形的缓冲区留待后面处理。环形缓冲区最终会被主循环处理,键盘矩阵也会基于信息而被更新。
上面所说的是实现该点的最简单的方法,但是最终的协议要更加复杂。你需要考虑多字节信息的处理,而且个人信息也要通过CRC-CCITT校验来检查其完整性。
在这一点上,我们的实验板模型或许会让你印象深刻:
第四步:满足LED显示屏
这是为了让用户能够定义多个特定于应用的键映射来提高生产效率。用户需要意识到一些正被用于键映射的方式,一个集成的LED显示屏被构建于键盘内,下图展示了这种模型:
LED显示是由一个8x6矩阵实现的:
每两行红色LED符号代表14-segment LED显示的分段,白色LED符号则代表了额外的三个状态指标。
通过LED驱动电流并使其亮起来,相应的列设为高电压,相应的行设为低电压。该系统一个有趣的结果是,在任何给定的时刻,只有一列是可以被启用的,而其他列是被禁用的。有人可能会认为这套系统不能工作于整个LED,但是在现实中,列和行更新的太快以至于凭人的肉眼无法看到明显的闪烁。
LED矩阵由两个集成电路(IC)驱动,一个驱动行,一个驱动列,驱动列的源IC是PCA9634 I2C LED驱动:
驱动行的为TPIC6C595:
让我们看下相关代码:
LedMatrix_UpdateNextRow()将以每毫秒的速度被调用,更新LED矩阵的一行,LedMatrix数组存储单个LED灯的状态,状态信息源于通过UART的按/释键事件。
整体情况
到这里我们已经逐步为自己的键盘建立了所有的必需组件。现在需要从全局出发,键盘的内部就像一个微型计算机网络:大量节点相互连接。所不同的是测量节点之间的距离不是米或公里,而是厘米,并且节点不是成熟的计算机,而是微型的集成电路。
但是到目前为止说的大多都是键盘装置方面的细节,关于UHK代理提的不多。UHK代理是配置器应用,通过键盘来满足用户的自定义需求。可以见于下段代码:
创建原型
一切制造之前都需要有一个CAD设计:
3D打印的键盘会是这个样子:
基于机械设计和原理、印刷电路板设计。右半部分的PCB在KiCad中会是这样:
PCB表面贴装组件必须手工焊接:
最后经过3D印刷、抛光、组装等,我们会得到这样一个原型: