mini2440触摸屏驱动----非input子系统实现方法

发布者:Chanhero最新更新时间:2022-11-12 来源: csdn关键字:mini2440 手机看文章 扫描二维码
随时随地手机看文章

触摸屏的驱动程序在不是使用input子系统的实现过程中,其实和普通的字符设备驱动没有太大的差别,只要按照触摸屏那几个步骤正常进行就可以。


①s3c2410_ts_init函数,这是整个程序的入口处。实现了各类初始化的作用。


/*设备初始化函数*/

static int __init s3c2410_ts_init(void)

{

int ret;

 

tsEvent = tsEvent_dummy;

 

/* 

注册字符设备

第一个参数为0表示自动分配

*/

ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);

//普通的注册失败判断。

if (ret < 0) {

  printk(DEVICE_NAME " can't get major numbern");

  return ret;

}

//tsMajor是一个全局变量,这里被赋设备注册的返回值

tsMajor = ret;

 

/* set gpio to XP, YM, YP and  YM */

//操作相应的GPIO寄存器,这些函数是内核留下来的接口。

set_gpio_ctrl(GPIO_YPON); 

set_gpio_ctrl(GPIO_YMON);

set_gpio_ctrl(GPIO_XPON);

set_gpio_ctrl(GPIO_XMON);


/*

注册中断

分别注册ADC和TC中断。

DEVICE_NAME在开始处有宏定义。

*/

ret = request_irq(IRQ_ADC_DONE, s3c2410_isr_adc, SA_INTERRUPT, 

  DEVICE_NAME, s3c2410_isr_adc);

if (ret) goto adc_failed;

ret = request_irq(IRQ_TC, s3c2410_isr_tc, SA_INTERRUPT, 

  DEVICE_NAME, s3c2410_isr_tc);

if (ret) goto tc_failed;

 

/*

等待触摸屏被按下的中断

这个函数的实现是使用宏来实现的。这就是一个等待函数,让我想起了当年的祥哥。

*/

wait_down_int();

 

//创建设备文件。

#ifdef CONFIG_DEVFS_FS

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

devfs_tsraw = devfs_register(devfs_ts_dir, "0raw", DEVFS_FL_DEFAULT,

tsMajor, TSRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR,

&s3c2410_fops, NULL);

#endif

 

ADCDLY = 0xFFFF;

printk(DEVICE_NAME " initializedn");

 

return 0;

//两个中断注册失败的跳转点。

 tc_failed:

free_irq(IRQ_ADC_DONE, s3c2410_isr_adc);

 adc_failed:

return ret;

}


在这个函数中出现了以前没有的条件编译,所以自己注意一下,不过这个条件编译的主要作用就是创建设备文件。同时还有两个中断注册失败的goto。为了自己看以后的程序不糊涂,先记下这句话://tsMajor是一个全局变量,这里被赋设备注册的返回值tsMajor = ret;


②s3c2410_ts_exit,这个函数是整个程序的退出函数,主要实现了设备的注销和中断的释放。


static void __exit s3c2410_ts_exit(void)

{

#ifdef CONFIG_DEVFS_FS

devfs_unregister(devfs_tsraw);

devfs_unregister(devfs_ts_dir);

#endif

unregister_chrdev(tsMajor, DEVICE_NAME);

 

free_irq(IRQ_ADC_DONE, s3c2410_isr_adc);

free_irq(IRQ_TC, s3c2410_isr_tc);

}


③一般分析字符设备驱动程序的时候都是先看init函数,然后再去找file_operation。但是触摸屏的驱动程序的实现肯定有会有中断,所以我们先来看一下中断函数。


先看第一个中断函数(在init函数中已经注册完毕)


/* 当按键按下时首先产生的中断 */

static void s3c2410_isr_tc(int irq, void *dev_id, struct pt_regs *reg)

{

//利用自旋锁给中断上锁。

spin_lock_irq(&(tsdev.lock));

//这里PEN_UP被宏定义为0,penStatus是一个结构体成员。

if (tsdev.penStatus == PEN_UP) /*如果是按下中断*/

{

  start_ts_adc(); /* 开始AD转化 */

} else 

{

  tsdev.penStatus = PEN_UP; /* 如果是弹起中断*/

  DPRINTK("PEN UP: x: %08d, y: %08dn", x, y);

  wait_down_int(); /*等待按下中断*/

  tsEvent(); /* 调用后续处理函数 */

}

spin_unlock_irq(&(tsdev.lock));

}


