input core输入事件 矩阵键盘 映射 原理分析

keyBoard.c #include #include "utilities.h" sbit KEY_OUT_3 = P2^0; sbit KEY_OUT_2 = P2^1; sbit KEY_OUT_1 = P2^2; sbit KEY_OUT_0 = P2^3; sbit KEY_IN_0 = P2^4; sbit KEY_IN_1 = P2^5; sbit KEY_IN_2 = P2^6; sbit KEY 阅读详情

//这个是矩阵键盘映射表,使用内核定义的宏KEY()来建立

//#defineKEY(row, col,val) ((((row)& (MATRIX_MAX_ROWS - 1)) << 24) |\

//(((col)& (MATRIX_MAX_COLS - 1)) << 16) |\

//((val)& 0xffff))

//从上面的定义来看KEY用于唯一确认一个值,用于将(row,col,val)转换为一个单一个32位的值。

//这样存储起来,比较节省空间。高高字节用于存储行号,高低字节用于存储列号,低高和低低字节用于保存值。

//如此一来,将二维坐标(x,y)及值val转换为一个单一的32int数据。

//但是取出来的时候还得使用特殊的宏来操作。

//将扫描码映射为内核定义的标准键值,以方便上层应用程序使用。

staticintmx6sl_evk_keymap[] = {

KEY(0,0, KEY_SELECT), //映射矩阵(0,0)处按键为内核标准的KEY_SELECT键码。

KEY(0,1, KEY_BACK),

KEY(0,2, KEY_F1), //映射矩阵(0,2)处按键为内核标准的KEY_F1键码。

KEY(0,3, KEY_F2), //映射矩阵(0,3)处按键为内核标准的KEY_F2键码。

//内核自己定义的键码在linux/input.h中定义。

KEY(1,0, KEY_F3),

KEY(1,1, KEY_F4),

KEY(1,2, KEY_F5),

KEY(1,3, KEY_MENU),


KEY(2,0, KEY_PREVIOUS),

KEY(2,1, KEY_NEXT),

KEY(2,2, KEY_HOME),

KEY(2,3, KEY_NEXT),


KEY(3,0, KEY_UP),

KEY(3,1, KEY_LEFT),

KEY(3,2, KEY_RIGHT),

KEY(3,3, KEY_DOWN),

};

//这个结构体也是内核抽象出来的,定义在linux/input/matrix_keypad.h中。

//structmatrix_keymap_data {

// constuint32_t *keymap;

// unsignedint keymap_size;

//};

staticconststructmatrix_keymap_data mx6sl_evk_map_data__initconst = {

.keymap =mx6sl_evk_keymap,

.keymap_size =ARRAY_SIZE(mx6sl_evk_keymap),

};

//#defineARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

//这里的ARRAY_SIZE宏用于确认数组大小(数组有多少元素)。

//从实现来看就是使用sizeof求出整个数组占用内存大小,然后用sizeof(第一个元素)占用内存大小

//这2个数一除就能得到整个数组中元素的个数。

#defineMATRIX_MAX_ROWS 32

#defineMATRIX_MAX_COLS 32


//内核使用一个32位的数据来保存3种信息:行号,列号,键码。

//最高8位<31:24>用于保存行号。

//低高8位<23:16>用于保存列号。

//低16位<15:0>用于保存内核定义的键码。

#defineKEY_ROW(k) (((k) >> 24) & 0xff) //从32位数据中提取最高8位的行号

#defineKEY_COL(k) (((k) >> 16) & 0xff) //从32位数据中提取次高8位的列号

#defineKEY_VAL(k) ((k) & 0xffff) //从32位数据中提取低16位的映射的内核定义的键码!


//这个应该用于行列的索引值,可以在映射数组中根据行,列获取下标。

//其中对于row_shift的定义为:

*@row_shift: number of bits to shift row value by to advance to thenext line in the keymap。

//大体的意思就是:在keymap中用于移至下一行的值的位数。

//在内核中找到了imx6kpp的驱动,他的定义如下,结合起来,更好理解。

//#defineMAX_MATRIX_KEY_ROWS 8

//#defineMAX_MATRIX_KEY_COLS 8

