linux c下触摸屏程序,linux下的触摸屏驱动开发

现在主要谈谈编写s3c2410的触摸屏驱动的收获。模仿已有的驱动自己也写了一个驱动,实现同样的功能。同时为了完成这个驱动,把LDD2 这本书相关部分好好的读了一遍,获益匪浅。

先看看为了完成一个驱动,需要作的事吧。

1.  看datasheet,说白了芯片user manual,对于触摸屏,那些寄存器是主要的关注点,如ADCCON,ADCTSC…..,这些寄存器均会在驱动中使用,驱动也是全凭这些寄存器才完成与硬件的通信。这步很关键的说,虽然只用了了几笔!

2.  接下来应该先熟悉一下驱动中都需要定义些什么接口,如read,write,open,release,这些是基本的。见多了就不怪了,其实就是那些为上层(用户层)预留了访问内核数据的接口,比如此驱动,我在用户层调用用户层的read函数读取数据时,实际上就是在调用内核层(驱动属于内核层)的read来完成读操作。

3.  中断,中断,上课时看似没用的东西,现在用到了吧。啥叫中断,在此不表。怎么实现中断?还记得中断服务程序吗,就是它了。在程序的初始化函数(init)中,先使用ret=request_IRQ(IRQ_ADC_DONE,adc_isr_handler,SA_INTERRUPT,DEVICE_NAME,NULL);申请一个ADC中断,然后调用adc_isr_handler这个中断服务程序,这个程序完成了触摸屏控制器的模数转换,取得寄存器中的x,y值。不过千万别忘了在模块卸载(exit)的时候将中断释放掉,否则的话,很快中断申请线的资源就被占尽了。

4.  调试程序,呵呵,print啊,不过这里是在编驱动,千万别用printf啊,为啥?丢不起这个人啊!内核编程怎能用C函数库的函数?应该用printk!使用打印信息的方法方便实用,再加上一些宏定义开启关闭调试信息的功能,perfect!还有其他的调试方法,不过看过书了不知所云,有待钻研。

5.  还用高级的字符驱动需要的阻塞型I/O,就是等待队列,休眠进程,唤醒进程。。。(偶还没太明白,先写这么几句!)

6.  看似简单的驱动阿,学问咋那么多呢。要真正完成触摸屏的驱动还需要时间流着部分知识,咋地也要让咱的屏屏能进行个识别输入的字母吧。现在我还在调他,本打算调通之后再来完成此篇文章,看来是奢望了。继续调~~

下面我的驱动和 测试 程序就要粉墨登场了,鉴于驱动只完成到可以挂载到内核之上,并不能实现最终的功能,在此就只展出部分,等到全部完成时,就是它与大家见面之曰。

程序片断1:触摸屏驱动

触摸屏的设备数据结构:

typedef struct{

unsigned int penStatus;

TS_RET buf[MAX_TS_BUF];

unsigned int head,tail;

wait_queue_head_t wq;

sPINLOCk_t lock;

}TS_DEV;

下面这两个函数是双胞胎阿,一读一写,文武双全。。。

static int read_xy(TS_RET * ts_ret)

{

spin_lock_irq(&(tsdev.lock));

ts_ret->x = tsdev.buf[tsdev.tail].x;

ts_ret->y = tsdev.buf[tsdev.tail].y;

ts_ret->pressure = tsdev.buf[tsdev.tail].pressure;

tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF);

spin_unlock_irq(&(tsdev.lock));

return sizeof(TS_RET);

}

static void ts_write_buf(void)

{

if(tsdev.penStatus==PEN_DOWN)

{

tsdev.buf[tsdev.head].x = x;

tsdev.buf[tsdev.head].y = y;

tsdev.buf[tsdev.head].pressure = PEN_DOWN;

}else{

tsdev.buf[tsdev.head].x = 0;

tsdev.buf[tsdev.head].y = 0;

tsdev.buf[tsdev.head].pressure = PEN_UP;

}

}

下面就是所谓的GNU C对标准C的一种扩展,叫做标记方法的初始化,这是真的,谁在windows下见过这样的写法。

statIC struct file_operations s3c2410_ts_fops={

owner:           THIS_MODULE,

open:             s3c2410_ts_open,

read:              s3c2410_ts_read,

release:   s3c2410_ts_release,

};

下面就是所谓的显式的初始化和清除函数,天啊,这个名字是翻书找的。看看里面的东西是不是和我的第一篇心得说的一样??不一样就见鬼了。

static devfs_handle_t devfs_ts_dir,devfs_tsraw;  //public paramter

static int __init s3c2410_ts_init(void)

{

int ret;

/*************************/

ret=register_chrdev(ts_major,DEVICE_NAME,&s3c2410_ts_fops);

if(ret<0){

printk(KERN_WARNING "scull: CAN''''t get major %d\n",ts_major);

return ret;

}

if(ts_major == 0 )

ts_major=ret;

set_gpio_CTRl(GPIO_YPON);

set_gpio_ctrl(GPIO_YMON);

set_gpio_ctrl(GPIO_XPON);

set_gpio_ctrl(GPIO_XMON);//这篇文章第一条谈到的,就是看UM(user manual)得到的

/**************************/

#ifdef CONFIG_DEVFS_FS

devfs_ts_dir = devfs_mk_dir(NULL,"touchpanel",NULL);

devfs_tsraw = devfs_register(devfs_ts_dir,"indev", DEVFS_FL_DEFAULT, ts_major, 1, S_IFCHR | S_IRUSR | S_IWUSR, &s3c2410_ts_fops,NULL);

printk(DEVICE_NAME "initialized!\n");

printk( DEVICE_NAME " module init ok!\n");

#endif

/***************************/

//中断申请在什么时候?    A:   就在init函数中

ret=request_IRQ(IRQ_ADC_DONE,adc_isr_handler,SA_INTERRUPT,DEVICE_NAME,NULL);

if(ret){

printk(KERN_INFO "adc: can''''t get assigned irq %d\n!",IRQ_ADC_DONE);    //62

return ret;

}

ret = request_irq(IRQ_TC,tc_isr_handler,SA_INTERRUPT,DEVICE_NAME,NULL);

if(ret){

printk(KERN_INFO "tc: can''''t get assigned irq %d\n!",IRQ_TC);

return ret;

}

}

static int __exit s3c2410_ts_exit(void)

{

#ifdef CONFIG_DEVFS_FS

devfs_unregister(devfs_tsraw);

devfs_unregister(devfs_ts_dir);

//上面这两个顺序能颠倒一下吗,试一试吧

#endif

unregister_chrdev(ts_major,DEVICE_NAME);

//注销中断

free_IRQ(IRQ_TC,NULL);

free_irq(IRQ_ADC_DONE,NULL);

}

程序2 :触摸屏驱动 测试 程序

#include

#include

#include

#define DEVICENAME "/dev/touchpanel/indev"

typedef struct ts_event {

unsigned short pressure;

unsigned short x;

unsigned short y;

unsigned short pad;

}ts_event;

void main(void)

{

int ts_fd,ret;

int x_raw,y_raw;

ts_event *ts_evt;

ts_fd = open(DEVICENAME,0);

if(!ts_fd)

{

perror("ts_open :");

exit(1);

}

ts_evt=malLOC(sizeof(ts_event));

MEMSet(ts_evt, 0, sizeof(struct ts_event));

while(1)

{

ret = read(ts_fd, ts_evt, sizeof(*ts_evt));

if(ret>0){

printf("x: %d\n", ts_evt->x);

printf("y: %d\n", ts_evt->y);

printf("pressure: %d\n", ts_evt->pressure);

}

else {

perror("read the raw data :");

exit(1);

}

}

close(ts_fd);

free(ts_evt);

}

你可能感兴趣的:(linux,c下触摸屏程序)