目录

一、触摸屏驱动简介

二、编写触摸屏驱动程序

2.1 硬件相关的代码

2.2 按下,产生中断

2.3 中断处理中启动ADC

2.4 转换结束产生ADC中断

2.5 优化误差

2.6 启动定时器(完整代码)

三、使用tslib与LCD配合


一、触摸屏驱动简介

  • 触摸屏驱动是以用输入子系统写的:输入子系统
  • 所有触摸屏驱动程序都是以下框架:

1.分配一个input_dev结构体;2.设置input_dev结构体;3.注册input_dev结构体;4.硬件相关的操作

static int s3c_ts_init(void)
{/* 1. 分配一个input_dev结构体 */s3c_ts_dev = input_allocate_device();/* 2. 设置 *//* 2.1 能产生哪类事件 */set_bit(EV_KEY, s3c_ts_dev->evbit);set_bit(EV_ABS, s3c_ts_dev->evbit); //绝对位移类事件(触摸屏)/* 2.2 能产生这类事件里的哪些事件 */set_bit(BTN_TOUCH, s3c_ts_dev->keybit); //按键类里面的触摸事件input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);// 例如绘图板,压力有很多级别,这里设0和1,要么按下,要么松开/* 3. 注册 */input_register_device(s3c_ts_dev);/* 4. 硬件相关的操作 */return 0;
}
  • 在S3C2440芯片手册上触摸屏为10位ADC,min和max则为0和0x3FF

static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)

  • 触摸屏实际是欧姆定律的运用,并且触摸屏为两层很薄的模盖在屏幕上,同时触摸屏和LCD一样大小,触摸屏和LCD是两样东西

  • 怎么测量X坐标,首先让XP接3.3V,XM接地,YM、YP不接,再测出YP的电压,上层相当于电阻,电流从XP流向XM,X坐标是电压值,与LCD分辨率是两码事,Y坐标同理,YP接3.3V,YM接地,XP、XM不接,测出XP的电压,下层相当于电阻,电流从YP流向YM

  • 触摸屏使用过程:

1.按下,产生触摸中断;2.在中断处理程序里,启动ADC转换X,Y坐标;3.ADC结束,产生ADC中断;4.在ADC中断处理函数里,用input_event函数上报,启动定时器(解决滑动、长按触发的问题);5.定时器时间到,再次启动ADC

二、编写触摸屏驱动程序

2.1 硬件相关的代码

  • 为了省电内核会先把不需要的模块关闭,因此需要我们先来使能ADC,即CLKCON寄存器

  • 利用clk_enable函数使能,此函数最终会调用到相应的clock.c中 s3c2410_clkcon_enable函数从而来使能clkcon寄存器
int s3c2410_clkcon_enable(struct clk *clk, int enable)
{unsigned int clocks = clk->ctrlbit;unsigned long clkcon;clkcon = __raw_readl(S3C2410_CLKCON);if (enable)clkcon |= clocks;elseclkcon &= ~clocks;/* ensure none of the special function bits set */clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);__raw_writel(clkcon, S3C2410_CLKCON);return 0;
}
...
static struct clk init_clocks_disable[] = {{.name      = "nand",.id     = -1,.parent       = &clk_h,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_NAND,}, {.name        = "sdi",.id      = -1,.parent       = &clk_p,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_SDI,}, {.name     = "adc",.id      = -1,.parent       = &clk_p,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_ADC,}, {.name     = "i2c",.id      = -1,.parent       = &clk_p,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_IIC,}, {.name     = "iis",.id      = -1,.parent       = &clk_p,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_IIS,}, {.name     = "spi",.id      = -1,.parent       = &clk_p,.enable       = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_SPI,}
};

struct clk* clk;
clk = clk_get(NULL, "adc");
clk_enable(clk);

  • 查看芯片手册将相关寄存器定义为结构体,统一映射设置

struct s3c_ts_regs {
    unsigned long adccon;
    unsigned long adctsc;
    unsigned long adcdly;
    unsigned long adcdat0;
    unsigned long adcdat1;
    unsigned long adcupdn;
};

static volatile struct s3c_ts_regs *s3c_ts_regs;

s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));

  • 设置ADCCON

bit[15]只读位不关心,bit[14]设置为1使能预分频,系统时钟在uboot设置好了,dmesg查看内核输出信息,PCLK为100M