//#defineMATRIX_ROW_SHIFT 3 //这里就是row_shift了,这里行大小为8,移至下行需要移到8个,所以2^3=8,所以这里

//row_shift就为8了。

#defineMATRIX_SCAN_CODE(row, col, row_shift) (((row) << (row_shift)) +(col))

//从上面的定义来看使用<<左移,所以2<<3=8.感觉这个函数只是将行号和列号组织在了一起而已。


//一般的驱动会有以下的代码,用于向inputcore提供事件。

//这里比较关键的是第3句,使用行列组织在一起的code从keycodes[]数组中提出映射键码,这是怎么做到的呢?


code= MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);

input_event(input_dev,EV_MSC, MSC_SCAN, code);

input_report_key(input_dev,keypad->keycodes[code],matrix_volatile_state[col]& (1 << row));


//来看一下,下面这些代码,分析一下,找出为什么?

input_dev->keycode= keypad->keycodes;

input_dev->keycodesize= sizeof(keypad->keycodes[0]);

input_dev->keycodemax= ARRAY_SIZE(keypad->keycodes);


//其实这里比较关键的,建立了映射关系!

conststructmatrix_keymap_data *keymap_data =pdev->dev.platform_data;//从平台设备中拿到映射表。


matrix_keypad_build_keymap(keymap_data,MATRIX_ROW_SHIFT,

keypad->keycodes,input_dev->keybit);

//再来看看这个映射函数的实现过程吧。

//内核中注释的意思将keymap_data转换到keymap中存储,并使用行+列来索引。

staticinlinevoid

matrix_keypad_build_keymap(conststructmatrix_keymap_data *keymap_data,

unsignedintrow_shift,

unsignedshort*keymap, unsignedlong*keybit)

{

inti;


for(i = 0; i < keymap_data->keymap_size;i++) { //循环处理每一个元素。

unsignedintkey = keymap_data->keymap[i];//存储的32位值。

unsignedintrow = KEY_ROW(key); //从32位值中拿到行号。

unsignedintcol = KEY_COL(key); //从32位值中拿到列号。

unsignedshortcode = KEY_VAL(key); //从32位值中拿到键码。


keymap[MATRIX_SCAN_CODE(row,col, row_shift)] = code; //最最关键的这句话!!在keymap中指定位置(行号+列号)存储键码!

//这里就是 行号<<8+列号 形成一个16位的数据,这样就可以唯一的标识一个数组的下标索引,将相关的键码保存在此单元中。

__set_bit(code,keybit);

}

__clear_bit(KEY_RESERVED,keybit); //这句真不知道什么意思?

//从structinput_dev结构体中找到的定义如下:

*@evbit:bitmap of types of events supported by the device (EV_KEY,

* EV_REL,etc.) 按位操作,表示这个设备支持的事件。

*@keybit:bitmap of keys/buttons this device has :按位操作,表示这个设备支持的按键。

}


好,我们再来看看上面那3句代码,用于向inputcore上报事件:

1、code= MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);

2、input_event(input_dev,EV_MSC, MSC_SCAN, code);

3、input_report_key(input_dev,keypad->keycodes[code],matrix_volatile_state[col]& (1 << row));

第1句知道了吧,根据上面的分析就是将行号<<8+列号,组合起来,构成一个16位的数据。

第2句这应该是上报类似于键盘扩展码之类的,这个暂时用不到。不过在内核中很多代码都加了这句。

第3句比较关键,关键是要正确上报映射的键码。由于之前使用matrix_keypad_build_keymap函数将键码存储到数组指定的位置,

那么下面可以轻松的使用行号<<8+列号来取到键码了。

键值1表示按下,0表示松开。现在来分析一下,还是比较简单的。

之前看到imx6中的kpp的驱动代码,结合数据手册,感觉imx6的这个kpp简单很鸡肋,没有什么功能。

只是提供了I/O的开漏输出和图腾柱输出模式,具体的扫描、消抖还得在代码中手工完成。

因为最近有个项目需要用于自定义的矩阵键盘,同时上层使用Qt来实现,看了下现在最新的qt5支持evdev,可直接从/dev/input/eventx

中读取输入事件,所以只要驱动使用input子系统上报输入事件,那么qt就肯定能收到。

