机械键盘,造轮子,还是造键盘?

是的,没错,我要重新开始造轮子。

最开始萌生此想法的原因是想把一个USB接口的键盘改造成蓝牙键盘(别问我为什么不直接买一个)。想改的前提有两个:一是笔者用的是笔记本,总会碰到USB接口不够用的尴尬局面;二是笔者之前从事蓝牙设备的开发工作,具备将键盘改造成蓝牙接口的能力。

后来由于种种原因,想法被搁置了。正好最近有个朋友有需求要做一个键盘的转接板,是直接从原始的矩阵键盘接口转到USB接口,就是下面这货。

好吧,离蓝牙接口还有段距离,不过能做成USB的,那就一定做成蓝牙的。

言归正传,开始动手吧。

一、硬件篇

无非就是个矩阵键盘嘛,嗯,看一下这货的资料,14*8,好家伙,线挺多的,这是全尺寸键盘的节奏?不过IO口多还真不是问题,市面上MCU那么多,随便选就好了。找个易用的又带有USB接口的并且比较熟悉的,关键是手头上就有的,非stm32莫属了。

后面仔细一看,发现实物和上图的FPC引脚数对不上 ==!,没办法了,总不能拆了键盘去看键码吧……先搭个线完成功能吧。

STM32F103C8T6,引脚够用,成本够低,开发环境成熟,资源丰富。

下面是最小系统板,万能的XX上有卖,10+可以搞定,还包邮。

IO分配好,PA0-PA7作为列(COL)输入,配置为下拉输入,PB0-PB5作为行(ROW)输出,默认为推挽输出。USB为PA11、PA12,PA9、PA10分别为TX、RX作调试用。

硬件就这么多了。

二、软件篇

软件才是让人头大的东西。

1、搭建工程

不过好在ST官方还算给力,做出了一个叫做STM32CubeMX的东西,简直是想快速搭建工程配置外设者的福音。

打开STM32CubeMX,新建工程,stm32_usb_kb。

之所以选择C8而不是C6版本,是因为市场上C8的出货量大,再就是因为开发时可以选容量稍大的产品,到后期程序完善了、优化了,可以量产时候去用的更低容量的IC节省成本。

点OK确定,然后来配置外设。

首先配置RCC,选择使用外部高速时钟。

再配置SYS,主要使用SWD作为程序的下载和调试接口,不选JTAG的原因是JTAG要占用多个IO(主要是把我要用的PB口占用了)。Timebase Source选SysTick,会要用到计时功能 。

然后配置串口,这里选择USART1,配置成异步模式。

再配置USB,勾选框框,MiddleWares的USB选择Human Interface Description

然后在芯片的引脚上配置我们需要用到的引脚,PA及PAB口,直接在IO口上单击即可选择需要的功能。

配置好的界面如下所示:

这时发现Clock Configuration选项卡上出现X,这是因为修改了时钟源造成的,点进去,会提示是否选择自动配置,当然选yes了。

切换到配置页面,配置GPIO,可以统一进行配置。

点OK完成配置,然后在Project菜单中选择Generate Code

配置好工程名,选择好存放位置,选择好IDE,然后确定。

至此,一个最基本的带有USB功能的支持矩阵键盘扫描的工程诞生了。

2、测试矩阵扫描的基本功能

a)首先初始化一下IO口,没啥好说的。

void matrix_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);/*Configure GPIO pins : PA0 PA1 PA2 PA3
PA4 PA5 PA6 PA7 */
GPIO_InitStruct.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_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*Configure GPIO pins : PB0 PB1 PB2 PB10
PB11 PB12 PB13 PB14
PB15 PB3 PB4 PB5
PB6 PB7 PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

b)按键扫描函数

uint16_t KS_ScanForKeyPress(uint8_t iActiveLine)
{
uint32_t outputRegister = ((uint32_t)1<< iActiveLine );
GPIOB->ODR = outputRegister;
uint32_t scannedInput = (GPIOA->IDR & 0x000000FF);
return scannedInput;
}uint8_t KS_PrintScanLines(void)
{
uint16_t scannedInput;
uint8_t keyScans = 0;for(uint8_t i = 0; i < 16; ++i)
{
scannedInput = KS_ScanForKeyPress(i);
if (scannedInput > 0)
{
// detected a key press
printf("Key press detected at %d/0x%04X\n", (i+1), scannedInput);
++keyScans;
}
}
return keyScans;
}

