基于I2C的嵌入式触摸屏驱动设计Word文件下载.docx
《基于I2C的嵌入式触摸屏驱动设计Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于I2C的嵌入式触摸屏驱动设计Word文件下载.docx(12页珍藏版)》请在冰豆网上搜索。
input_mt_sync(input);
}
//一帧数据发送完成,发送一个同步信号
input_sync(input);
Linux多点触摸接口
39
输入子系统----硬件设备驱动
按键、触摸屏、键盘、鼠标等输入都可以利用input接口函数来实现设备驱动,驱动层负责和底层硬件打交道,向系统报告按键、触摸屏、键盘、鼠标等输入事件,驱动报告的事件经过InputCore和Eventhandler最终到达用户空间。
通过input子系统,具体的输入设备驱动只需要完成如下工作:
1.在模块加载函数中注册输入设备,注册输入设备的函数为
intinput_register_device(structinput_dev*dev);
2.在模块加载函数中告知input子系统它可以报告的事件。
设备驱动通过set_bit()告诉input子系统它支持哪些事件:
set_bit(EV_KEY,button_dev.evbit);
3.在键被按下/抬起、触摸屏被触摸/抬起/移动、鼠标被移动/单击/抬起时通过input_report_xxx()报告发生的事件及对应的键值/坐标等状态。
主要的事件类型:
function:
voidinput_report_key(structinput_dev*dev,unsignedintcode,intvalue);
voidinput_report_rel(structinput_dev*dev,unsignedintcode,intvalue);
voidinput_report_abs(structinput_dev*dev,unsignedintcode,intvalue);
input_sync()用于事件同步,它告知事件的接收者驱动已经发出了一个完整的报告。
比如:
在触摸屏设备驱动中,一次坐标及按下状态的整个报告过程如下:
input_report_abs(input_dev,ABS_X,x);
//X坐标
input_report_abs(input_dev,ABS_Y,y);
//Y坐标
input_report_abs(input_dev,ABS_PRESSURE,pres);
//压力
input_sync(input_dev);
//同步
4.在模块卸载函数中注销输入设备:
voidinput_unregister_device(structinput_dev*dev);
一个设备可以支持一个或多个事件类型。
每个事件类型下面还需要设置具体的触发事件,比如EV_KEY事件,支持哪些按键等。
多点触摸接口
译自:
linux-2.6.31.14\Documentation\input\multi-touch-protocol.txt
简介
为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据。
这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息。
使用说明
单点触摸信息是以ABS承载并按一定顺序发送,如BTN_TOUCH、ABS_X、ABS_Y、SYNC。
而多点触摸信息则是以ABS_MT承载并按一定顺序发送,如ABS_MT_POSITION_X、ABS_MT_POSITION_Y,然后通过调用input_mt_sync()产生一个SYN_MT_REPORTevent来标记一个点的结束,告诉接收方接收当前手指的信息并准备接收其它手指的触控信息。
最后调用input_sync()函数上报触摸信息开始动作并告诉接收方开始接收下一系列多点触摸信息。
协议定义了一系列ABS_MT事件,这些事件被分为几大类,充许只应用其中的一部份,多点触摸最小的事件集中应包括ABS_MT_TOUCH_MAJOR、ABS_MT_POSITION_X和ABS_MT_POSITION_Y,以此来实现多点触摸。
如果设备支持ABS_MT_WIDTH_MAJOR这个事件,那么此事件可以提供手指触摸接触面积大小。
触摸方向等信息可以由ABS_MT_TOUCH_MINOR,ABS_MT_WIDTH_MINORandABS_MT_ORIENTATION提供。
ABS_MT_TOOL_TYPE提供触摸设备的类别,如手或是笔或是其它。
最后有些设备可能会支持ABS_MT_TRACKING_ID,用来支持硬件跟踪多点信息,即该点属于哪一条线等。
下面是两点触摸支持的最小事件集序列:
ABS_MT_TOUCH_MAJOR
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
SYN_MT_REPORT
//上报第一个点
ABS_MT_TOUCH_MAJOR
//上报第二个点
SYN_REPORT
//开始动作
Event原语
“接触”一词用来描述一个物体直接碰到另一个物体的表面。
ABS_MT_TOUCH_MAJOR描述了主接触面的长轴,它和X,Y同一个单位,如果一个面的分辨率为X*Y,则ABS_MT_TOUCH_MAJOR的最大值为sqrt(X^2+Y^2)
ABS_MT_TOUCH_MINOR描述了接触面的短轴,如果接触面是圆形,它可以不用。
ABS_MT_WIDTH_MAJOR描述了接触工具的长轴
ABS_MT_WIDTH_MINOR描述了接触工具的短轴
ABS_MT_TOUCH_MAJOR:
=max(X,Y)
ABS_MT_TOUCH_MINOR:
=min(X,Y)
ABS_MT_ORIENTATION:
=bool(X>
Y)
以上四个参数可以用来生成额外的触摸信息,如ABS_MT_TOUCH_MAJOR/ABS_MT_WIDTH_MAJOR的比率可以用来描述压力。
ABS_MT_ORIENTATION
ABS_MT_POSITION_X接触面的中心点X坐标
ABS_MT_POSITION_Y接触面的中心点Y坐标
ABS_MT_TOOL_TYPE描述接触工具类型,很多内核驱动无法区分此参数如手指及笔,如果是这样,该参数可以不用,协议目前支持MT_TOOL_FINGER和MT_TOOL_PEN两种类型。
ABS_MT_BLOB_ID形状集ID,集合几个点以描述一个形状,很多驱动没有形状属性,此参数可以不用。
ABS_MT_TRACKING_ID描述了从接触开始到释放的整个过程的集合,如果设备不支持,此参数可是不用。
触摸轨迹
仅有少数设备可以明触的标识真实的trackingID,多数情况下trackingID只能来标识一次触摸动作的过程。
手势
多点触摸指定的应用是创建手势动作,TOUCH和WIDTH参数经常用来区别手指的压力和手指间的距离,另外MINOR类的参数可以用来区别设备的接触面的大小(点接触还是面接触),ORIENTATION可以产生旋转事件。
参考代码:
(1)注册多点触摸设备
ts->
input_dev=input_allocate_device();
if(ts->
input_dev==NULL){
ret=-ENOMEM;
printk(KERN_ERR"
Failedtoallocateinputdevice\n"
);
gotoerr_input_dev_alloc_failed;
}
ts->
input_dev->
name="
MT-touchscreen"
;
set_bit(EV_SYN,ts->
evbit);
set_bit(EV_KEY,ts->
set_bit(EV_ABS,ts->
set_bit(BTN_TOUCH,ts->
keybit);
max_x=0x77b;
max_y=0xb38;
input_set_abs_params(ts->
input_dev,ABS_X,0,max_x,0,0);
input_dev,ABS_Y,0,max_y,0,0);
input_dev,ABS_PRESSURE,0,255,0,0);
input_dev,ABS_TOOL_WIDTH,0,15,0,0);
input_dev,ABS_MT_POSITION_X,0,max_x,0,0);
input_dev,ABS_MT_POSITION_Y,0,max_y,0,0);
input_dev,ABS_MT_TOUCH_MAJOR,0,255,0,0);
input_dev,ABS_MT_WIDTH_MAJOR,0,15,0,0);
ret=input_register_device(ts->
input_dev);
if(ret){
Unabletoregister%sinputdevice\n"
ts->
name);
gotoerr_input_register_device_failed;
(2)报点
for(i=0;
i<
finger;
input_report_abs(ts->
input_dev,ABS_MT_TOUCH_MAJOR,1);
input_dev,ABS_MT_POSITION_X,ts->
x[i]);
input_dev,ABS_MT_POSITION_Y,ts->
y[i]);
input_mt_sync(ts->
upsend=0;
if(finger){
input_sync(ts->
}else{
if(!
upsend){
input_dev,ABS_MT_TOUCH_MAJOR,0);
upsend=1;
基于I2C的嵌入式多点触摸屏幕驱动设计
(1)更新于2011-03-2116:
09:
33文章出处:
OFweek
关键字:
I2C嵌入式多点触摸屏幕驱动
引言
随着嵌入式设备的开发和推广,触摸屏作为新式输入设备已经随处可见,手机、PDA、MID以及ATM机等设备都已经用到了触摸屏。
而科技在不断发展,触摸屏也由一开始的4线式单点电阻触摸屏发展到今天的各种多点式电容触摸屏。
本文通过对以cypress7958为代表的I2C总线接口电容式多点触摸屏的研究,设计了针对Linux操作系统的多点触摸的屏幕驱动,以及不运行操作系统前提下的单片机对触摸屏的驱动,取得了良好的效果。
1研究平台介绍
1.1ARM11处理器S3C6410X
S3C6410X是基于ARM1176JZFS核的用于手持、移动等终端设备的通用处理器。
S3C6410X是一款低功率、高性价比、高性能的用于移动电话和通用处理RSIC处理器。
为2.5G和3G通信服务提供了优化的硬件性能,采用64/32位的内部总线架构,融合了AXI、AHB、APB总线。
还有很多强大的硬件加速器,包括运动视频处理、音频处理、2D加速、显示处理和缩放。
1.2电容式多点触摸屏
电容式触摸屏在触摸屏4边均镀上狭长的电极,在导电体内形成一个低电压交流电场。
在触摸屏幕时,由于人体电场,手指与导体层间会形成一个耦合电容,4边电极发出的电流会流向触点,而电流强度与手指到电极的距离成正比,位于触摸屏幕后的控制器会计算电流的比例及强弱,准确算出触摸点的位置。
电容触摸屏的双玻璃不但能保护导体及感应器,更有效地防止外在环境因素对触摸屏造成影响,就算屏幕沾有污秽、尘埃或油渍,电容式触摸屏依然能准确算出触摸位置。
与电阻触摸屏相对比,电容式触摸屏就是支持多点触摸的人机交互方式,普通电阻式触摸屏只能进行单一点的触控。
1.3ARM工具链
本文针对ARM核的单片机使用了armnonelinuxgnueabi4.3.2交叉编译链,实现对ARM支持的二进制文件编译,用以成功编译ARMLinux2.6.28内核。
1.4移植条件
对于本文所述内容,所有支持Linux操作系统运行的处理器(包括嵌入式处理器)都可以运行,而所有支持I2C总线协议的单片机也可以在不使用操作系统的前提下将触摸屏作为一种普通输入设备进行使用。
2研究过程
图1显示了本文中针对嵌入式Linux平台下的驱动软硬件结构体系。
图1驱动软硬件结构体系
2.1I2C设备在平台部分声明
CYPRESS7958多点触摸屏的I2C地址为0x20,在使用前需要在平台设备处进行I2C设备声明,这样才可以使Linux驱动找到其对应的I2C地址进行操作。
首先要声明该I2C设备结构体,代码如下:
staticstructi2c_board_infoi2c_devs1[]__initdata={
{I2C_BOARD_INFO(“cypress7958”,0x20),},/*cypress7958touchpannelcontroller*/
};
然后在staticvoid__initsmdk6410_machine_init(void)函数中声明该I2C设备:
i2c_register_board_info(1,i2c_devs1,ARRAY_SIZE(i2c_devs1));
2.2Cypress7958驱动部分设计
2.2.1注册和注销模块
首先建立I2C驱动结构体,cypress_7958_driver,代码如下:
staticstructi2c_drivercypress_7958_driver={
.probe=cypress_7958_probe,
.remove=cypress_7958_remove,
.id_table=cypress_7958_id,
.driver={
.name=CYPRESS_7958_NAME,
},
然后建立_INIT初始化函数与_EXIT注销设备函数:
staticint__devinitcypress_7958_ts_init(void),staticvoid__exitcypress_7958_exit(void),通过i2c_add_driver与i2c_del_driver函数进行I2C设备的注册与注销。
2.2.2触摸屏驱动入口函数的设计
由上节中声明的I2C结构体得知,在设备被检查到的时候进入staticintsynaptics_ts_probe(structi2c_client*client,conststructi2c_device_id*id)函数,在该函数中需要进行触摸屏工作模式的初始化,对作为输入设备的触摸屏驱动在Linux平台下的设备名注册,同时初始化触摸事件触发时引起的中断操作。
(1)Cypress7958模式初始化
作为多点触摸屏幕,Cypress7958有很多相关的配置寄存器,本文中不再赘述,初始化部分仅需对屏幕是否工作在正常工作模式下进行检查,通过读取0x28地址的寄存器,如果值为0x07,则屏幕工作正常,否则返回错误值。
ret=i2c_smbus_read_byte_data(ts》client,0x28);
if(ret!
=0x07){
printk(KERN_ERR,“CypressDetectErrorn”);
returnret;
}
(2)输入设备名注册
创建structinput_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)驱动事件产生中断函数初始化
Cypress7958触摸屏在触摸事件产生时会在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函数:
staticirqreturn_tcypress_7958_irq_handler(intirq,void*dev_id){
structsynaptics_ts_data*ts=dev_id;
//intret=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);
returnIRQ_HANDLED;
当驱动事件被触发之后通过queue_work函数进入驱动工作区cypress_7958_wq,进行驱动层对应用层的信息上报。
2.2.3
触摸屏工作区函数设计
触摸屏工