由于是嵌入式设备,界面上就不能使用鼠标进行操作了,就必须使用keyPressEvent/keyReleaseEvent来实现操作了。




51单片机开发出问题 51单片机开发的问题,求大佬解答 阅读详情

相关推荐

matrix_keypad 矩阵按键驱动分析

matrix_keypad 矩阵按键驱动分析 //主要函数调用过程 matrix_keypad_probe matrix_keypad_parse_dt //根据设备树构造 pdata pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios"); pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios"); of_get_prop..

开挂的熊猫 2482

51按键及按键矩阵(复习)

AT89C51中使用按键控制数码管及按键矩阵的使用方法

qq_44941069的博客 853

嵌入式Linux输入子系统实战:在Intel Edison上监听键盘事件

在嵌入式Linux开发中,输入子系统是处理键盘、鼠标等外设的核心框架。其原理是通过内核驱动将硬件信号转换为标准输入事件,应用程序通过读取/dev/input/下的设备文件获取事件数据。这一机制为嵌入式设备提供了稳定、低延迟的输入处理能力,尤其适用于信息亭、智能控制面板等交互场景。本文以Intel Edison平台为例,深入探讨如何通过Python evdev库监听键盘事件,并解决设备权限、事件解析等常见问题,帮助开发者快速实现可靠的输入处理功能。

weixin_30756499的博客 369

六、按键

原理图 按键抖动 按键抖动必然存在,一般在10ms左右,采用定时器定期扫描,连续16ms按键状态一致,可以判定按键按下或者抬起状态。 单按键扫描 按键控制数码管显示,按一次,显示数字加一,0到9循环往复,代码: #include <reg52.h> sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; sbit KEY1 = P2^4; sbi

lingdong24的博客 1578

Proteus仿真STM32驱动矩阵键盘:从原理到实战的嵌入式开发指南

在嵌入式系统开发中,外设驱动是连接微控制器与物理世界的关键环节。矩阵键盘作为一种常见的输入设备,其驱动原理基于行列扫描法,通过分时复用GPIO端口,以较少的引脚实现多个按键的检测。这项技术的核心价值在于优化硬件资源,降低系统成本,并广泛应用于密码锁、计算器和工业控制面板等场景。Proteus仿真软件为开发者提供了一个无硬件的虚拟验证平台,能够可视化电路行为,加速算法迭代。本文以STM32 HAL库为例,结合Proteus 8 Professional,详细拆解了4x4矩阵键盘的驱动逻辑、消抖处理及联合调试流

weixin_34195364的博客 386

STM32矩阵键盘驱动与Proteus仿真:从IO复用原理到HAL库实现

在嵌入式系统设计中,IO口复用是一项基础且关键的技术,它通过动态扫描检测机制,有效解决了微控制器IO资源有限与多外设需求之间的矛盾。其核心原理在于利用行列交叉的电路结构,以N+M个IO口控制N×M个按键,实现了硬件资源的极大节约。这项技术的工程价值在于将“一对一”的静态连接思维,升级为“分时复用”的动态管理思维,是嵌入式人机交互设计的基石。基于STM32 HAL库的矩阵键盘驱动开发,结合Proteus仿真验证,为嵌入式课程设计、毕业设计提供了稳定可靠的输入解决方案,典型应用于计算器、密码锁及各类菜单控制系统

weixin_30243533的博客 458

DIYables_Keypad:轻量跨平台Arduino矩阵键盘驱动库

矩阵键盘是嵌入式人机交互的基础输入设备,其核心原理基于行列扫描与软件消抖技术。通过行输出低电平、列输入上拉检测的硬件机制,配合状态机驱动的非阻塞轮询逻辑,可高效解决机械触点抖动、IO资源紧张及多平台兼容等工程痛点。该方案具备低Flash/SRAM占用、零HAL依赖、Arduino Core原生适配等技术优势,广泛适用于密码锁、HMI控制面板、LVGL输入设备及FreeRTOS多任务系统等场景。本文详解DIYables_Keypad库的硬件抽象设计、抗干扰消抖实现与跨平台移植方法。

weixin_42263617的博客 261

嵌入式通用输入处理框架:从硬件抽象到事件驱动的模块化设计