将ADC设置为1M,则 bit[13:6]设置为49,对于bit[0]为AD转换,先设置为0

s3c_ts_regs->adccon = (1<<14)|(49<<6);

如下图,对于bit[5:3]为多路选择,如果为一般的ADC转换就可以设置这一位

2.2 按下,产生中断

  • 注册中断,以pen_down_up_irq为处理函数

request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);

  • 在手册中ADC有四种模式,其中第四种为等待触摸中断模式,需要设置ADCTSC为0xd3

static void enter_wait_pen_down_mode(void)
{
    s3c_ts_regs->adctsc = 0xd3;
}

  • 分析ADCTSC寄存器

对于bit[8]如果是等待松开中断则设置为1,因此可以写出等待松开中断模式

static void enter_wait_pen_up_mode(void)
{
    s3c_ts_regs->adctsc = 0x1d3;
}

0xd3为11010011,对于等待中断模式,YM和上拉电阻要闭合,即bit[3]为0、bit[7]为1,对于bit[2]没有开启ADC为0,其他一 一对应

  • 当发生触摸中断,根据ADCDAT0中bit[15]来判断是否按下或者松开,其中bit[9:0]后面可以开启ADC后得到转换值

  • 设置pen_down_up_irq处理函数,当发生时进入等待松开模式,松开后进入等待按下模式
static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{if (s3c_ts_regs->adcdat0 & (1<<15)){printk("pen up\n");enter_wait_pen_down_mode();}else{printk("pen down\n");enter_wait_pen_up_mode();}return IRQ_HANDLED;
}
  • 代码,后面编写出口函数
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/plat-s3c24xx/ts.h>
#include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h>struct s3c_ts_regs {unsigned long adccon;unsigned long adctsc;unsigned long adcdly;unsigned long adcdat0;unsigned long adcdat1;unsigned long adcupdn;
};static struct input_dev *s3c_ts_dev;
static volatile struct s3c_ts_regs *s3c_ts_regs;static void enter_wait_pen_down_mode(void)
{s3c_ts_regs->adctsc = 0xd3;
}static void enter_wait_pen_up_mode(void)
{s3c_ts_regs->adctsc = 0x1d3;
}static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{if (s3c_ts_regs->adcdat0 & (1<<15)){printk("pen up\n");enter_wait_pen_down_mode();}else{printk("pen down\n");enter_wait_pen_up_mode();}return IRQ_HANDLED;
}static int s3c_ts_init(void)
{struct clk* clk;s3c_ts_dev = input_allocate_device();set_bit(EV_KEY, s3c_ts_dev->evbit);set_bit(EV_ABS, s3c_ts_dev->evbit);set_bit(BTN_TOUCH, s3c_ts_dev->keybit);input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);input_register_device(s3c_ts_dev);clk = clk_get(NULL, "adc");clk_enable(clk);s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));s3c_ts_regs->adccon = (1<<14)|(49<<6);request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);enter_wait_pen_down_mode();return 0;
}static void s3c_ts_exit(void)
{free_irq(IRQ_TC, NULL);iounmap(s3c_ts_regs);input_unregister_device(s3c_ts_dev);input_free_device(s3c_ts_dev);
}module_init(s3c_ts_init);
module_exit(s3c_ts_exit);
MODULE_LICENSE("GPL");
  • 测试:将内核源码中去掉原来的触摸屏驱动程序,make menuconfig->Device Drivers->Input device support->Generic input layer->Touchscreens-> <>   S3C2410/S3C2440 touchscreens

Makefile:编译驱动程序

KERN_DIR = /work/system/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    += s3c_ts.o

  • 在S3C2440上加载新内核,编译驱动后加载驱动,并在触摸屏上按下松开,结果如下

# insmod s3c_ts.ko
input: Unspecified device as /class/input/input0
pen down
pen up
# pen down
pen up
pen down
pen up

2.3 中断处理中启动ADC

  • 对于ADC四种模式中有自动转换模式,因此我们写出自动转换模式函数,并启动ADC,在ADCTSC寄存器(图在上面)中有bit[2]要设置为1,同时在读出XY坐标时需要将上拉开关断开,因此bit[3]设置为1

自动转换模式:

static void enter_measure_xy_mode(void)
{
    s3c_ts_regs->adctsc = (1<<3)|(1<<2);
}

  • 修改触摸中断函数
static void enter_measure_xy_mode(void)
{s3c_ts_regs->adctsc = (1<<3)|(1<<2);
}static void start_adc(void)
{s3c_ts_regs->adccon |= (1<<0);
}static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{if (s3c_ts_regs->adcdat0 & (1<<15)){printk("pen up\n");enter_wait_pen_down_mode();}else{//printk("pen down\n");//enter_wait_pen_up_mode();enter_measure_xy_mode();start_adc();  //启动ADC}return IRQ_HANDLED;
}

2.4 转换结束产生ADC中断

  • 注册ADC中断,以adc_irq为处理函数

request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);

  • 在处理函数中打印出转换值,并等待下次触摸按下中断,转换值为寄存器ADCDAT0和ADCDAT1中
static irqreturn_t adc_irq(int irq, void *dev_id)
{static int cnt = 0;printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, s3c_ts_regs->adcdat0 & 0x3ff, s3c_ts_regs->adcdat1 & 0x3ff);enter_wait_pen_up_mode();return IRQ_HANDLED;
}
  • 编译后测试,在测试过程中存在这误差

2.5 优化误差

  • 优化措施1:按下的时候,若立刻产生中断,此时电压可能不稳定,这时测量电压会不准确,因此等电压稳定后再产生触摸按下松开中断,在手册中有个ADCDLY寄存器来设置延时时间,这里设置为最大值

s3c_ts_regs->adcdly = 0xffff;

  • 优化措施2:ADC转换需要一定时间,当按下触摸中断时,ADC没有转换完成就松开,就丢弃此次结果,在ADC处理函数中(此时没有松开),若判断为松开则进入等待按下触摸中断
static irqreturn_t adc_irq(int irq, void *dev_id)
{static int cnt = 0;int adcdat0, adcdat1;adcdat0 = s3c_ts_regs->adcdat0;adcdat1 = s3c_ts_regs->adcdat1;if (s3c_ts_regs->adcdat0 & (1<<15)){/* 已经松开 */enter_wait_pen_down_mode();}else{printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);enter_wait_pen_up_mode();}return IRQ_HANDLED;
}
  • 优化措施3:多次测量求平均值,当测量结果数量不满足4时,则再次进入自动测量模式,启动ADC
static irqreturn_t adc_irq(int irq, void *dev_id)
{static int cnt = 0;static int x[4], y[4];int adcdat0, adcdat1;adcdat0 = s3c_ts_regs->adcdat0;adcdat1 = s3c_ts_regs->adcdat1;if (s3c_ts_regs->adcdat0 & (1<<15)){/* 已经松开 */cnt = 0;enter_wait_pen_down_mode();}else{x[cnt] = adcdat0 & 0x3ff;y[cnt] = adcdat1 & 0x3ff;++cnt;if (cnt == 4){printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);cnt = 0;enter_wait_pen_up_mode();}else{enter_measure_xy_mode();start_adc();}     }return IRQ_HANDLED;
}
  • 优化措施4:软件过滤(比较粗糙),将四个值以误差值10作比较,第一个数和第二数的平均值与第三个数相比,若误差大于10,这不要此次数据,第四个数以此类推
static int s3c_filter_ts(int x[], int y[])
{
#define ERR_LIMIT 10int avr_x, avr_y;int det_x, det_y;avr_x = (x[0] + x[1])/2;avr_y = (y[0] + y[1])/2;det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))return 0;avr_x = (x[1] + x[2])/2;avr_y = (y[1] + y[2])/2;det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))return 0;return 1;
}static irqreturn_t adc_irq(int irq, void *dev_id)
{static int cnt = 0;static int x[4], y[4];int adcdat0, adcdat1;adcdat0 = s3c_ts_regs->adcdat0;adcdat1 = s3c_ts_regs->adcdat1;if (s3c_ts_regs->adcdat0 & (1<<15)){/* 已经松开 */cnt = 0;enter_wait_pen_down_mode();}else{x[cnt] = adcdat0 & 0x3ff;y[cnt] = adcdat1 & 0x3ff;++cnt;if (cnt == 4){if (s3c_filter_ts(x, y)){            printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);}cnt = 0;enter_wait_pen_up_mode();}else{enter_measure_xy_mode();start_adc();}       }   return IRQ_HANDLED;
}