再说这个中断函数之前,首先要说一下触摸品主要的工作流程:


触摸屏的工作流程

①选择X/Y的获取模式。

②设置触摸屏等待中断的状态。

③如果中断发生启动相应的数模转换。

④当数模转换之后,可以获取X/Y坐标值,返回到等待中断的状态(②之后③之前)。


同时还要说一下触摸屏的两个中断:


TC中断:手按下拿起的时候

ADC中断:发生在第四步。


上面的中断处理函数其实就是TC中断,从名字也可以看得出来,也就是触摸屏发生的第一个中断。


当中断发生的时候首先是自旋锁上锁。然后给出判定并分配了两种情况,假如确实是按下了,那么就开始进行AD转换,AD转换的函数在另一个函数中实现,这里只是调用。如果是弹起中断,那么就继续等待,并调用后续函数(这里的后续函数一定要仔细的看)。


上面的TC中断函数中一共调用了两个函数,分别是start_ts_adc和tsEvent函数。下面分别介绍这两个函数。


start_ts_adc函数:


//通过响应的寄存器的设置来启动AD转换。

//mode_x_axis,start_adc_x都是宏定义的函数。

static inline void start_ts_adc(void)

{

 adc_state = 0;

 mode_x_axis();

 start_adc_x();

}

这个函数主要是通过操作寄存器来实现的,具体的定义在整个程序开始的宏定义中有表现。


tsEvent函数:


static void tsEvent_raw(void)

{

if (tsdev.penStatus == PEN_DOWN) { /* 保存按下时的坐标 */

BUF_HEAD.x = x;

BUF_HEAD.y = y;

BUF_HEAD.pressure = PEN_DOWN;

 

#ifdef HOOK_FOR_DRAG 

/*当笔在触摸屏上长期滑动的时候,如果不进行特殊处理不会产生点的轨迹。*/

ts_timer.expires = jiffies + TS_TIMER_DELAY;

add_timer(&ts_timer); /* 

对长时间按下键的处理 

这个函数的具体实现在本函数中实现。

*/

#endif

} else {

#ifdef HOOK_FOR_DRAG 

del_timer(&ts_timer);

#endif

BUF_HEAD.x = 0;

BUF_HEAD.y = 0;

BUF_HEAD.pressure = PEN_UP; /* 保存弹起时的坐标 */

}

 

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

//这里的唤醒进程和read函数中的sleep on对应。

wake_up_interruptible(&(tsdev.wq)); /* 唤醒进程 */

 

}



在等待按下中断函数后再调用后续处理函数,这里是一个循环的调用。在后续处理函数要注意:


#ifdef HOOK_FOR_DRAG

/*当笔在触摸屏上长期滑动的时候,如果不进行特殊处理不会产生点的轨迹。*/

  ts_timer.expires = jiffies + TS_TIMER_DELAY;

  add_timer(&ts_timer);


      /*

        对长时间按下键的处理

        这个函数的具体实现在本函数中实现。

       */

#endif


这个函数是针对长时间按键的情况,这里ts_timer实现了检测频率的体现,同时,ts_timer中实现了如下函数:


static void ts_timer_handler(unsigned long data)

{

spin_lock_irq(&(tsdev.lock));

if (tsdev.penStatus == PEN_DOWN) {

start_ts_adc();

}

//给这个程序解锁。

spin_unlock_irq(&(tsdev.lock));

}

这样长时间按键的情况就不是检测连个中断了,而且检测的频率还可以自己进行设定。


④当TC中断函数执行完成以后自然而然的根据IRQ中断号就要执行另一个中断ADC中断了。


static void s3c2410_isr_adc(int irq, void *dev_id, struct pt_regs *reg)

{

 

spin_lock_irq(&(tsdev.lock));

if (tsdev.penStatus == PEN_UP)

  s3c2410_get_XY();

#ifdef HOOK_FOR_DRAG

else

  s3c2410_get_XY();

#endif

spin_unlock_irq(&(tsdev.lock));

}


这一部分是ADC实现的代码。其中这个函数主要调用了 s3c2410_get_XY这个函数,包括判定之后的执行也都是在s3c2410_get_XY这个函数再进行进一步判定之后进行的。


