嵌入式linux驱动-触摸屏笔记
2019-07-12 14:44发布
生成海报
一、开发环境
1、内核:Linux 2.6.22.6;
2、JZ2440v3
3、ubuntu 9.10
二、过程
三、程序
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
static struct input_dev *myts_dev;
static struct timer_list ts_time;
struct ts_regs{
unsigned long adccon;
unsigned long adctsc;
unsigned long adcdly;
unsigned long adcdat0;
unsigned long adcdat1;
unsigned long adcupdn;
};
static volatile struct ts_regs *ts_regs;
static int enter_pen_up_mode(void)
{
ts_regs->adctsc=0x1d3;
return 0;
}
static void enter_pen_down_mode(void)
{
ts_regs->adctsc=0xd3;
}
static void enter_measure_xy_mode(void)
{
ts_regs->adctsc=(1<<3)|(1<<2)|(3<<0);
}
static void start_adc(void)
{
ts_regs->adccon |=(1<<0);
}
static int filter_ts(int x[],int y[])
{
#define ERR_LIMIT 10
int 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 int adc_irq(int irq,void *dev_id)
{
static int cnt;
static int x[4],y[4];
int adcdat0,adcdat1;
adcdat0=ts_regs->adcdat0 & 0x3ff;
adcdat1=ts_regs->adcdat1 & 0x3ff;
if(ts_regs->adcdat0 &(1<<15))
{ //已经松开
cnt=0;
input_report_abs(myts_dev, ABS_PRESSURE, 0);
input_report_key(myts_dev, BTN_TOUCH,0);
input_sync(myts_dev);
enter_pen_down_mode();
}
else
{
//未松开
x[cnt]=adcdat0;
y[cnt]=adcdat1;
++cnt;
if(cnt==4)
{ if(filter_ts( x,y))
//printk("adc_irq cnt=%d,x=%d,y=%d
",cnt,(x[0]+x[1]+x[2]+x[3])/4,(y[0]+y[1]+y[2]+y[3])/4);
input_report_abs(myts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);
input_report_abs(myts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);
input_report_abs(myts_dev, ABS_PRESSURE, 1);
input_report_key(myts_dev, BTN_TOUCH, 1);
input_sync(myts_dev);
cnt=0;
enter_pen_up_mode();
//启动定时器处理长按滑动的情况
mod_timer(&ts_time, jiffies+HZ/100);
}
else
{
enter_measure_xy_mode();
start_adc();
}
}
return IRQ_HANDLED;
}
static void ts_timer_function(unsigned long data)
{
if(ts_regs->adcdat0 &(1<<15))
{ //已经松开,进入等待按下模式
input_report_abs(myts_dev, ABS_PRESSURE, 0);
input_report_key(myts_dev, BTN_TOUCH,0);
input_sync(myts_dev);
enter_pen_down_mode();
}
else
{//否则再次启动转换测量xy坐标
enter_measure_xy_mode();
start_adc();
}
//return IRQ_HANDLED;
}
static int pen_updown_irq(int irq,void *dev_id)
{
if(ts_regs->adcdat0 &(1<<15))
{
printk("pen_up!
");
enter_pen_down_mode();
}
else
{
printk("pen_down!
");
//enter_pen_up_mode();
enter_measure_xy_mode();
start_adc();
}
return IRQ_HANDLED;
}
static int ts_init(void)
{
static struct clk *adc_clock;
//1.分配一个input_dev结构体
myts_dev=input_allocate_device();
//2设置
//2.1能产生那类事件
set_bit(EV_KEY,myts_dev->evbit);
set_bit(EV_ABS,myts_dev->evbit);
//2.2能产生这类事件里的那类事件
set_bit(BTN_TOUCH,myts_dev->keybit);
input_set_abs_params(myts_dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(myts_dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(myts_dev, ABS_PRESSURE, 0, 1, 0, 0);
//3注册
input_register_device(myts_dev);
//4硬件相关的操作
//4.1使能时钟
adc_clock = clk_get(NULL, "adc");
clk_enable(adc_clock);
//4.2设置s3c2410触摸屏寄存器
ts_regs=ioremap(0x58000000, sizeof(struct ts_regs));
ts_regs->adccon=(1<<14)|(49<<6);
request_irq(IRQ_TC, pen_updown_irq, IRQF_SAMPLE_RANDOM,"ts_action", NULL);
request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM,"ts_adc", NULL);
//优化延时
ts_regs->adcdly=0xffff;
//使用定时器 处理 长按滑动的情况
init_timer(&ts_time);
ts_time.function=ts_timer_function;
add_timer(&ts_time);
enter_pen_down_mode();
return 0;
}
static void ts_exit(void)
{
free_irq(IRQ_TC, NULL);
free_irq(IRQ_ADC, NULL);
iounmap(ts_regs);
input_unregister_device(myts_dev);
input_free_device(myts_dev);
del_timer(&ts_time);
}
module_init(ts_init);
module_exit(ts_exit);
MODULE_LICENSE("GPL");
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