2.6 启动定时器(完整代码)

  • 处理长按和滑动的问题,在按下过程中,启动定时器进入自动测量模式再次启动ADC测量
static void s3c_ts_timer_function(unsigned long data)
{if (s3c_ts_regs->adcdat0 & (1<<15)){/* 已经松开 */enter_wait_pen_down_mode();}else{/* 测量X/Y坐标 */enter_measure_xy_mode();start_adc();}
}static irqreturn_t adc_irq(int irq, void *dev_id)
{
...if (cnt == 4){if (s3c_filter_ts(x, y)){            printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);}cnt = 0;enter_wait_pen_up_mode();/* 启动定时器处理长按/滑动的情况 */mod_timer(&ts_timer, jiffies + HZ/100);}else{enter_measure_xy_mode();start_adc();}      }return IRQ_HANDLED;
}static int s3c_ts_init(void)
{
...init_timer(&ts_timer);ts_timer.function = s3c_ts_timer_function;add_timer(&ts_timer);
}
  • 把printk改为上报事件,input_report_abs和input_report_key函数来代替,实质也是与event.c配合,配合input_sync函数上报完毕,完整代码如下
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>#include <asm/plat-s3c24xx/ts.h>#include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h>struct s3c_ts_regs {unsigned long adccon;unsigned long adctsc;unsigned long adcdly;unsigned long adcdat0;unsigned long adcdat1;unsigned long adcupdn;
};static struct input_dev *s3c_ts_dev;
static volatile struct s3c_ts_regs *s3c_ts_regs;static struct timer_list ts_timer;static void enter_wait_pen_down_mode(void)
{s3c_ts_regs->adctsc = 0xd3;
}static void enter_wait_pen_up_mode(void)
{s3c_ts_regs->adctsc = 0x1d3;
}static void enter_measure_xy_mode(void)
{s3c_ts_regs->adctsc = (1<<3)|(1<<2);
}static void start_adc(void)
{s3c_ts_regs->adccon |= (1<<0);
}static int s3c_filter_ts(int x[], int y[])
{
#define ERR_LIMIT 10int avr_x, avr_y;int det_x, det_y;avr_x = (x[0] + x[1])/2;avr_y = (y[0] + y[1])/2;det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))return 0;avr_x = (x[1] + x[2])/2;avr_y = (y[1] + y[2])/2;det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))return 0;return 1;
}static void s3c_ts_timer_function(unsigned long data)
{if (s3c_ts_regs->adcdat0 & (1<<15)){/* 已经松开 */input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);input_report_key(s3c_ts_dev, BTN_TOUCH, 0);input_sync(s3c_ts_dev);enter_wait_pen_down_mode();}else{/* 测量X/Y坐标 */enter_measure_xy_mode();start_adc();}
}static irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{if (s3c_ts_regs->adcdat0 & (1<<15)){input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);input_report_key(s3c_ts_dev, BTN_TOUCH, 0);input_sync(s3c_ts_dev);enter_wait_pen_down_mode();}else{enter_measure_xy_mode();start_adc();}return IRQ_HANDLED;
}static irqreturn_t adc_irq(int irq, void *dev_id)
{static int cnt = 0;static int x[4], y[4];int adcdat0, adcdat1;/* 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果 */adcdat0 = s3c_ts_regs->adcdat0;adcdat1 = s3c_ts_regs->adcdat1;if (s3c_ts_regs->adcdat0 & (1<<15)){cnt = 0;input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);input_report_key(s3c_ts_dev, BTN_TOUCH, 0);input_sync(s3c_ts_dev);enter_wait_pen_down_mode();}else{// printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);/* 优化措施3: 多次测量求平均值 */x[cnt] = adcdat0 & 0x3ff;y[cnt] = adcdat1 & 0x3ff;++cnt;if (cnt == 4){/* 优化措施4: 软件过滤 */if (s3c_filter_ts(x, y)){           //printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1); //压力值input_report_key(s3c_ts_dev, BTN_TOUCH, 1);//按键类事件 1表示按下input_sync(s3c_ts_dev);}cnt = 0;enter_wait_pen_up_mode();/* 启动定时器处理长按/滑动的情况 */mod_timer(&ts_timer, jiffies + HZ/100);}else{enter_measure_xy_mode();start_adc();}     }return IRQ_HANDLED;
}static int s3c_ts_init(void)
{struct clk* clk;/* 1. 分配一个input_dev结构体 */s3c_ts_dev = input_allocate_device();/* 2. 设置 *//* 2.1 能产生哪类事件 */set_bit(EV_KEY, s3c_ts_dev->evbit);set_bit(EV_ABS, s3c_ts_dev->evbit);/* 2.2 能产生这类事件里的哪些事件 */set_bit(BTN_TOUCH, s3c_ts_dev->keybit);input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);/* 3. 注册 */input_register_device(s3c_ts_dev);/* 4. 硬件相关的操作 *//* 4.1 使能时钟(CLKCON[15]) */clk = clk_get(NULL, "adc");clk_enable(clk);/* 4.2 设置S3C2440的ADC/TS寄存器 */s3c_ts_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));/* bit[14]  : 1-A/D converter prescaler enable* bit[13:6]: A/D converter prescaler value,*            49, ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz* bit[0]: A/D conversion starts by enable. 先设为0*/s3c_ts_regs->adccon = (1<<14)|(49<<6);request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);/* 优化措施1: * 设置ADCDLY为最大值, 这使得电压稳定后再发出IRQ_TC中断*/s3c_ts_regs->adcdly = 0xffff;/* 优化措施5: 使用定时器处理长按,滑动的情况* */init_timer(&ts_timer);ts_timer.function = s3c_ts_timer_function;add_timer(&ts_timer);enter_wait_pen_down_mode();return 0;
}static void s3c_ts_exit(void)
{free_irq(IRQ_TC, NULL);free_irq(IRQ_ADC, NULL);iounmap(s3c_ts_regs);input_unregister_device(s3c_ts_dev);input_free_device(s3c_ts_dev);del_timer(&ts_timer);
}module_init(s3c_ts_init);
module_exit(s3c_ts_exit);
MODULE_LICENSE("GPL");
  • 编译测试:查看hexdump /dev/event0,按下后如下,其中0003为事件EV_ABS,0000为事件中ABS_X,后面则为测量值