在嵌入式系统开发中,输入设备(如按键、编码器、摇杆)的处理是基础且关键的环节。其核心原理在于将物理信号的采集、消抖、状态转换等底层操作,与上层应用逻辑进行解耦。这种解耦带来的技术价值是显著的:它提升了代码的复用性、可维护性,并使得开发者能更专注于业务功能实现。通过构建一个通用的输入处理框架,可以为各类输入设备定义标准化的驱动接口,利用硬件抽象层隔离硬件差异,并通过核心引擎统一调度与管理。这种模块化设计尤其适用于需要处理多种交互方式的复杂应用场景,例如消费电子、工业控制设备等。本文以Custom GINPUT

huqiyes的专栏 381

基于STM32与Proteus的温湿度自动控制系统仿真设计全流程

嵌入式系统开发是物联网与智能控制领域的核心技术,其核心原理在于通过微控制器(MCU)采集传感器数据、执行控制逻辑并驱动外设。STM32作为一款高性价比的ARM Cortex-M系列MCU,凭借其丰富的外设和强大的生态,成为众多嵌入式项目的首选。Proteus仿真软件则提供了在虚拟环境中搭建电路、加载程序并观察系统行为的强大能力,能有效降低硬件调试初期的成本和风险,加速产品验证周期。在智慧农业、环境监控等应用场景中,温湿度自动控制系统是典型的嵌入式应用,它融合了传感器技术、人机交互和自动控制算法。本文以STM

weixin_34396103的博客 426

基于Proteus与STM32 HAL库的温湿度监控系统仿真开发实践

嵌入式系统开发中,传感器数据采集与处理是核心基础技术,其原理涉及模拟/数字信号转换、通信协议(如I2C、单总线)及微控制器外设驱动。通过仿真技术,开发者可在无实体硬件条件下,验证电路设计与程序逻辑的协同性,大幅降低学习成本与开发风险,提升调试效率。Proteus作为主流电路仿真软件,结合STM32 HAL库的硬件抽象层,能构建完整的嵌入式系统模型,适用于环境监控、智能家居等应用场景。本文以温湿度自动控制系统为例,详解如何利用仿真环境实现从传感器模拟、OLED显示到矩阵键盘输入的闭环开发,并重点阐述状态机设计

weixin_30887919的博客 607

CH32V303上LVGL鼠标控制:输入设备驱动与调试

嵌入式GUI开发中,输入设备驱动是交互体验的关键环节。LVGL作为轻量级图形库,通过抽象输入设备层统一管理触摸屏、鼠标等指针设备。其核心是read_cb回调机制,设备驱动只需周期上报坐标与按键状态,即可触发控件事件。这一设计让MCU接入鼠标变得简单,尤其适合在RISC-V内核的CH32V303平台上进行界面调试与验证。开发者可选择USB HOST直连或串口坐标转发两种硬件路径,并需要理解相对位移到绝对坐标的换算、边界裁剪及按下/释放状态翻转。掌握这些原理,能快速解决鼠标不动、点击失效、坐标偏移等典型问题,为

weixin_30236595的博客 310

STM32定时器PWM驱动电子琴:从GPIO输入到音频输出的嵌入式综合实践

在嵌入式系统开发中,GPIO输入输出、定时器和PWM(脉冲宽度调制)是基础且核心的技术模块。GPIO负责数字信号的采集与控制,是微控制器与外部世界交互的桥梁;定时器提供精确的时间基准,用于生成周期信号和计时;PWM则通过调节脉冲宽度来模拟模拟量输出,广泛应用于电机控制、LED调光和音频生成等领域。这些技术的结合,能够实现从简单开关检测到复杂信号处理的跨越,其工程价值在于将离散的数字逻辑转化为连续的物理效应。在音频应用场景中,通过将特定频率映射为PWM参数,可以驱动无源蜂鸣器或扬声器发声,从而构建简易电子琴等

weixin_34112181的博客 387

Motorola CMB1200 FPGA编程与MAPI接口实战指南

在嵌入式系统开发中,FPGA(现场可编程门阵列)作为一种可重构硬件,常与微控制器(MCU)协同工作,以实现高性能、灵活的数字逻辑处理。其核心原理是通过配置比特流定义内部逻辑单元与互连,从而将软件算法转化为硬件电路。这种软硬件协同设计的技术价值在于能显著提升特定任务的执行效率,并降低系统功耗。FPGA的典型应用场景包括通信协议处理、实时信号控制以及作为MCU的专用硬件加速器。本文聚焦于Motorola CMB1200开发平台,深入解析其专用的FPGAProg编程器软件的使用方法,包括通信协议选择、芯片选择基地

