AW9523 linux 按键驱动解析

AW9523 linux 按键驱动解析AW9523 linux 按键驱动解析 硬件介绍 AW9523 是国产芯片 中文手册也是看着方便很多 我从 datasheet 中摘录一些编写驱动过程中重要信息贴到下面 当然 最好还是看芯片手册 项目使用 AW9523 接入 16 个独立按键 AW9523A 是一款 I2C 接口 4 路呼吸灯及 16 路扩展

大家好,我是讯享网,很高兴认识大家。

 AW9523 linux 按键驱动解析

 硬件介绍

AW9523是国产芯片,中文手册也是看着方便很多,我从datasheet中摘录一些编写驱动过程中重要信息贴到下面,当然,最好还是看芯片手册,项目使用AW9523接入16个独立按键。

AW9523A 是一款 I2C 接口、 4 路呼吸灯及 16 路扩展 GPIO 控制器,它包含 16 路双向 GPIO 端口,其中 4 路可通过指令配置LED 驱动模式。

讯享网

寄存器地址 W/R 默认值 功能 描述
00H R xxH Input_Port0 P0 口输入状态
01H R xxH Input_Port1 P1 口输入状态
02H W/R 参考表 2 Output_Port0 P0 口输出状态
03H W/R 参考表 2 Output_Port1 P1 口输出状态
04H W/R 00H Config_Port0 P0 口输入或输出配置
05H W/R 00H Config_Port1 P1 口输入或输出配置
06H W/R 00H Int_Port0 P0 口中断使能
07H W/R 00H Int_Port1 P1 口中断使能
11H W/R 00H CTL 全局控制寄存器
13H W/R 0FH LED Mode Switch P1_3~P1_0 工作模式切换
20H W 00H DIM0 P1_0 口 LED 电流控制
21H W 00H DIM1 P1_1 口 LED 电流控制
22H W 00H DIM2 P1_2 口 LED 电流控制
23H W 00H DIM3 P1_3 口 LED 电流控制
7FH W 00H Software Reset 软复位寄存器
08H~10H
12H
14H~1FH
24H~7EH
80H~FFH
- - - 保留寄存器,用户不操作

注册设备

AW9523使用i2c_driver模型,在board中对应I2C i2c_board_info中注册设备如下,这里应该注意AW9523的AD0/AD1管脚应该接地。从上图中,可以确定其I2C地址。

#if defined(CONFIG_AW9523_KPD) { I2C_BOARD_INFO("aw9523", 0xB0), }, #endif

讯享网

驱动

 probe函数

aw9523上电复位,代码如下

讯享网 // power on gpio_request(rst, "aw9523_rst"); gpio_direction_output(rst, 0); udelay(100); gpio_direction_output(rst, 1); mdelay(100); gpio_free(rst);

检测ID,代码如下

err = aw9523_read(data->client, 0x10, &val); if (!err && val == 0x23) return 0;

初始化配置,代码如下

讯享网 // port 0 input mode aw9523_write(data->client, AW9523_CONFIG_PORT_0, 0xff); // keys input // port 0 output low aw9523_write(data->client, AW9523_OUTPUT_PORT_0, 0x00); // port 0 enable int aw9523_write(data->client, AW9523_INT_PORT_0, 0x00); // enable irq // port 1 input mode aw9523_write(data->client, AW9523_CONFIG_PORT_1, 0xff); // keys input // port 1 output low aw9523_write(data->client, AW9523_OUTPUT_PORT_1, 0x00); // port 1 enable int aw9523_write(data->client, AW9523_INT_PORT_1, 0x00); // enable irq

注册输入设备

 input = input_allocate_device(); if (!input) { err = -ENOMEM; goto exit_input_dev_alloc_failed; } input_set_drvdata(input, data); for(i=0; i<8*2; i++) { input_set_capability(input, EV_KEY, data->key_matrix[i]); } err = input_register_device(input); if (err) { goto exit_input_register_device_failed; } 

创建工作队列

讯享网 INIT_WORK(&data->work, aw9523_work_func); data->work_q = create_singlethread_workqueue(dev_name(&client->dev)); if (!data->work_q) { err = -ESRCH; goto exit_create_singlethread_failed; } schedule_work(&data->work);

申请中断,aw9523中断管教是连接到我们CPU上的,所以有按键按下,会触发中断

 err = request_irq(client->irq, aw9523_irq_handler, IRQF_TRIGGER_FALLING, client->name, data); if (err < 0) { dev_err(&client->dev, "aw9523_i2c_probe: request irq failed\n"); goto exit_irq_request_failed; } 

中断服务函数

中断服务函数比较简单,只需要关闭AW9523中断,将工作加入到工作队列中,最终唤醒对应内核线程

讯享网 aw9523_irq_disable(data); if (!work_pending(&data->work)) queue_work(data->work_q, &data->work); return IRQ_HANDLED;

工作函数

工作函数读取AW9523 P0 P1口的管教状态,进行比对新旧状态比对,找到变化的管教,通过input系统上报。

 // get port0 value aw9523_read(data->client, AW9523_INPUT_PORT_0, &p0); p0 = ~p0; if(p0 != data->port0_state) { chg = p0^data->port0_state; // xor tmp = p0; for(i=0; i<8; i++) { if(chg & 0x01) { input_report_key(data->input_dev, data->key_matrix[i], tmp & 0x01); input_sync(data->input_dev); } chg >>= 1; tmp >>= 1; } data->port0_state = p0; }

 

小讯
上一篇 2025-03-12 08:15
下一篇 2025-02-11 10:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/120253.html