秒            微秒      type code    value
0000000 29a4 0000 8625 0008 0003 0000 0172 0000
0000010 29a4 0000 8631 0008 0003 0001 027c 0000
0000020 29a4 0000 8634 0008 0003 0018 0001 0000
0000030 29a4 0000 8638 0008 0001 014a 0001 0000
0000040 29a4 0000 863c 0008 0000 0000 0000 0000
0000050 29a4 0000 c85e 0008 0003 0000 0171 0000
0000060 29a4 0000 c874 0008 0003 0001 027d 0000
0000070 29a4 0000 c87b 0008 0000 0000 0000 0000
0000080 29a4 0000 ed37 0008 0003 0018 0000 0000
0000090 29a4 0000 ed48 0008 0001 014a 0000 0000
00000a0 29a4 0000 ed4a 0008 0000 0000 0000 0000

三、使用tslib与LCD配合

  • 在ubuntu上编译tslib库过程

sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool

tar xzf tslib-1.4.tar.gz
cd tslib
./autogen.sh

mkdir tmp
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
make
make install

  • 将tmp目录拷到S3C2440上,这里使用nfs传输,其中加入d参数使链接也保持为链接

cp tmp/ /work/nfs_root/first_fs/ts_dir -rfd

  • 在开发板上安装

cd tmp        
cp * -rf /

  • 使用过程

先安装s3c_ts.ko, lcd.ko驱动,lcd.ko驱动参考:S3C2440之LCD驱动

