导言
跟着嵌入式设备的开发和推行,接触屏作为新式输入设备现已随处可见,手机、PDA、MID以及ATM机等设备都现已用到了接触屏。而科技在不断发展,接触屏也由一开始的4线式单点电阻接触屏发展到今日的各种多点式电容接触屏。本文经过对以cypress 7958为代表的I2C总线接口电容式多点接触屏的研讨,规划了针对Linux操作体系的多点接触的屏幕驱动,以及不运转操作体系前提下的单片机对接触屏的驱动,取得了杰出的作用。
1 研讨渠道介绍
1.1 ARM11处理器S3C6410X
S3C6410X是根据ARM1176JZFS核的用于手持、移动等终端设备的通用处理器。S3C6410X是一款低功率、高性价比、高功用的用于移动电话和通用处理RSIC处理器。为2.5G和3G通讯服务供给了优化的硬件功用,选用 64/32位的内部总线架构,交融了AXI、AHB、APB总线。还有许多强壮的硬件加快器,包含运动视频处理、音频处理、2D加快、显现处理和缩放。
1.2 电容式多点接触屏
电容式接触屏在接触屏4边均镀上细长的电极,在导电体内构成一个低电压沟通电场。在接触屏幕时,因为人体电场,手指与导体层间会构成一个耦合电容,4边电极宣布的电流会流向触点,而电流强度与手指到电极的间隔成正比,坐落接触屏暗地的控制器会核算电流的份额及强弱,精确算出接触点的方位。电容接触屏的双玻璃不但能维护导体及感应器,更有效地避免外在环境要素对接触屏形成影响,就算屏幕沾有污秽、尘土或油渍,电容式接触屏仍然能精确算出接触方位。与电阻接触屏相比照,电容式接触屏便是支撑多点接触的人机交互方法,一般电阻式接触屏只能进行单一点的触控。
1.3 ARM东西链
本文针对ARM核的单片机运用了arm?none?linux?gnueabi?4.3.2穿插编译链,完结对ARM支撑的二进制文件编译,用以成功编译ARMLinux 2.6.28内核。
1.4 移植条件
关于本文所述内容,一切支撑Linux操作体系运转的处理器(包含嵌入式处理器)都能够运转,而一切支撑I2C总线协议的单片机也能够在不运用操作体系的前提下将接触屏作为一种一般输入设备进行运用。
2 研讨进程
图1显现了本文中针对嵌入式Linux渠道下的驱动软硬件结构体系。
图1 驱动软硬件结构体系
2.1 I2C设备在渠道部分声明
CYPRESS 7958多点接触屏的I2C地址为0x20,在运用前需求在渠道设备处进行I2C设备声明,这样才能够使Linux驱动找到其对应的I2C地址进行操作。首要要声明该I2C设备结构体,代码如下:
static struct i2c_board_info i2c_devs1[] __initdata={
{I2C_BOARD_INFO(“cypress?7958”, 0x20), }, /*cypress?7958 touch pannel controller*/
};
然后在staTIc void __init smdk6410_machine_init(void)函数中声明该I2C设备:
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
2.2 Cypress 7958驱动部分规划
2.2.1 注册和刊出模块
首要树立I2C驱动结构体,cypress_7958_driver,代码如下:
staTIc struct i2c_driver cypress_7958_driver={
.probe=cypress_7958_probe,
.remove=cypress_7958_remove,
.id_table=cypress_7958_id,
.driver={
.name=CYPRESS_7958_NAME,
},
};
然后树立_INIT初始化函数与_EXIT刊出设备函数:staTIc int __devinit cypress_7958_ts_init(void),staTIc void __exit cypress_7958_exit(void),经过i2c_add_driver与i2c_del_driver函数进行I2C设备的注册与刊出。
2.2.2 接触屏驱动进口函数的规划
由上节中声明的I2C结构体得知,在设备被检查到的时分进入static int synaptics_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)函数,在该函数中需求进行接触屏作业形式的初始化,对作为输入设备的接触屏驱动在Linux渠道下的设备名注册,一起初始化接触事情触发时引起的中止操作。
(1) Cypress 7958形式初始化
作为多点接触屏幕,Cypress 7958有许多相关的装备寄存器,本文中不再赘述,初始化部分仅需对屏幕是否作业在正常作业形式下进行检查,经过读取0x28地址的寄存器,假如值为0x07,则屏幕作业正常,不然回来过错值。
ret=i2c_smbus_read_byte_data(ts?》client, 0x28);
if(ret!=0x07){
printk(KERN_ERR,“Cypress Detect Errorn”);
return ret;
}
(2) 输入设备名注册
创立struct input_dev结构体,经过input_allocate_device()函数进行设备名的创立,然后经过set_bit函数进行输入设备功用声明。因为是多点接触屏,能够发生EV_SYN,EV_KEY,BTN_TOUCH,BTN_2(多点接触),EV_ABS等功用,故对之进行声明:
set_bit(EV_SYN, ts?》input_dev?》evbit);
set_bit(EV_KEY, ts?》input_dev?》evbit);
set_bit(BTN_TOUCH, ts?》input_dev?》keybit);
set_bit(BTN_2, ts?》input_dev?》keybit);
set_bit(EV_ABS, ts?》input_dev?》evbit);
然后完结对事情的详细装备:
input_set_abs_params(ts?》input_dev, ABS_X, 0, max_y, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_Y, 0, max_x, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_HAT0X, 0, max_y, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_HAT0Y, 0, max_x, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_MT_POSITION_X, 0, max_y, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_MT_POSITION_Y, 0, max_x, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(ts?》input_dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
终究经过input_register_device(ts?》input_dev)函数完结对该设备名的注册。
(3) 驱动事情发生中止函数初始化
Cypress 7958接触屏在接触事情发生时会在IRQ引脚发生一个低电平信号,将该引脚连接到GPN(15)引脚上,一起创立GPIO中止函数:
s3c_gpio_cfgpin(S3C64XX_GPN(15),S3C_GPIO_SFN(2));
client?》irq=gpio_to_irq(S3C64XX_GPN(15));
irqflags=IRQF_TRIGGER_LOW;
然后经过ret=request_irq(client?》irq, cypress_7958_irq_handler, irqflags, client?》name, ts)进行中止函数请求。创立cypress_7958_irq_handler函数:
static irqreturn_t cypress_7958_irq_handler(int irq, void *dev_id){
struct synaptics_ts_data *ts=dev_id;
//int ret=gpio_get_value(S3C64XX_GPN(15));
//printk(“%s:ret=%dn”,__func__,ret);
disable_irq_nosync(ts?》client?》irq);
queue_work(cypress_7958_wq, &ts?》work);
return IRQ_HANDLED;
}
当驱动事情被触发之后经过queue_work函数进入驱动作业区cypress_7958_wq,进行驱动层对使用层的信息上报。
2.2.3 接触屏作业区函数规划
接触屏作业区函数需求完结事情信息获取以及驱动层对使用层的信息上报功用,经过INIT_WORK(&ts?》work, cypress_7958_work_func)函数完结驱动作业区函数的初始化声明,在驱动事情中止发生之后进入作业区函数cypress_7958_work_func。
(1) 接触屏事情信息获取
Cypress 7958的事情触发信息存储在寄存器中,只需求经过 i2c_smbus_read_byte_data函数对其寄存器信息进行读取即可完结其事情信息的获取,也能够经过i2c_transfer完结对其寄存器信息的批量读取:
buf[0]=i2c_smbus_read_byte_data(ts?》client, 0x12);
buf[1]=i2c_smbus_read_byte_data(ts?》client, 0x13);
buf[2]=i2c_smbus_read_byte_data(ts?》client, 0x14);
buf[3]=i2c_smbus_read_byte_data(ts?》client, 0x15);
buf[4]=i2c_smbus_read_byte_data(ts?》client, 0x16);
buf[5]=i2c_smbus_read_byte_data(ts?》client, 0x17);
buf[6]=i2c_smbus_read_byte_data(ts?》client, 0x18);
buf[7]=i2c_smbus_read_byte_data(ts?》client, 0x19);
buf[8]=i2c_smbus_read_byte_data(ts?》client, 0x1a);
buf[9]=i2c_smbus_read_byte_data(ts?》client, 0x1b);
buf[10]=i2c_smbus_read_byte_data(ts?》client, 0x1c);
buf[11]=i2c_smbus_read_byte_data(ts?》client, 0x1d);
buf[12]=i2c_smbus_read_byte_data(ts?》client, 0x1e);
buf[13]=i2c_smbus_read_byte_data(ts?》client, 0x1f);
(2) 接触屏事情信息上报
经过对buf数组的剖析,获取当时事情详细信息,然后经过input_report系列函数进行事情信息的使用层上报:
if(fingermark==2){
input_report_key(ts?》input_dev,ABS_MT_TRACKING_ID,0);
input_report_abs(ts?》input_dev, ABS_MT_TOUCH_MAJOR, f1z);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_X, f1x);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_Y, f1y);
input_mt_sync(ts?》input_dev);
input_report_key(ts?》input_dev,ABS_MT_TRACKING_ID,1);
input_report_abs(ts?》input_dev, ABS_MT_TOUCH_MAJOR, f2z);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_X, f2x);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_Y, f2y);
input_mt_sync(ts?》input_dev)
input_sync(ts?》input_dev);
}
else if(fingermark==1){
input_report_key(ts?》input_dev,ABS_MT_TRACKING_ID,0);
input_report_abs(ts?》input_dev, ABS_MT_TOUCH_MAJOR, f1z);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_X, f1x);
input_report_abs(ts?》input_dev, ABS_MT_POSITION_Y, f1y);
input_mt_sync(ts?》input_dev);
input_sync(ts?》input_dev);
}
else{
input_report_abs(ts?》input_dev, ABS_MT_TOUCH_MAJOR, 0);
input_mt_sync(ts?》input_dev);
input_sync(ts?》input_dev);
}
2.3 Cypress 7958驱动在内核中的移植
经过改写Makefile与KCONFIG完结Cypress 7985在内核中的移植,以协助GCC东西链完结对内核的编译。
2.3.1 Kconfig的修正
在/driver/input/touchscreen/Kconfig中增加如下句子:
config TOUCHSCREEN_CYPRESS
tristate “CYPRESS 7958 touchscreens”
help
Say Y here if you have a CYPRESS 7958 touchscreen connected to your system.
If unsure, say N.
以完结将文件编译选项增加到MAKE MENUCONFIG中。因为接触屏驱动归于体系根本输入设备驱动,自身调用了I/O中止,不能完结模块编译,只能彻底编译进内核。在后续的研制中发现能够运用时钟中止将其模块化编译进内核,但因为时钟中止影响UCLINUX时刻片的运转,故弃之不必。
2.3.2 Makefile的修正
然后在/driver/input/touchscreen/Makefile中增加对应编译信息:
obj?$(CONFIG_TOUCHSCREEN_CYPRESS) +=touchscreen_cypress.o
终究在编译选项中将/MAKEFILE中的ARCH选项设置为S3C6410,在make menuconfig指令之后的选项中挑选TOUCHSREEN_CYPRESS选项并挑选编译进内核。
结语
本规划以I2C方法对多点接触屏进行驱动,经过嵌入式Linux将多点接触输入方法使用到嵌入式使用体系中,丰厚了单一的键盘输入与单点输入方法, 减小了体系尺度,提高了体系的可靠性。使得嵌入式体系的输入方法简略易行,一起也增强了嵌入式体系与人之间的通讯才能,简化了繁琐的调试。选用三星公司的S3C6410 ARM11处理器,加快了试验的操作过程。实践证明,该规划驱动多点接触屏幕的速度以及安稳性满足调试要求。该规划只需对底层驱动进行简略修正,就可直接使用于单片机以及其他悉数能够运转Linux的嵌入式体系中。