mini2440 简单touch screen驱动程序

2023-11-01 124浏览
百检网是一家专业的第三方检测平台,汇聚众多拥有权威资质的第三方检测机构为你提供一站式的检测服务,做检测就上百检网。百检网让检测从此检测,一份报告全国通用,专业值得信赖。

模块加载后打印出水平和垂直方向的ad转换结果,没有做坐标的转换,只为学习一下touch screen接口的编程方法,代码记录如下:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

static struct input_dev *ts_dev; //定时器用于处理长按和滑动

static struct ts_regs_t{

unsigned long adccon;

unsigned long adctsc;

unsigned long adcdly;

unsigned long adcdat0;

unsigned long adcdat1;

unsigned long adcupdn;

};

static volatile struct ts_regs_t *ts_regs;

static volatile unsigned long *clkcon;

static struct clk *adc_clk;

static struct timer_list ts_timer;

void enable_adc_clock(void){

(*clkcon) |= (1<<15);

}

void enter_wait4down_mode(void){

ts_regs->adctsc = 0xd3; //等待中断模式,检测触摸屏按下

}

void enter_wait4up_mode(void){

ts_regs->adctsc = 0x1d3; //等待中断模式,检测触摸屏松开

}

//进入测量xy坐标的工作模式

void enter_measure_xy_mode(void){

ts_regs->adctsc = (1<<3)|(1<<2);

}

//启动ac转换

void start_adc(void){

ts_regs->adccon |= (1<<0);

}

//adc中断处理函数

static irqreturn_t grh_handle_adc_irq(int irq, void *dev_id){

static int adc_count = 0;

static int xv=0, yv=0;

if(ts_regs->adcdat0 & (1<<15)){

enter_wait4down_mode();

adc_count = 0;

xv = yv = 0;

}

else{ //多次取值取平均值

if(adc_count == 4){

printk(KERN_EMERG"count=%d x=%d y=%dr", adc_count, xv>>2, yv>>2);

//上报事件

input_report_abs(ts_dev, ABS_X, xv>>2);

input_report_abs(ts_dev, ABS_Y, yv>>2);

input_report_abs(ts_dev, ABS_PRESSURE, 1);

input_report_key(ts_dev, BTN_TOUCH, 1);

input_sync(ts_dev);

adc_count = 0;

xv = yv = 0;

enter_wait4up_mode();

mod_timer(&ts_timer, jiffies+HZ/100); //10ms

}

else{

adc_count ++;

xv += (ts_regs->adcdat0)&0x3ff;

yv += (ts_regs->adcdat1)&0x3ff;

enter_measure_xy_mode();

start_adc();

}

}

return IRQ_HANDLED;

}

//tc中断处理函数

static irqreturn_t grh_handle_tc_irq(int irq, void *dev_id){

if(ts_regs->adcdat0 & (1<<15)){

//printk(KERN_EMERG"pen up!n");

enter_wait4down_mode();

}

else{

//printk(KERN_EMERG"pen downn");

//enter_wait4up_mode();

enter_measure_xy_mode();

start_adc();

}

return IRQ_HANDLED;

}

//定时器超时处理函数

static void grh_handle_timer_int(unsigned long num){

if(ts_regs->adcdat0 & (1<<15)){

//上报事件

input_report_abs(ts_dev, ABS_PRESSURE, 0);

input_report_key(ts_dev, BTN_TOUCH, 0);

input_sync(ts_dev);

enter_wait4down_mode();

}

else{

enter_measure_xy_mode();

start_adc();

}

}

static int ts_init(void){

ts_dev = input_allocate_device();

//设置能够产生哪些事件

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); /*设置**位移取值范围*/

input_set_abs_params(ts_dev, ABS_Y, 0, 0x3ff, 0, 0); /*设置**位移取值范围*/

input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0); /*设置压力的取值范围,只有0和1*/

/*注册*/

input_register_device(ts_dev);

//ioremap

ts_regs = ioremap(0x58000000, sizeof(struct ts_regs_t));

clkcon = ioremap(0x4C00000C, 4);

//使能时钟,使得adc可以正常工作

adc_clk = clk_get(NULL, "adc");

if (!adc_clk) {

printk(KERN_ERR "failed to get adc clock sourcen");

return -ENOENT;

}

clk_enable(adc_clk);

/*

bit[14] PRESCEN=1 使能预分频

bit[13:6] PRESCVL=49 预分频数值为49(pclk=50.625M) adcclk = 50.625M/50=1.0125MHz

bit[2] STDBM=0 不进入等待模式

bit[1] READ_START=0

bit[0] ENABLE_START=0

*/

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

ts_regs->adcdly = 0xffff; //设定延时,保证数据的准确性

//注册中断

if( request_irq(IRQ_TC, grh_handle_tc_irq, IRQF_SAMPLE_RANDOM, "irq_tc", ts_dev) ){

printk(KERN_EMERG"allocate IRQ_TC error!n");

return -EIO;

}

if( request_irq(IRQ_ADC, grh_handle_adc_irq, IRQF_SHARED|IRQF_SAMPLE_RANDOM, "irq_adc", ts_dev) ){

printk(KERN_EMERG"allocate IRQ_ADC error!n");

return -EIO;

}

init_timer(&ts_timer);

ts_timer.function = grh_handle_timer_int;

add_timer(&ts_timer);

enter_wait4down_mode();//等待中断模式,检测触摸屏按下

return 0;

}

static void ts_exit(void){

iounmap(ts_regs);

iounmap(clkcon);

free_irq(IRQ_TC, ts_dev);

free_irq(IRQ_ADC, ts_dev);

input_unregister_device(ts_dev);

input_free_device(ts_dev);

del_timer(&ts_timer);

}

module_init(ts_init);

module_exit(ts_exit);

MODULE_AUTHOR("GRH");

MODULE_VERSION("1.0");

MODULE_DESCRIPTION("TOUCH SCREEN DRIVER");

MODULE_LICENSE("GPL");


百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台