c)测试

int main(void)
{
uint8_t scanCode;/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */
printf("Hello, STM kb!\r\n");/* Infinite loop */
while (1)
{
HAL_Delay(10);
scanCode = KS_PrintScanLines();
}
}

用每一行的线分别接触每一列的线,测试矩阵。

3、处理按键的逻辑

a)按键冲突问题

买键盘的时候,经常会听到全键无冲、六键无冲等关键字,尤其对喜欢玩游戏的朋友来说。关于其概念,想要了解的可以自行百度,在这里只需要要知道相邻两行两列矩阵上的三个键按下可能会出现另外一个未按下键的键值即可(针对是没在矩阵上做过处理的键盘来讲,加了二极管的键盘不在此列)。程序上要处理这种情况,当然,现在薄膜键盘的矩阵设计在一般的办公场景及大部分游戏场景很难会出现多键冲突的情况。

b)组合键处理

如按下ctrl键后又点击C(点击:点下去,然后立马释放)、按下Ctrl+alt+……等等。

c)功能键Fn

大多笔电按键较少,无法将常用的按键一次性布局,往往会提供Fn+其它键实现一些不能布下键的功能,为实现这种功能,程序上要实现多套键码,动态切换。

d)……(一些未想到的)

说了这么多,却没有敲半句代码实现。

虽然说是造轮子,但不是说从制造材料开始,那是原始人才会做的事。

我不是代码的生产者,而是代码的搬运工。

要善于借鉴前人的经验。

打开github,输入关键字“USB keyboard”,有一堆开源项目。反复查看代码,发现这家伙的比较适合移植,有很多Demo,平台近似,提交比较活跃,文档写得也比较清楚。

很多DIY机械键盘的实现也可用上此工程。

https://github.com/tmk/tmk_keyboard

里面有几篇文档值得关注一下,可以详细了解整个程序的结构及框架的实现。

及工程根目录下的README,通读好处多多。

4、移植到M3平台,MDK开发环境

这里不多说,只与各位看官提提几个要注意的地方。

a)github的工程是用GNU写的,在Keil MDK ARM编译器环境下要设置--gnu的编译选项,要么你就自己修改代码,如匿名结构体。

b)一些语法上的修改,如case Fn1...Fn9: 在ANSI C下是没有这种写法的,需要自行更改。其次是Keil下没有0b00001111这种表示方法。

c)代码移植选择tmk_core文件夹的内容即可,里面有avr平台的实现,可以对照改为STM32的实现,主要是初始化,定时器,串口输出。

d)参照keyboard/hbkb的代码,自行实现Matrix.c中的矩阵扫描部分,config.h文件中一些宏的开启等。宏的话,参照此文件下的设置即可,如果要实现更加高级的功能,看官自行研究。keymap.c矩阵的修改。

e)需要实现host_driver_t驱动,主要是报告描述,此结构位于report.h文件下。

贴一个我用到的代码目录:

建议:串口输出一定要实现好,对调试有莫大的帮助。(可在debug.c文件中开启要调试的部分)

5、测试

键码还没搞到手,先用单独的按键替代测试。接了按键“1”与ctrl键,输出正常,连接电脑也能正常打字,试试组合键也还行。

按下“1”

按下ctrl+1

三、总结篇

看似常用且简单的东西还是是有一些技术含量在里面的。

1、以前没有好好写过矩阵键盘的扫描代码,现在写过了并且记忆深刻了;

2、了解了一些与编译器相关的关键字,如__attirbute__ (weak);

3、KEIL MDK ARM下支持GNU语法编译方法:project->options->C/C++下,添加--gnu

a)keil中不支持GNU中的匿名结构体,需要在结构体前添加#pragma anon_unions或者在编译选项中添加--gnu

b)“--gnu”实际上是在ARMCC中加入支持GNU扩展格式,当然实际上Keil是可以添加GCC的编译器的,通过keil菜单中“Project > Manage > Components, Environment, Books..”添加,前提是你得提前装好GCC编译器。官方原文:http://www.keil.com/arm/gnu.asp

4、Keil环境中,用memset()对结构体“清零”时要注意四字节对齐,否则会出错。可在定义结构体的末尾(;前面)添加__attirbute__ ((aligned(4))),如uint8_t EXTERN_DHCPBUF[1024] __attribute__((aligned(4)));