下面列出s3c2410_get_XY这个函数的主要代码:


static inline void s3c2410_get_XY(void)

{

//adc_state这个变量的作用是区分现在到底在获取哪一个坐标。

if (adc_state == 0) { /* 转换x */

adc_state = 1;

disable_ts_adc();

y = (ADCDAT0 & 0x3ff); /* 获取x坐标 */

mode_y_axis(); 

start_adc_y(); /*启动y坐标转化*/

} else if (adc_state == 1) {  /*转换y*/

adc_state = 0;

disable_ts_adc();

x = (ADCDAT1 & 0x3ff); /* 获取y坐标 */

tsdev.penStatus = PEN_DOWN; /* 改变屏状态 */

DPRINTK("PEN DOWN: x: %08d, y: %08dn", x, y);

wait_up_int();   /* 等待弹起中断 */

tsEvent();

}

}


在上述的几个中断程序中涉及到了部分流程控制的循环调用,所以大家务必仔细阅读。


⑤中断讲解完毕以后开始说一下file_operations。


多么的亲切!


static struct file_operations s3c2410_fops = {

 owner: THIS_MODULE,

 open: s3c2410_ts_open,

 read: s3c2410_ts_read, 

 release: s3c2410_ts_release,

 poll: s3c2410_ts_poll,

};


说到了file_operations了,那么就把代码分别粘贴出来了ha~


s3c2410_ts_open:


static int s3c2410_ts_open(struct inode *inode, struct file *filp)

{

tsdev.head = tsdev.tail = 0;

tsdev.penStatus = PEN_UP;

#ifdef HOOK_FOR_DRAG 

init_timer(&ts_timer);

ts_timer.function = ts_timer_handler;

#endif

tsEvent = tsEvent_raw;

init_waitqueue_head(&(tsdev.wq));

 

MOD_INC_USE_COUNT;

return 0;

}


说到这里还有一个问题没有弄懂,那就是tsdev.head = tsdev.tail = 0;不懂为什么头和尾都要置零。其他的部分也就不做过多的解释了。

s3c2410_ts_read函数:


static ssize_t s3c2410_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)

{

TS_RET ts_ret;

 

retry: 

if (tsdev.head != tsdev.tail) {

int count;

count = tsRead(&ts_ret);

if (count) copy_to_user(buffer, (char *)&ts_ret, count);

return count;

} else {

if (filp->f_flags & O_NONBLOCK)

return -EAGAIN;

interruptible_sleep_on(&(tsdev.wq));

//这个判断的作用是:判断是否是信号把它唤醒了

if (signal_pending(current))

return -ERESTARTSYS;

goto retry;

}

 

return sizeof(TS_RET);

}


注意一下这里://这个判断的作用是:判断是否是信号把它唤醒了if (signal_pending(current))。


release函数:


static int s3c2410_ts_release(struct inode *inode, struct file *filp)

{

#ifdef HOOK_FOR_DRAG

del_timer(&ts_timer);

#endif

MOD_DEC_USE_COUNT;

return 0;

}


大体部分也就上面这些,我是在看过了input子系统实现了触摸屏驱动之后写的这个,突然感觉还是input子系统实现起来比这个简单了很多。

关键字:mini2440 引用地址:mini2440触摸屏驱动----非input子系统实现方法

上一篇:mini2440的触摸屏驱动----使用input子系统实现
下一篇:MINI2440 按键输入子系统 驱动及测试代码分析

推荐阅读最新更新时间:2024-11-12 15:17

