键盘-0准备工作-0借鉴工作模式

本文探讨了无线机械键盘的工作原理,重点分析了两种不同类型的键盘矩阵电路,并使用逻辑分析仪观察了某品牌键盘主控的扫描过程。文章还详细解释了键盘在不同状态下的工作模式,包括正常操作及休眠模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一、缘由

手里机械键盘日渐增多,看到有无线机械键盘的需求。感觉不会太复杂就上手试试吧。

不过先得了解机械键盘的键盘矩阵是怎么工作的,之前有为罗技K230主控画过原理图,是普通的没有上拉的扫描矩阵。


类似这样的。

而在百度上找到有上拉的类似这种:

(百度上搜到的)

二、资料

键盘工作原理我已经了解了,只是这两种电路选择的区别不太清楚。而主控去轮询时候以什么样的方式工作也不甚明晰。

既然手上有一片某品牌的键盘主控,我就尝试用逻辑分析仪查看一下工作方式以作参考。


这是之前测得的主控矩阵,在实际应用中它是没有上拉的电路。按照我对矩阵的理解,主控中上图X和Y两组引脚上总会有一组是主动输出信号的。

不过在实际测量中遇到不少问题,键盘一段时间没有响应就进入静默,10-20均为高电平,其他引脚为低电平。

在多次尝试后发现上电后一段时间才能在10-20引脚检测到高电平背景下有低电平脉冲。找了半个小时后发觉是我把时序想得太短,毕竟某品牌某型号所采用的主控是nRF24LE1,内核是51,在200ms周期内只能看到偶发的脉冲。


调整采集频率和周期后,检测到规律的信号。


除此之外还有些尚未找到规律的


以及





三、工作模式分析

通过第二张图的时序分析,某品牌键盘主控采用内部上拉一组引脚,周期性下拉。假设按键(1,10)按下时,1引脚检测到上拉的高电平,同时周期性(0.25s)下拉,当下拉时由中断或扫描方法判断此时下拉是由10引脚产生。

下拉时长3.81ms,没错,与未找到规律的其中一个周期时间长度相等,不知是否有关联。

同时也想明白了这种工作模式的好处,在一段时间没有按键后,系统进入休眠,10-20引脚保持高电平不再动作,另一组引脚依然处于输入模式,我判断采用中断保证实时性。当休眠中按下键后,引脚被高电平产生中断进入正常的工作模式。


继续分析后两张未知含义的脉冲是什么用,同时等待52832到货。

### STM32 实现 PS2 小键盘接口 为了在STM32上实现PS2小键盘的功能或接口,可以借鉴`PS2KeyAdvanced`库的应用方式并适配到STM32环境中。下面提供了具体的实现方法以及示例代码。 #### 准备工作 确保已经准备好如下材料: - STM32微控制器开发板(推荐使用如STM32F103系列) - PS/2接口的小键盘模块 - 连接线若干根用于连接MCU与小键盘的数据线和时钟线 #### 软件环境搭建 对于STM32来说,通常会采用HAL库或者LL库来进行底层驱动编程。这里假设读者已经在电脑端配置好了适合于所选型号的IDE(比如Keil MDK、STM32CubeIDE),并且能够正常编译运行程序。 #### 编写代码逻辑 由于原生的`PS2KeyAdvanced`是针对Arduino平台设计的,在STM32上的应用可能需要做一些调整。以下是基于STM32 HAL库的一个简化版本的例子,它实现了基本的PS/2协议解析功能[^1]。 ```c #include "main.h" #include <string.h> #define DATA_PIN GPIO_PIN_3 #define CLOCK_PIN GPIO_PIN_4 #define GPIO_PORT GPIOA UART_HandleTypeDef huart1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); // 定义一个函数用来初始化GPIO口作为输入模式 void ps2_init(){ __HAL_RCC_GPIOA_CLK_ENABLE(); // 设置DATA_PIN为浮空输入 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DATA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct); // 设置CLOCK_PIN为下拉输入 GPIO_InitStruct.Pin = CLOCK_PIN; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct); } uint8_t read_ps2_data(){ uint8_t data=0; int i,j; while(HAL_GPIO_ReadPin(GPIO_PORT,CLOCK_PIN)==SET); //等待时钟变低 for(i=0;i<11;i++){ while(HAL_GPIO_ReadPin(GPIO_PORT,CLOCK_PIN)!=RESET); //等待时钟上升沿 if(i==0){ continue; //跳过起始位 } j=i-1; if(j>=8){ //处理奇偶校验位和停止位 break; } delay_us(5); //延时一小段时间让电平稳定下来 if(HAL_GPIO_ReadPin(GPIO_PORT,DATA_PIN)){ data|=(1<<(7-j)); } while(HAL_GPIO_ReadPin(GPIO_PORT,CLOCK_PIN)); //等待下降沿到来 } return data; } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); char buffer[2]; sprintf(buffer,"OK\r\n"); HAL_UART_Transmit(&huart1,(uint8_t*)buffer,strlen((char*)buffer),HAL_MAX_DELAY); ps2_init(); while (1) { if(read_ps2_data()!=0xFF){ uint8_t key=read_ps2_data(); sprintf(buffer,"%d\r\n",key); HAL_UART_Transmit(&huart1,(uint8_t*)buffer,strlen((char*)buffer),HAL_MAX_DELAY); } } } ``` 这段代码展示了如何利用STM32的GPIO外设来模拟PS/2接口的工作原理,并通过串口打印出收到的按键值。需要注意的是这只是一个非常基础的实现方案,实际项目中还需要考虑更多细节问题,例如错误检测机制、特殊字符映射表等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值