1.修改 /etc/ts.conf第1行(去掉#号和第一个空格)

# module_raw input
改为:
module_raw input

2.修改环境变量

export TSLIB_TSDEVICE=/dev/event0 
export TSLIB_CALIBFILE=/etc/pointercal    //校验文件
export TSLIB_CONFFILE=/etc/ts.conf  //配置文件
export TSLIB_PLUGINDIR=/lib/ts  //插件
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0

3. 执行ts_calibrate,执行完后,lcd出现校准十字架,校准完毕会生成校验文件,还有其他测试程序,ts_print打印lcd坐标值(480*272),ts_print_raw打印原始值(ADC值)

S3C2440之触摸屏驱动相关推荐

  1. linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例

    1.1    本节阅读前提 本节的说明建立在前两节的基础之上,需要先阅读如下两篇章: linux input输入子系统分析<一>:初识input输入子系统 linux input输入子系统 ...

  2. linux 触摸屏驱动分析

    mini2440驱动分析系列之 ---------------------------------------Mini2440触摸屏程序分析 By JeefJiang July,8th,2009 这是 ...

  3. linux 触摸屏驱动介绍

    本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次如下图所示, 其中事件处理层的函数都是通过input_register_handler()函数注册 ...

  4. Linux3.4.2的触摸屏驱动分析与编写

    开发环境: 开发板:JZ2440V3 CPU:samsunS3C2440 内核:Linux3.4.2 编译工具:arm-linux-gcc 4.3.2 LCD:4.3存液晶屏AT043TN24 参考文 ...

  5. 嵌入式Linux ———触摸屏驱动开发

    声明:本文章是看完韦东山老师的触摸屏驱动视频所写的关于触摸屏的驱动,因此如果有相关内容与其他网友相同,敬请原谅.同时我还是想说本文只是总结自己的学习所得,同时也将自己所学到的知识写下来,所以如果这篇文 ...

  6. 触摸屏驱动三部曲之硬件原理

    转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/24794665 零.触摸屏驱动三部曲概述 触摸屏已经在我们的生活中无处不在,所以 ...

  7. WINCE6.0+S3C6410的触摸屏驱动

    ********************************LoongEmbedded******************************** 作者:LoongEmbedded(kandi ...

  8. linux 触摸屏驱动编写

    早在诺基亚手机还比较流行的时候,那时候触摸屏用的还不多.但是随着触摸屏手机.即智能手机的流行,触摸屏基本成了手机的标配.所以,今天可以看看触摸屏驱动在linux上是如何进行的. 1.驱动目录 driv ...

  9. linux内核关闭触摸屏校准,linux内核usb触摸屏驱动bug调试- selected device is not a touchscreen I understand...

    近期给客户调试一块数控板,今天客户带过来一个屏,并且有一个usb的触摸屏芯片接在屏上.屏很快就弄好正常显示. 触摸屏在内核下找到usb 触摸屏驱动,内核启动后这个usb转的触摸屏也正常找到,注册为ev ...

最新文章

  1. Nginx学习4:负载均衡实例
  2. FileStream 的FileShare一点小认识
  3. string字符串详解
  4. FAST300M无线宽带路由器FW300R(从)桥接TPLINK路由器(主)
  5. vue从其它页面返回_vue页面按返回键等跳转重定向判断
  6. Linux线程(五)
  7. 音视频技术开发周刊 | 215
  8. 实验7-3-4 字符串替换 (15分)
  9. 怎样在 Ubuntu 13.04 Raring Ringtail , 12.10, 12.04 中安装和设置 Samba 实现网上邻居共享...
  10. 刷新include引进的页面
  11. Mac下CUDA开启及Tensorflow-gpu 1.4 安装
  12. vue学习笔记-节接口调用-async和await
  13. linux怎么查看设备序列号,linux 使用dmidecode查看设备序列号
  14. 游戏设计梦工厂学习笔记(一)
  15. 计算机用通讯电压多少,通信局(站)用交流电源的质量指标要求
  16. 计算机网络丢包排查,ping命令图文教程,电脑测试网络丢包延迟,检测网络故障通不通...
  17. 吴洪声十问戴跃: 域名圈巴菲特是如何炼成的?
  18. switch的优缺点
  19. P2657 [SCOI2009] windy 数(数位DP)
  20. ps4饥荒联机版服务器未响应,《饥荒联机版》国服的正确打开方式,你get到吗?...

热门文章

  1. 服务器physx性能测试,PhysX有多吃性能?
  2. JAVA自动化(三)--ExcelProperties
  3. 高并发场景下backlog详解
  4. iview template模式_iview render的使用
  5. flutter项目架构
  6. html 修改内容弹窗,javascript如何设置弹窗?
  7. C#实战积累:常用的lambda表达式整理
  8. elementui 表格单行删除
  9. 围棋棋盘怎么编程python_python3 turtle 画围棋棋盘
  10. 可导一定连续,连续不一定可导