一起学mini2440裸机开发(十二)--mini2440的串口中断实验
本实验实现的功能是:利用串口中断功能,通过串口调试工具接收到字符后再显示。 下图为我的工程文档 main.c文件 #include isrservice.h #include uart.h #include led.h #include interrupt.h int main() { Uart0_Init(115200); //初始化并设置波特率为115 200 Uart0_Interrupt_Init(); //Uart0中断初始化 Led_Init(); //Led初始化 while(1) //循环,等到中断发生 { ; }
[单片机]
一起学<font color='red'>mini2440</font>裸机开发(十二)--<font color='red'>mini2440</font>的串口中断实验
Ubuntu 8.10 下移植 madplay 到 mini2440
在 Ubuntu 8.10 下移植 madplay 到 mini2440过程中同样参考了网上的一篇帖子,由于当时未想到要把过程放到这就没有记录那篇帖子的网址,在此表示感谢! madplay移植记录: 一、PC版的madplay PC版的编译基本同mini2440手册上的一致。 二、ARM版的madplay 1、编译zlib-1.2.3 解压zlib-1.2.3.tar.gz到/opt/FriendlyARM/mini2440/madplay/src-arm/zlib-1.2.3 进入zlib-1.2.3目录 配置configure: sudo gedit configure a、把AR=${AR- ar rc }改为: AR=${
[单片机]
玩转mini2440开发板之【64位Ubuntu系统无法运行arm-linux-gcc】
前段时间由于工作原因,将虚拟机重装了,由原来的Ubuntu 12.04(32位)升级成了Ubuntu 16.04(64位)。自然,原来安装在Ubuntu 12.04中的所有mini2440开发板相关的工具和源码,都要重装一遍。今天刚好得空,于是就开始整。 第一步当然是安装交叉编译器了,仍然是友善之臂arm-linux-gcc 4.4.3的版本,按照官方手册的步骤,直接解压,然后添加环境变量,一气呵成。可是,当我注销完重新登录之后,输入命令时,系统却给出了一个出错提示: leon@Ubuntu:~$ arm-linux-gcc -v /opt/FriendlyARM/toolschain/4.4.3/bin/arm-linu
[单片机]
mini2440 LED灯裸机硬件控制程序
查找mini2440的原理图,找到LED部分的原理图: 然后查找nLED_1到nLED_4分别连接的S3C2440的引脚: 由图可知: nLED_1---GPB5 nLED_2---GPB6 nLED_3---GPB7 nLED_4---GPB8 在S3C2440的引脚划分中,这四个引脚都属于Port B,因此可以通过配置Port B的控制寄存器对这四个引脚的功能进行配置 如果要让LED灯亮,nLED_1到nLED_4端需要低电平,因此GPB5到GPB8引脚需要: (1)输出:GPBCON 因此,GPBCON寄存器的11,13,15,17位要设置为0,而10,12,14,16位要设置为1,而且我们还知道GPBCON
[单片机]
<font color='red'>mini2440</font> LED灯裸机硬件控制程序
keil mini2440裸机代码问题解决笔记1
Warning: L6305W: Image does not have an entry point. (Not specified or not set due to multiple choices.) 加上启动代码 注释掉main,会出现 解决 在Options for Target选项的Linker—Misc controls加入入口地址:–entry Reset_Handler 帮助手册中 Controls Specify any directive for which there is no individual dialog control.
[单片机]
linux-2.6.32在mini2440开发板上移植-移植UDA1341 音频驱动
1 在初始化文件中加入UDA1341 设备结构 Linux-2.6.32.2 已经完美的支持UDA1341 音频芯片的驱动, 我们只要在arch/arm/mach-s3c2440/mach-mini2440.c 文件中注册UDA1341 平台设备的控制端口就可以了,打开mach-mini2440.c,添加如下内容: ;在文件首部添加头文件 #include sound/s3c24xx_uda134x.h ;在LCD 平台设备后面添加UDA1341 设备结构 static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data = { .l3_clk =
[单片机]
mini2440 按键驱动POLL机制实验
Makefile KERN_DIR = /home/grh/kernel_source_code/linux-2.6.32.2 all : make -C $(KERN_DIR) M=`pwd` modules arm-linux-gcc key_interrupt_app.c -o key_interrupt_app clean : make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += test_driver.o obj-m += key_poll.o obj-m += key_interrupt.o copy
[单片机]
<font color='red'>mini2440</font> 按键驱动POLL机制实验
Linux-2.6.32.2内核在mini2440上的移植(九)---触摸屏驱动移植
移植环境 1,主机环境:VMare下CentOS 5.5 ,1G内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 嵌入式linux应用开发完全手册,韦东山,编著。 Mini2440 之Linux 移植开发实战指南 【1】在内核中添加触摸屏驱动程序 Linux-2.6.32.2 内核也没有包含支持S3
[单片机]
Linux-2.6.32.2内核在<font color='red'>mini2440</font>上的移植(九)---<font color='red'>触摸屏</font>驱动移植
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved