关闭

触摸屏驱动问题解决

362人阅读 评论(0) 收藏 举报

最近在做电子书是用到触摸屏是卡住了,因为之前触摸屏驱动编写的时候就遇到问题没有解决,网上说问题在于mini2440不同于其他开发板,触摸屏使用的一线触控,而不是四线触控,相关的解决方法也是找了好久,最终在一个帖子上找到了http://blog.csdn.net/doccode/article/details/46520275 这是网址。按照里面的方法修改电路之后,终于可以和视频一样用了。


今天晚上继续写触摸屏驱动。附上代码如下:

#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>


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;//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 irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
/*如果ADCDAT0数据寄存器的15位为0表示按下,1表示抬起*/
if(s3c_ts_regs->adcdat0&(1<<15))
{
printk("pen up!\n");
enter_wait_pen_down_mode();
}
else
{
printk("pen down!\n");
enter_measure_xy_mode();//进入自动转换模式
start_adc(); //使能ADC转换
}
return IRQ_HANDLED;
}


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;
}


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));


/*ADCCON控制寄存器,ADCCON[14]=1为预分频使能,
* ADCCON[13:4]=49分频系数为49,总线时钟为PCLK=50Mhz,
*分频后的ADC转换频率为50/(49+1)=1Mhz
*ADCCON[0]ADC转换使能,以后设置
*/
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_SHARED|IRQF_SAMPLE_RANDOM,"adc",1);
enter_wait_pen_down_mode();

return 0;
}


static void s3c_ts_exit(void)
{
free_irq(IRQ_ADC,1);
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");

分析:之前在注册IRQ_TS IRQ_ADC 中断时,request_irq函数的最后一个参数都设为NULL 后来发现虽然TS中断进入,但是ADC中断没有进入,在一篇帖子上看到不能写空,会导致请求中断失败,将其设为1之后,果然能正常进入中断了。

好开心,夜里起风了,台风来临,加油!

2015.7.11 0:08

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:28936次
    • 积分:1027
    • 等级:
    • 排名:千里之外
    • 原创:77篇
    • 转载:2篇
    • 译文:0篇
    • 评论:3条
    最新评论