本文共 7315 字,大约阅读时间需要 24 分钟。
在触摸屏实验里遇到的问题:
1. 在加载模块时,就会出现采样数据
# insmod ts.ko input: s3c2440_touch_screen as /devices/virtual/input/input0 init touch screen input dev pen down adc_irq cnt = 0, x = 10, y = 543 adc_irq cnt = 1, x = 507, y = 420 adc_irq cnt = 2, x = 514, y = 420 adc_irq cnt = 3, x = 516, y = 420 pen up
不知何解??
2.在触摸触摸屏弹出的数据更是奇怪,有些相差较大,下面是一次完整的触摸过程闯过来的数据,而且根本没有进入设置的过滤函数??
# pen down adc_irq cnt = 0, x = 124, y = 471 adc_irq cnt = 1, x = 186, y = 392 adc_irq cnt = 2, x = 224, y = 370 adc_irq cnt = 3, x = 258, y = 368 pen up pen down adc_irq cnt = 0, x = 70, y = 500 adc_irq cnt = 1, x = 371, y = 407 adc_irq cnt = 2, x = 121, y = 398 adc_irq cnt = 3, x = 185, y = 381 adc_irq cnt = 0, x = 154, y = 449 adc_irq cnt = 1, x = 279, y = 386 adc_irq cnt = 2, x = 156, y = 386 adc_irq cnt = 3, x = 135, y = 394 pen up pen down adc_irq cnt = 0, x = 95, y = 484 adc_irq cnt = 1, x = 335, y = 400
3.在input下的
# cat devices I: Bus=0013 Vendor=dead Product=beef Version=0100 N: Name="s3c2440_touch_screen" P: Phys= S: Sysfs=/devices/virtual/input/input0 U: Uniq= H: Handlers=mouse0 event0 B: EV=b B: KEY=400 0 0 0 0 0 0 0 0 0 0 B: ABS=1000003
发现handler同时有mouse0 和event0 会不会因为mouse的原因,待解??
# cat handlers N: Number=0 Name=kbd N: Number=1 Name=mousedev Minor=32 N: Number=2 Name=evdev Minor=64
这是调试过程遇到的??
经过我再次制作的内核,再次调试,不会出现上次问题,以下为第一次调试的代码
#include#include #include #include #include #include #include #include #include #include #include #include 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_base;static struct input_dev* ts_dev;static struct timer_list ts_timer;//up 等待触摸屏被松开void ts_up_mode(){ ts_base->adctsc = 0x1d3; // 1 1101 0011}//down 等待触摸屏被按下void ts_down_mode(){ ts_base->adctsc = 0xd3; // 1101 0011}//启动adc转换void start_adc(){ ts_base->adccon |= (1<<0);}//设备adc自动转换xy坐标,禁止上拉电阻void measure_xy_mode(){ //measure xy; ts_base->adctsc |= (1<<3) | (1<<2);}static int ts_filter(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 void ts_timer_functions(unsigned long data){ if(ts_base->adcdat0 & (1<<15)) { printk("timer_func: pen up\n"); //ts_down_mode(); input_report_abs(ts_dev, ABS_PRESSURE, 0); input_report_abs(ts_dev, BTN_TOUCH, 0); input_sync(ts_dev); ts_down_mode(); } else { printk("timer_func: pen down\n"); //ts_up_mode(); measure_xy_mode(); start_adc(); }}//pen已触摸(包括pen点下和松开都会发生中断), 进入此函数static irqreturn_t ts_irq(int irq, void *dev_id){ //up进入等待模式,down就进行转换数据 //if(ts_base->adctsc & (1<<8)) if(ts_base->adcdat0 & (1<<15)) { printk("ts_irq: pen up\n"); ts_down_mode(); } else { printk("ts_irq: pen down\n"); //ts_up_mode(); measure_xy_mode(); start_adc(); } //ts_timer.data = (unsigned long)dev_id; //mod_timer(&ts_timer, jiffies + HZ/100); return IRQ_RETVAL(IRQ_HANDLED);}//转换完成后进入此中断,等待pen的松开static irqreturn_t adc_irq(int irq, void *dev_id){ static int cnt = 0; int adcdata0, adcdata1; static int adcx[4], adcy[4]; //如果adc完成时,发现触摸笔松开,则丢弃 adcdata0 = ts_base->adcdat0; adcdata1 = ts_base->adcdat1; //adcx[cnt] = ts_base->adcdat0 & 0x3ff; //adcy[cnt] = ts_base->adcdat1 & 0x3ff; if( adcdata0 & (1<<15) ) { printk("adc_irq: no wait cnt=4 end \n"); ts_down_mode(); } else { if( cnt == 4 ) { if(ts_filter(adcx, adcy)) { int x, y; x = (adcx[0]+adcx[1]+adcx[2]+adcx[3])/4; y = (adcy[0]+adcy[1]+adcy[2]+adcy[3])/4; //report_abs_evevnt(); printk("touch point: x = %d, y = %d\n\n", x, y); input_report_abs(ts_dev, ABS_X, x); input_report_abs(ts_dev, ABS_Y, y); input_report_abs(ts_dev, ABS_PRESSURE, 1); input_report_key(ts_dev, BTN_TOUCH, 1); input_sync(ts_dev); } cnt = 0; ts_up_mode(); //S3C2410_CS4 //timer mod_timer(&ts_timer, jiffies + HZ); } else { adcx[cnt] = adcdata0 & 0x3ff; adcy[cnt] = adcdata1 & 0x3ff; printk("adc_irq cnt = %d, x = %d, y = %d\n", cnt, adcx[cnt], adcy[cnt]); cnt++; measure_xy_mode(); start_adc(); } //ts_up_mode(); } return IRQ_RETVAL(IRQ_HANDLED);}static int input_init(void){ struct clk* clk; //1 分配一个input_dev ts_dev = input_allocate_device(); //2 设置 //设置产生什么事件 //设置这类事件的那种 ts_dev->name = "s3c2440_touch_screen"; ts_dev->id.bustype = BUS_RS232; ts_dev->id.vendor = 0xDEAD; ts_dev->id.product = 0xBEEF; ts_dev->id.version = 0x0100; //ts_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_SYN); //ts_dev->keybit[0] = BIT_MASK(EV_KEY); set_bit(EV_KEY, ts_dev->evbit); set_bit(EV_ABS, ts_dev->evbit); set_bit(BTN_TOUCH, ts_dev->keybit); input_set_abs_params(ts_dev, ABS_X, 0, 0x3ff, 0, 0);//adcdat0 xpdata有说明 input_set_abs_params(ts_dev, ABS_Y, 0, 0x3ff, 0, 0);//dactat1 ypdata 有说明 input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0);//按压 和弹起 //3 注册 input_register_device(ts_dev); //4 硬件相关的操作 //set clk clk = clk_get(NULL, "adc"); clk_enable(clk); //set register ts_base = ioremap(0x58000000, sizeof(struct ts_regs) ); ts_base->adccon = (1<<14) | (0x31<<6); //50/(49+1)=1mhz //设置定时器,使用定时器处理长按,滑动的情况 init_timer(&ts_timer); ts_timer.function = ts_timer_functions; add_timer(&ts_timer); //设置延时,电压稳定后再发出中断 ts_base->adcdly = 0xffff; //设置中断包括ts和adc request_irq(IRQ_TC, ts_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL); request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL); ts_down_mode(); printk ("init touch screen input dev\n"); return 0;}static void input_exit(void){ //释放irq //删除定时器 //注销设备,释放所占用空间 free_irq(IRQ_TC, NULL); free_irq(IRQ_ADC, NULL);//del iomap iounmap(ts_base); del_timer(&ts_timer); input_unregister_device(ts_dev); input_free_device(ts_dev);}module_init(input_init);module_exit(input_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LCL");
第一次现在测试也是正确的,这因为默认情况下,cnt = 4 就进入ts_up_mode();
第二次我修改了adc_ts里面的代码,按照韦东山代码,优化了在adc转换完成后,但是cnt<4的情况下,就报告退出,放弃当前的测试
if( adcdata0 & (1<<15) ) //触摸松开 { cnt = 0; printk("touch screen up\n"); input_report_abs(ts_dev, ABS_PRESSURE, 0); input_report_key(ts_dev, BTN_TOUCH, 0); input_sync(ts_dev); ts_down_mode(); } else //触摸还在按下状态 { adcx[cnt] = adcdata0 & 0x3ff; adcy[cnt] = adcdata1 & 0x3ff; printk("adc_irq cnt = %d, x = %d, y = %d\n", cnt, adcx[cnt], adcy[cnt]); cnt++; if( cnt == 4 ) { if(ts_filter(adcx, adcy)) { int x, y; x = (adcx[0] + adcx[1] + adcx[2] + adcx[3])/4; y = (adcy[0] + adcy[1] + adcy[2] + adcy[3])/4; //report evevnt; printk("touch point: x = %d, y = %d\n\n", x, y); input_report_abs(ts_dev, ABS_X, x); input_report_abs(ts_dev, ABS_Y, y); input_report_abs(ts_dev, ABS_PRESSURE, 1); input_report_key(ts_dev, BTN_TOUCH, 1); input_sync(ts_dev); } cnt = 0; ts_up_mode(); //S3C2410_CS4 //timer mod_timer(&ts_timer, jiffies + HZ/100); } else { measure_xy_mode(); start_adc(); }
在第一次加载时默认就会启动定时器,但是就启动这一次,只有以后cnt=4才会调用
# insmod ts.ko input: s3c2440_touch_screen as /devices/virtual/input/input3 init touch screen input dev timer_func: pen up
转载地址:http://tbtqb.baihongyu.com/