AW9523 linux 按键驱动解析

 AW9523 linux 按键驱动解析

 硬件介绍

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

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

寄存器地址W/R默认值功能描述
00HRxxHInput_Port0P0 口输入状态
01HRxxHInput_Port1P1 口输入状态
02HW/R参考表 2Output_Port0P0 口输出状态
03HW/R参考表 2Output_Port1P1 口输出状态
04HW/R00HConfig_Port0P0 口输入或输出配置
05HW/R00HConfig_Port1P1 口输入或输出配置
06HW/R00HInt_Port0P0 口中断使能
07HW/R00HInt_Port1P1 口中断使能
11HW/R00HCTL全局控制寄存器
13HW/R0FHLED Mode SwitchP1_3~P1_0 工作模式切换
20HW00HDIM0P1_0 口 LED 电流控制
21HW00HDIM1P1_1 口 LED 电流控制
22HW00HDIM2P1_2 口 LED 电流控制
23HW00HDIM3P1_3 口 LED 电流控制
7FHW00HSoftware 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;
	}

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大牛攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值