5、移植过来的代码与平台结合性不强,可以移植大部分平台上去了,也可以采取各种通讯接口及协议。蓝牙键盘的改造过程有望了。

四、拖拉篇

本来前三节写好就要发的,结果一直没拿到键码,拖到现在,于是有了这一节。

很早之前就想买一把机械键盘玩玩了,无奈要不就是价格太贵,要不就是按键手感不符合。

正好有了之前的基础,倒是有机会做一把键盘了。

一般的机械键盘组成部分:轴(关键),键帽,卫星轴,键盘PCBA,底壳,如果用的是3脚的轴还需要按键的固定钢板。

轴的分类不多说(主要是我也说不清楚 ==!),看好介绍,然后买个试轴器自己感受,再决定上手什么轴。X宝上大把的。

用习惯了笔记本,发现小键盘区用得并不多,再就是希望尽可能的节省成本吧,决定做60键的键盘,小巧,方便携带出去装B。自己做好配列,60键还是足够用的。

GitHub上找找,结果有开源的PCB,但自己用的IC不一样,还是得改改。

链接在此:https://github.com/komar007/gh60

下载后发现是KiCAD格式的,找遍若干方法,还是没能将其转换为AD的格式。最终没办法,自己重新画矩阵,重新画封装。

当然,不是傻傻的去弄。

提供一方法:

AD由Gerber反向生成PCB:

1)新建CAM文件,分别导入gerber和drill文件;

2)必要时调整一下Layer Order,Tables->Layers Order;

3)关键:Tools->Netlist->Extract;

4)File->Export->Export to PCB;

5)网络表是重命名的网络表,可以从原理图重新导入网络表。

至此,得到可供“使用”的PCB,仅仅是用于提取封装、外形尺寸及定位。

对比原设计,我的设计添加了些自己的东西,如添加了灯的接口:

  • 为每一排按键添加了独立的灯控制电路,限于MCU只有四个PWM口,只好把最后两排接到同一个PWM口上。这样,便可独立控制每一排灯了。
  • 为CAPS Lock添加了单独的灯,可以知道当前Caps的状态。
  • 将Mini USB接口换成了更常用的插件Micro USB(现在安卓手机大行其道,Micro USB线还是更常见一些)。
  • 留出了矩阵及灯的接口,方便用其它平台打造键盘,比如蓝牙,wifi等等。

3D预览的PCB:

实物:

做得比较着急,还是出了一些问题,比如丝印上漏了个W,少打一个孔,少一电阻等等小问题……

目前PCB的功能还只是能打字,还没有把灯及固件升级的功能做上去,等闲一点的时候再买材料完善了。

等完善好了我会将PCB、原理图及固件源代码放到CSDN或Github上,欢迎有需要的人士下载或提出宝贵的建议~

PS:本人踩过的坑也全部在本文写明,绝不藏私。如果真有愿意动手的朋友,相信也会迎难而上的。

