移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容)
1,主机环境:VMare下linux5.7 ,384内存。
2,编译编译环境:arm-linux-gcc v4.4.3
3,开发板:FL2440,4M nor flash,256M nand flash。
4,u-boot版本:u-boot-2011.09
5,linux 版本:linux-3.1
6,参考文章:
嵌入式linux应用开发完全手册,韦东山,编著。
LDD3,
【1】linux3.1的内核已经自s3c2410的触摸屏的驱动,而且在ADC驱动中我也有提到过触摸屏的驱动。触摸屏是作为主客户端运行在其它ADC任务之上...
s3c2410的触摸屏的驱动在drivers/input/touchscreen文件夹下面。在此不作过多的说明,请自行参看....
触摸屏转换的整个流程,以下流程为使用s3c2410.c作为触摸驱动说明
触摸屏转换的过程个人理解如下:
(1) 如果触摸屏感觉到触摸,则进入触摸中断(stylus_irq),触摸中断启动ADC转换,
(2) ADC 转换,如果小于触摸设置采样总次数的时候会一直转换数据,如果触摸设置采样总次数完毕后,启动1 个时间滴答的定时器,停止ADC,也就是说在这个时间滴答内,ADC 是停止的, 这样可以防止屏幕抖动。
(3) 数据 ADC的转换开始结束是靠s3c2410.c文件中的s3c24xx_ts_select函数和s3c24xx_ts_conversion函数来完成,在申请adc客户端的时候就建立这两个函数,在adc采样完成后进行调用。
(4) 如果1 个时间滴答到时候,触摸屏仍然处于触摸状态则上报转换数据,并重启ADC,重复(2)
(5) 如果触摸笔释放了,则上报释放事件,并将触摸屏重新设置为等待中断状态。
由于上一张完整移植完ADC,现在触摸屏驱动的移植变得简单了,只需要做三样事情,
1:设置触摸屏的ADC的采样周期和采样的次数。
2: 把触摸屏底层驱动加入到内核中
3: 写出触摸屏的测试程序。
【2】 如何设置触摸屏的ADC的采样周期和采样的次数。
在arch/arm/mach-s3c2440/mach-smdk2440.c增加红色如下内容:
static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
};
static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_ohci,
&s3c_device_lcd,
&s3c_device_rtc,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_adc,
&s3c_device_ts,
&s3c_device_adcdev,
&s3c_device_iis,
&s3c_device_dm9000,
};
static void __init smdk2440_machine_init(void)
{
s3c24xx_fb_set_platdata(&smdk2440_fb_info);
s3c_i2c0_set_platdata(NULL);
s3c24xx_ts_set_platdata(&s3c_ts_platform);
platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
smdk_machine_init();
}
【3】 把触摸屏驱动加入到内核中,如下图所示
【4】 触摸屏的测试程序
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
struct sample{
char position[15];
int x;
int y;
};
struct sample sample_array[4]=
{
{"topleft",0,0},
{"topright",0,0},
{"bottonleft",0,0},
{"bottonright",0,0},
};
/* 采样多次坐标点,最终进行平均值记录 */
void getsample(int fd,int position)
{
struct input_event ev[128];
int rb,sample_cnt,cntx=0,cnty=0;
rb=read(fd,ev,sizeof(struct input_event)*128);
if (rb < (int) sizeof(struct input_event)) {
perror("evtest: short read");
exit (1);
}
for (sample_cnt = 0;
sample_cnt< (int) (rb / sizeof(struct input_event));
sample_cnt++)
{
if (EV_ABS== ev[sample_cnt].type){
if( sample_cnt%20==0){
printf("%ld.%06ld ",
ev[sample_cnt].time.tv_sec,
ev[sample_cnt].time.tv_usec);
printf("type %d code %d value %d\n",
ev[sample_cnt].type,
ev[sample_cnt].code, ev[sample_cnt].value);
}
if(ABS_X==ev[sample_cnt].code){
sample_array[position].x+= ev[sample_cnt].value;
cntx++;
}
if(ABS_Y==ev[sample_cnt].code){
sample_array[position].y+= ev[sample_cnt].value;
cnty++;
}
}
}
sample_array[position].x/=cntx;
sample_array[position].y/=cnty;
}
int main(int argc, char **argv)
{
struct pollfd pfd;
int n,fd,i=0;
if ((fd = open("/dev/event0",O_RDONLY) )< 0) {
printf("open error! \n");
exit(1);
}
/*分别记录四次坐标点 然后显示*/
for(i=0;i<4;i++){
printf("Please touch the %s for 6 second ! \n",sample_array[i].position);
sleep(6);
printf("Time is up Please release\n");
getsample(fd,i);
sleep(1);
}
for(i=0;i<4;i++){
printf("%12s x=%4d,y=%4d\n",sample_array[i].position,
sample_array[i].x,
sample_array[i].y);
}
close(fd);
exit(0);
}
到此触摸屏的驱动完成....