




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本文格式为Word版,下载可任意编辑——linux串口触摸屏设计总结Linuxserialtouch设计总结
概述:最近在做嵌入式linux下串口触摸屏设计,遇到一些问题,经过查找资料和请教同事,
终究把问题解决了,事后有把linux相关的内核代码细心看了一遍,为了有点成果,特别写了个总结。如有任何问题请联系yxj_5421@163.com,转载请标明出处。
系统资源:Linux:2.6.36UI:QT+TSLIB
硬件资源不关心
设计方法:有两种实现途径。
1、
是将要使用的串口单独拿出来,作为一个platform总线设备实现,在嵌入式平台mach文件里面,加上串口中断号和寄放器首地址,然后将这个串口注册成
一个platform总线设备。在驱动probe函数里面需要得到这个串口中断号以及寄放器映射地址,通过寄放器映射地址设置串口波特率,数据位,中止位等,通过中断号注册中断等,然后调用input_register_device注册一个input设备。在中断里面得到外面触摸屏的数据,然后根据inputtouch协议上报触摸数据。这种方法实现简单明白,不需要和linux的tty,serio等打交道。但是要求知道串口硬件spec,譬如寄放器等,而且这个串口就只能给触摸屏使用了,不能作为tty使用。由于是嵌入式开发,因此很简单知道硬件spec,而且嵌入式平台一旦确定,那么这个串口确定就是给触摸屏使用了。因此在嵌入式平台上,推荐使用这个方法。
是将串口作为一个serio总线设备,利用linux内核提供serio总线驱动,通过设置对应的串口,调用serport提供的函数将串口当做serio总线设备,在驱动里面需要依照serio总线设备驱动的框架来实现,这方面的例子linux里面有好多,譬如touchright.c,在模块init函数里面调用serio_register_driver注册serio总线设备驱动,假使serio总线上对应的serio设备存在,就调用connect函数,在这个函数里面调用input_register_device注册一个input设备。具体驱动不再分
析了,很简单,相信各位都能看的懂。
至此,两种方法都实现了串口触摸屏的驱动,讲到这里是不是就完了,非也,本文的重点还在后面,请看下面分析:
第一种方法只要驱动模块被加载,就会在/dev/input下面创立一个eventx节点,tslib就能访问这个节点,获得触摸坐标,然后送给qt。其次种方法驱动模块加载后,并没有创立eventx节点,也就是说connect函数没有被调用,依照linux驱动模型来看,就是serio总线上还没有对应的serio设备,因此驱动加载时没有对应的设备,就不会调用connect函数,这时的串口还是作为一个linuxtty设备存在。
我遇到的问题就是serio驱动加载了,但是没有创立eventx节点,查找资料也只有一个说是要把tty设置成N_MOUSE,然后读,说的不明白,也不知道怎么实现,经过自己摸索,终究把问题解决了。
2、
Linux启动后串口形式:
Linux一启动是将串口作为tty来设置的。看下的调用:
start_kernelinit/main.c大家对这个函数不陌生吧,linux启动过程中重要的一个函数
console_init();drivers/tty/tty_io.c
tty_register_ldisc(N_TTY,drivers/tty/tty_idisc.c给串口注册一个tty链路层处理函数ops。
现在我们需要写一个上层的应用程序,对这个tty进行设置,需要设置波特率,数据位,中止位等,最重要的是要将这个tty设备设置成一个serio总线设备,然后把它注册在serio总线上,请看下面的代码:
fd=open(device,O_RDWR|O_NOCTTY|O_NONBLOCK);if(fdflags,type->speed);ldisc=N_MOUSE;
if(ioctl(fd,TIOCSETD,}
fprintf(stderr,\device,strerror(errno));return1;
里面的device就是对应要使用的那个串口,linux里面一般是/dev/ttyS0,首先是开启串口open(device,O_RDWR|O_NOCTTY|O_NONBLOCK)接着设置波特率等setline(fd,CS8,B9600);
staticvoidsetline(intfd,intflags,intspeed){}
structtermiost;tcgetattr(fd,
t.c_cflag=flags|CREAD|HUPCL|CLOCAL;t.c_iflag=IGNBRK|IGNPAR;t.c_oflag=0;t.c_lflag=0;
t.c_cc[VMIN]=1;t.c_cc[VTIME]=0;cfsetispeed(cfsetospeed(tcsetattr(fd,TCSANOW,
devt=type->type|(idtype|(idops->open(tty)ld->ops就是serport注册的serport_ldisc
staticintserport_ldisc_open(structtty_struct*tty)drivers/input/serio/serport.c
这个函数里面会创立一个serport结构体,并初始化
调用
longtty_ioctl(structfile*file,unsignedintcmd,unsignedlongarg)drivers/tty/tty_io.cretval=ld->ops->ioctl(tty,file,cmd,arg);staticintserport_ldisc_ioctl(structtty_struct*tty,structfile*file,unsignedintcmd,unsignedlongarg)设置
serport->to=typeserport->id.id=(typeserport->id.extra=(type
这里三个值一定要和serio总线驱动里面对应的值一致,serio总线就是靠它们来给设备和驱动建立联系的。
调用
read(fd,NULL,0);
跟踪代码到内核层tty_read:
staticssize_ttty_read(structfile*file,char__user*buf,size_tcount,
loff_t*ppos)
(ld->ops->read)(tty,file,buf,count)这个ld就是tty当前的链路层结构,上面我们已
经设置N_MOUSE为tty的当前链路层,因此ld->ops就是serport注册的serport_ldiscstaticssize_tserport_ldisc_read(structtty_struct*tty,structfile*file,unsignedchar__user*buf,size_tnr)serio_register_port(serport->serio);serio_init_port(serio);
serio_queue_event(serio,owner,SERIO_REGISTER_PORT);
注册一个serio总线设备,关于serio总线,网络有好多资料介绍,这里就不说了。至此,我们的串口设备已经当做serio总线设备注册在serio总线上了,假使相应的驱动也在serio总线上,就会进行设备和驱动的匹配,然后调用驱动里面的connect函数,在这个函数里面就会创立input节点。我们的驱动和设备已经运行起来了,现在看看数据是如何传递的
先看具体串口中断函数:我们以altera_uart.c为例:altera_uart_interrupt
altera_uart_rx_chars(pp)
tty_flip_buffer_push(port->state->port.tty);
flush_to_ldisc(
disc->ops->receive_buf(tty,char_buf,flag_buf,count);disc->ops就是serport注册的serport_ldiscstaticvoidserport_ldisc_receive(structtty_struct*tty,constunsignedchar
*cp,char*fp,intcount)
serio_interrupt(serport->serio,cp[i],ch_flags);ret=serio->drv->interrupt(serio,data,dfl);
drv->interrupt就是我们驱动函数提供一个函数,它每次接受一个字符,在这个函数里面,接受到足够信息后,就能得到触摸屏坐标信息,然后通过input_report上报上去。看看数据处理流程图:
总结:要想让基于serio总线驱动的串口触摸屏能正常工作,在linux内核需要加载驱动模块,serport模块。还需要一个上层应用程序,这个程序需要进行以下工作
1、开启你要使用的串口,譬如
open(device,O_RDWR|O_NOCTTY|O_NONBLOCK)device为/dev/ttyS0
2、设置串口波特率等,和你的串口触摸屏一致3、给串口增加一个N_MOUSE链路层4、设置你的串口触摸屏type,id,extra5、读串口read(fd,NULL,0);
总结:要想让基于serio总线驱动的串口触摸屏能正常工作,在linux内核需要加
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 幼儿园员工聘用合同
- 流通经销合同8篇
- 《无机化学》课程标准
- 出口赔偿合同范本
- 个人英语学习计划
- 三年级语文下册工作总结
- 南车 合同范本
- 双方合作生产经营合同范例
- 厨房工作人员劳务合同范本
- 会计记账报税合同范本
- 2024年保安员证资格考试题库及答案
- 机器狗:技术成熟性能优越场景刚需放量在即2025
- 《生态安全》课件
- 教科版六年级下册科学全册单元教材分析
- 2025年春新人教版一年级下册数学全册教学课件
- 2024年第四季度 国家电网工程设备材料信息参考价
- 环保行业污水处理厂智能化管理方案
- GB/T 17145-2024废矿物油回收与再生利用导则
- 普通高中生物学课程标准-(2024修订版)
- GB/T 45006-2024风电叶片用纤维增强复合材料拉挤板材
- 2025国家公务员政治理论应知应会知识考试题库(含答案)
评论
0/150
提交评论