banshen0201的博客 351

STM32多音电子琴Proteus仿真:零成本学习音频处理与嵌入式开发

PWM(脉冲宽度调制)是嵌入式系统中常用的信号生成技术,通过调节脉冲的占空比和频率来控制外部设备。其原理基于微控制器的定时器模块,通过预分频器和自动重载值精确控制输出波形。在音频处理领域,PWM技术能够生成不同频率的方波信号,模拟各种音调,为电子琴、音乐播放器等应用提供基础支持。结合Proteus仿真平台,开发者可以在虚拟环境中验证电路设计和代码逻辑,大幅降低硬件成本和调试风险。STM32作为广泛应用的ARM Cortex-M系列微控制器,其丰富的定时器资源和HAL库函数为PWM音频生成提供了便捷实现路径。

weixin_34242331的博客 519

AM571x引脚功能深度解析:GPIO、PWM与PRU-ICSS实战配置指南

在嵌入式系统与工业控制领域,处理器引脚功能配置是连接硬件设计与软件驱动的核心环节,其本质是对芯片内部丰富片上资源的有效管理与复用。理解引脚复用(Mux)机制、电源域划分及电气特性,是确保系统稳定可靠的基础。从通用输入输出(GPIO)的灵活控制,到脉冲宽度调制(PWM)在电机驱动中的精确应用,再到可编程实时单元(PRU)实现硬实时通信与高速数据采集,这些技术共同构成了现代工业控制器实现复杂功能与高性能的基石。本文聚焦于德州仪器AM571x系列处理器,深入剖析其GPIO、PWM和PRU-ICSS(工业通信子系统

cuankuangzhong6373的博客 443

基于ESP32复刻诺基亚1110:经典功能机变身NES游戏掌机

嵌入式系统开发中,微控制器(MCU)是核心组件,负责执行控制逻辑与处理数据。其工作原理是通过编程控制GPIO、外设接口与片上资源,实现特定功能。在物联网与智能硬件领域,MCU的技术价值在于其低功耗、高集成度与强大的实时处理能力,能有效驱动传感器、显示屏并连接无线网络。典型的应用场景包括智能家居控制、可穿戴设备及各类DIY电子项目。本文聚焦于利用ESP32这一集成Wi-Fi/蓝牙功能的流行MCU,通过硬件改造与软件编程,将经典的诺基亚1110功能机重塑为一款可运行NES游戏、具备网络连接能力的复古掌上设备,项

weixin_33924770的博客 321

Android 按键代码分析

S5PV310的矩阵按键接口 看一下芯片上的专用接口,如下图,全用的话有点多。 关于专用接口的寄存器,这些寄存器我们后面要用得到的,按键的行、列信息会在这里面暂存的。 以S5PV310为例,驱动代码:samsung-keypad.c 软件部分: 总体流程图如下,这个是在触摸屏基础上改过来的,感觉流程都是这个样子的。中断触发,中断处理

cjwsimple 1383

LVGL+FreeRTOS嵌入式GUI项目架构拆解与模块化设计实践

嵌入式图形界面开发中,如何平衡交互流畅度与资源占用是关键挑战。将LVGL图形库与FreeRTOS实时操作系统结合,通过任务划分和事件驱动机制,可有效解决MCU上复杂界面的卡顿与管理混乱问题。模块化分层设计将核心业务、用户界面、硬件驱动和中间层解耦,依赖单向流动,显著提升代码可维护性和移植效率。这种架构尤其适合资源受限的带屏设备,如智能家居面板、工业控制终端等。本文以KZZCV20项目为例,详细拆解了LVGL与FreeRTOS的集成细节、UI事件处理、内存优化及驱动调试经验,为嵌入式GUI开发提供了一套可落地

weixin_29164843的博客 341
上一篇: libmad mp3 decode example code
下一篇: Qt5 mouseless 测试
Yantai666
博客等级 码龄15年 45粉丝 271原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值