从0开始制作机械键盘相关推荐

  1. STM32DIY机械键盘

    STM32DIY制作机械键盘 键盘图片 硬件介绍 原理图 PCB 3D 效果图 PCB打样 程序 芯片一定不能贪便宜!!! 首先要感谢O正义阿庚O这位up主开源的资料 b站视频 键盘图片 硬件介绍 键 ...

  2. 为了程序员的颈椎,做机械键盘的 Cherry 发布了把椅子!

    北京时间 6 月 10 日,65 岁的德国老牌外设厂商 CHERRY 在北京丽都皇冠假日酒店举办了 2018 年新品发布会.一口气发布了三款机械键盘,一个游戏竞技鼠标,以及一把相当电竞范儿的椅子. 新 ...

  3. 程序员必备神卡!仅500张,价值万元0.8折抢!4个月小白变大牛!(送机械键盘)

    小白程序员初入职场或者即将进入职场,都会面临4个问题: 1)能力还比较青涩,不能满足工作的需求,需要学习 2)但是刚刚步入职场,收入有限,太多技术课程太贵 3)精挑细选的技术课程,太难了,听不懂,老师 ...

  4. 究极丐版客制化机械键盘制作全纪录(下:程序下载)

    究极丐版客制化机械键盘制作全纪录(下:程序下载) 前排提示:由于键盘制作时间距离写文章的时间比较久远所以不对分享文件的正确性保证!!!! 在比较久之前写了个上篇,当时比较有时间为了简单的记录自己做键盘 ...

  5. 樱桃cherryMX8.0机械键盘for MacBookPro

    科大讯飞语音鼠标for Mac 安装说明 https://mouse.iflytek.com/#/xfhome3 https://support.apple.com/zh-cn/HT204434 Ma ...

  6. 从零开始的踩坑生活(3):有关cherry mx8.0 机械键盘和Ubuntu系统的不兼容(输入延迟卡顿cpu占用高)

    2021/03/05更新: 好像挺多人有一样的问题欸. 放一个链接,如果急得话可以下载,不急的话私信发邮箱,我看到就会回复. 项目场景: 最近被这个Ubuntu折腾的够呛.这里放上来一个很鬼畜的问题 ...

  7. 键盘定位板图纸_聊聊机械键盘的结构

    很多人觉得客制化机械键盘都有着风格迥异的设计,但它们的结构都是互通的,万变不离其宗.这篇文章就粗略的讲一下机械键盘的结构与特殊设计. 客制化键盘的结构分Case mount和Tray mount两大类 ...

  8. 触发键盘_雷蛇这款光轴机械键盘开箱评测,光速触发,颜值爆表

    首先感谢头条众测给予雷蛇猎魂光蛛精英版机械键盘的测评机会,雷蛇作为在游戏设备领域深耕的领先者,其生产的游戏设备深得游戏玩家喜爱,下面我们来一睹这款雷蛇机械键盘的风采. 首先从包装盒正面可以感受到这款雷 ...

  9. python实现抢劵_双十一福利丨机械键盘、蓝牙音箱送送送!Python/UI/Unity多场微课解剖双十一套路!...

    福利来了 别等双十一 多场微课get双十一全套路 机械键盘送送送! 福 利 来 了 双十一福利第一波 - 11/1-11/11 - 机械键盘送送送 有品位的IT侠 早已get起双十一的新姿势 11月1 ...

最新文章

  1. TiDB 在知乎万亿量级业务数据下的实践和挑战
  2. openstack-Icehouse版本部署安装
  3. css hack技术整理
  4. Ubuntu下MySQL、Redis以及MongoDB三个数据库的启动、重启以及停止命令
  5. mysql动静分离_haproxy的web服务负载均衡、动静分离、 MySQL服务负载均衡、状态监控...
  6. Anaconda安装(ubuntu 14.04.03 LTS 64bit)
  7. 王自如、罗永浩将一起出镜直播带货?罗永浩亲自回应
  8. 指定跳转_炸裂!PPT能一键统一色彩,还能一键跳转到指定颜色
  9. Java程序设计语言基础02:Java中的基本数据类型和运算符
  10. 利用ajax查询数据库显示在前台,ajax动态查询数据库数据并显示在前台的方法
  11. pycharm 修改darcual(暗黑)主题滚动条颜色
  12. CVE-2018-0798:Microsoft office 公式编辑器 Matrix record 字段栈溢出漏洞调试分析
  13. 孙空空的Vue之路-Day03-Class与Style的绑定操作
  14. js中的数据驱动(基础)
  15. 区块链倪老师:区块链思维——序章
  16. 搭建webdav文件共享服务器,使用Nginx搭建WebDav作为简易共享空间
  17. 《数据库概论》实验(3)-交互式SQL--简单查询
  18. System.Data.SqlClient.SqlError: 备份集中的数据库备份与现有的 'XXX' 数据库不同。 (Microsoft.SqlServer.Smo)...
  19. 国内最值得关注的10家人工智能语音识别公司
  20. python绘画_python绘图骚操作之plotly(一)——plotly的基本绘图方式

热门文章

  1. 一个MM的八年“抗战”
  2. 北林计算机分数,2021北京林业大学录取分数线-北京林业大学分数线-2021北京林业大学录取查询网址...
  3. 中国手机浏览器行业运行态势与前景趋势预测报告(2022-2028年版)
  4. Instagram的技术架构
  5. 我们该如何通向全球商业的新秩序?
  6. unity使用Socket与HTTP连接服务器传输数据包
  7. silly-datetime
  8. 联想小新air14指纹失效解决方法
  9. android日历价格控件,Android 自定义价格日历控件
  10. 从Windows到Linux(二)