模块加载后打印出水平和垂直方向的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");
百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台