历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2018年10月11日 | OK6410触摸屏驱动

发布者:seanxnie 来源: eefocus关键字:OK6410  触摸屏驱动 手机看文章 扫描二维码
随时随地手机看文章

ts.c源码:

#include "linux/module.h"

#include "linux/init.h"

#include "linux/fs.h"

#include "linux/interrupt.h"

#include "linux/irq.h"

#include "linux/sched.h"

#include "linux/pm.h"

#include "linux/sysctl.h"

#include "linux/proc_fs.h"

#include "linux/delay.h"

#include "linux/platform_device.h"

#include "linux/input.h"

#include "linux/io.h"

#include "linux/clk.h"

#include "linux/delay.h"

static struct timer_list ts_timer;

static struct input_dev *ts_dev;

struct adc_regs {

    unsigned long adccon;

    unsigned long adctsc;

    unsigned long adcdly;

    unsigned long adcdat0;

    unsigned long adcdat1;

    unsigned long adcupdn;

    unsigned long adcclrint;

    unsigned long reserved;

    unsigned long adcclrintpndnup;

};

static struct adc_regs *adc_regs;

static void enter_wait_for_pen_down(void)

{

    adc_regs->adctsc = 0xd3;

}

static void enter_wait_for_pen_up(void)

{

    adc_regs->adctsc = 0x1d3;

}

static void enter_measure_xy_mode(void)

{

    adc_regs->adctsc = ((1<<7) | (1<<6) | (1<<4) | (1<<3) | (1<<2));

}

static void start_adc(void)

{

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

}

static irqreturn_t ts_pen_down_up_isr(int irq, void *dev_id)

{

    unsigned long data0, data1;

    int down;

    data0 = adc_regs->adcdat0;

    data1 = adc_regs->adcdat1;

    down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));

    

    if (!down)

    {

        //printk("pen up\n");

        enter_wait_for_pen_down();

        // 调用evdev_event: 保存,唤醒 

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);

        input_sync(ts_dev);

    }

    else

    {

        //printk("pen down\n");

        //enter_wait_for_pen_up();

        // 进入"自动测量x/y座标模式" 

        enter_measure_xy_mode();

        

        // 启动ADC 

        start_adc();

    }

    adc_regs->adcupdn   = 0;

    adc_regs->adcclrint = 0;

    adc_regs->adcclrintpndnup = 0;

    return IRQ_HANDLED;

}

static irqreturn_t adc_isr(int irq, void *dev_id)

{

    // 为何不在这里立刻处理ADC到结果?

    // 因为6410的ADC有个缺点: 

    // 当ADC刚完成时, 必须等待若干ms, 

    // 才能读取adcdat0,adcdata1来判断

    // 当前的触摸屏是被按下还是松开

    // 启动定时器, 是为了不在中断处理函数里等待 

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

    enter_wait_for_pen_up();

    adc_regs->adcupdn   = 0;

    adc_regs->adcclrint = 0;

    adc_regs->adcclrintpndnup = 0;

    return IRQ_HANDLED;

}

static irqreturn_t adc_isr_ok_old(int irq, void *dev_id)

{

    int x,y;

    int adcdat0,adcdat1;

    int down;

#if 1 // in auto xy mode, after adc interrupt, have to wait several ms to test up/down  

    udelay(1000);

    udelay(1000);

    udelay(1000);

    udelay(1000);

#endif

    adcdat0 = adc_regs->adcdat0;

    adcdat1 = adc_regs->adcdat1;

    x = adcdat0 & 0xfff;

    y = adcdat1 & 0xfff;

    

    down = (!(adcdat0 & (1<<15))) && (!(adcdat1 & (1<<15)));

    //printk("adcdat0 = 0x%x, adc_dat1 = 0x%x\n", adcdat0, adcdat1);

    if (down)

    {

        //printk("enter_wait_for_pen_up\n");

        enter_wait_for_pen_up();

        //printk("x = %d, y = %d\n", x, y);

        input_event(ts_dev, EV_ABS, ABS_X, x);

        input_event(ts_dev, EV_ABS, ABS_Y, y);

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 1);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 1);

        input_sync(ts_dev);

        // 启动定时器 

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

    }

    else

    {

        //printk("enter_wait_for_pen_down\n");

        enter_wait_for_pen_down();

        

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);

        input_sync(ts_dev);

    }

    adc_regs->adcupdn   = 0;

    adc_regs->adcclrint = 0;

    adc_regs->adcclrintpndnup = 0;

    return IRQ_HANDLED;

}

static void ts_timer_function_ok_old(unsigned long data)

{

    // 如果触摸笔已经松开, 就没必要再次启动ADC 

    // 否则, 启动ADC 

    unsigned long data0, data1;

    int down;

    data0 = adc_regs->adcdat0;

    data1 = adc_regs->adcdat1;

    down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));

    

    if (down)

    {

        enter_measure_xy_mode();

        start_adc();

    }

    else

    {

        enter_wait_for_pen_down();

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);

        input_sync(ts_dev);

    }

}

static void ts_timer_function(unsigned long data)

{

    // 如果触摸笔已经松开, 就没必要再次启动ADC 

    // 否则, 启动ADC 

    unsigned long data0, data1;

    int down;

    int x, y;

    data0 = adc_regs->adcdat0;

    data1 = adc_regs->adcdat1;

    down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));

    if (down)

    {

        x = data0 & 0xfff;

        y = data1 & 0xfff;

        input_event(ts_dev, EV_ABS, ABS_X, x);

        input_event(ts_dev, EV_ABS, ABS_Y, y);

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 1);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 1);

        input_sync(ts_dev);

        

        enter_measure_xy_mode();

        start_adc();

    }

    else

    {

        enter_wait_for_pen_down();

        input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);

        input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);

        input_sync(ts_dev);

    }

}

static int ts_init(void)

{

    struct clk *clk;

    // 1. 分配input_dev 

    ts_dev = input_allocate_device();

    

    // 2. 设置 

    // 2.1 能产生哪类事件 

    set_bit(EV_KEY, ts_dev->evbit);

    set_bit(EV_ABS, ts_dev->evbit);

    

    // 2.2 能产生这类事件里的哪些事件 

    set_bit(BTN_TOUCH, ts_dev->keybit);

    input_set_abs_params(ts_dev, ABS_X, 0, 0xfff, 0, 0);

    input_set_abs_params(ts_dev, ABS_Y, 0, 0xfff, 0, 0);

    input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0);

    

    // 3. 注册 

    input_register_device(ts_dev);

    

    // 4. 硬件相关 

    adc_regs = ioremap(0x7E00B000, sizeof(struct adc_regs));

    clk = clk_get(NULL, "adc");

    clk_enable(clk);  // PCLK_GATE[12]设为1 

    // bit[16]   : 1 = 12-bit A/D conversion

    // bit[14]   : 1 - enable A/D converter prescaler enable

    // bit[13:6] : A/D converter prescaler value,

    //             PCLK=66500000, adcclk=pclk/(n+1)

    //             取值13, adclk=66.5MHz/14=4.75

     

    adc_regs->adccon = (1<<16) | (1<<14) | (65<<6);

    adc_regs->adcdly = 0xffff;

    adc_regs->adcclrintpndnup = 0;

    request_irq(IRQ_TC, ts_pen_down_up_isr, IRQF_SHARED, "pen_down_up", 1);

    request_irq(IRQ_ADC, adc_isr, IRQF_SHARED, "adc", 1);

    init_timer(&ts_timer);

    ts_timer.expires  = 0;

    ts_timer.function = ts_timer_function;

    add_timer(&ts_timer);

    // 进入"wait for interrupt mode", 等待触摸笔按下或松开的模式 

    enter_wait_for_pen_down();

    return 0;

}

static void ts_exit(void)

{

    del_timer(&ts_timer);

    free_irq(IRQ_TC, 1);

    free_irq(IRQ_ADC, 1);

    iounmap(adc_regs);

    input_unregister_device(ts_dev);

    input_free_device(ts_dev);

}

module_init(ts_init);

module_exit(ts_exit);

MODULE_LICENSE("GPL");

====================================================================

Mekefile文件:

KERN_DIR = /home/linux/linux-3.0.1

all:

    make -C $(KERN_DIR) M=`pwd` modules 

clean:

    make -C $(KERN_DIR) M=`pwd` modules clean

    rm -rf modules.order

obj-m += ts.o

=====================================================================

测试:

一、配置内核make menuconfig ARCH=arm 去掉第三张图片中touchscreens选项前的*

OK6410如何去掉触摸屏驱动OK6410如何去掉触摸屏驱动OK6410如何去掉触摸屏驱动

若只做这一步,编译内核会提示如下错误:

arch/arm/mach-s3c64xx/built-in.o: In function `smdk6410_machine_init':

/xh/work/linux-3.0.1/arch/arm/mach-s3c64xx/mach-smdk6410.c:1096: undefined reference to `s3c_ts_set_platdata'

arch/arm/mach-s3c64xx/built-in.o:(.init.data+0x26c): undefined reference to `s3c_device_ts'

make: *** [.tmp_vmlinux1] Error 1

[root@IVAN linux-3.0.1]#

二、打开/arch/arm/mach-s3c64xx/mach-smdk6410.c

    搜索 “s3c_ts_set_platdata”和“s3c_device_ts”,并注释掉这两行。

成功……


三、使用新内核启动:

1、编译内核:

make zImage                 //生成内核镜像文件

cp arch/arm/boot/zImage ../../zImage_no_ts

2、把开发板设置为SD卡启动,使用SD卡启动后按空格进入SD卡的u-boot;

3、用SD卡里面的u-boot烧写内核到0x000000200000-0x000000700000 : "Kernel"分区:

tftp 50008000 zImage_no_ts

nand erase 200000 500000

nand write 50008000 200000 500000

4、烧写完成后设置开发版为nand flash启动,使用新内核启动。

四、编译测试(详细可以参考JZ2440触摸屏驱动程序(输入子系统)):

insmod ts.ko

insmod lcd.ko

编译:

tar xzf tslib-1.4.tar.gz

cd tslib

./autogen.sh 

mkdir tmp

echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache

./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp

make

make install

set bootargs root=/dev/nfs nfsroot=10.1.0.124:/rootfs ip=10.1.0.126 console=ttySAC0

安装:

cd tmp

cp * -rf 开发板的/

使用:

1.

修改 /etc/ts.conf第1行(去掉#号):

# module_raw input

改为:

module_raw input

2.

export TSLIB_FBDEVICE=/dev/fb0             # LCD

export TSLIB_TSDEVICE=/dev/event2        # 触摸屏

export TSLIB_CALIBFILE=/etc/pointercal

export TSLIB_CONFFILE=/etc/ts.conf

export TSLIB_PLUGINDIR=/lib/ts

export TSLIB_CONSOLEDEVICE=none

测试:

ts_calibrate

ts_test

hexdump /dev/event2


关键字:OK6410  触摸屏驱动 引用地址:OK6410触摸屏驱动

上一篇:OK6410分层分离(总线-驱动-设备模型)
下一篇:OK6410之LCD驱动

推荐阅读

在今年的人工智能和机器学习投资竞赛中,中国最大的科技公司BAT、蚂蚁金服已经超过了硅谷的科技巨头。同时,虽然美国继续创造最大规模的创业和风险资本活动,但其占全球总量的份额已大幅下降,北京等城市崛起。 中国AI超越美国了——在投资上。 据英国媒体,最新研究显示,在今年的人工智能和机器学习投资竞赛中,中国最大的科技公司已经超过了硅谷的科...
周三,John B. Goodenough(得克萨斯大学)、M. Stanley Whittingham(纽约州立大学宾汉顿分校)和吉野彰(旭化成研究员、名城大学教授)因为对锂离子电池开发的贡献而获得了2019年的诺贝尔化学奖。对于三位的获奖原因,诺贝尔委员会表示:“锂离子电池彻底改变了我们的生活,并广泛应用于从手机到笔记本电脑和电动汽车的所有领域。通过他们的工作,为...
受新冠疫情的影响,全球液晶面板价格大幅反弹,第三季度大部分尺寸LCD TV面板的价格上涨30%以上。据业内消息透露,由于LCD面板价格大幅度上涨,LGD决定将生产计划延长一年。据悉,LGD已将这一计划告知了合作伙伴及其他相关公司。近两年,随着大陆高世代产线产能的释放,LCD面板价格持续下降,导致韩系两大液晶面板巨头三星和LGD的经营业绩陷入亏损状态,...
早前,台积电董事长刘德音接受专访时表示,对于芯片短缺问题,台积电努力用前所未有的方式解决,不过送到工厂的芯片比用于产品多,代表供应链有人囤积芯片!刘德音指出,因车用芯片短缺造成车厂大幅减产,很多车厂指责台积电供应不足,但他们想对车厂说,你是我客户的客户的客户,台积电怎么会「优先考虑其他人」而不给你芯片?为了解决车用芯片短缺,台积...

史海拾趣

问答坊 | AI 解惑

925MHZ to 2175MHZ RF设计

知道1/4波长射频个公式:波长(天线)=(300/f)*0.25*0.96 这个F是指一个固定频率么,现在我的频率是925MHZ to 2175MHZ ,天线长度该如何设置呢?…

查看全部问答∨

以太网 Lite MAC(媒体访问控制器)

以太网 Lite MAC(媒体访问控制器)设计用来整合 IEEE 标准内介绍的可用特性。802.3 媒体独立接口(MII)规范。 The Ethernet Lite MAC (Media Access Controller) is designed to incorporate the applicable features described in the IEEE Std ...…

查看全部问答∨

CodeWarrior+USB-TAP怎么调试PowerPC(VxWorks系统)下的bootrom

请教高手,一个问题 现在我手上有一个CodeWarrior IDE(Windows版)和USB-TAP 我就是想问:怎么用它们调试基于Freescale’ PowerPC的MPC8270下面的bootrom,我用的是VxWorks系统,可以跟踪romInit、bootInit跑到什么地方的那种,而不是调试Linux下 ...…

查看全部问答∨

ActiveSync无法连接的问题

我使用的QQ2440V3 开发板,按照说明书的介绍,安装好了USB驱动,在DNW中显示为“OK”,但是ActiveSync一直连接不上pc,哪位知道怎么解决?是什么问题造成的?…

查看全部问答∨

100分求助EBOOT中startup.s代码问题

本来不好意思问这些代码问题。但是钻进了死胡同,看了差不多一天了也还是没有头绪;以前学得都比较顺畅,今天开始不停郁闷。 问题如下: 1、startup.s其中一个功能是把eboot的代码搬到RAM中运行,根据注释,我找到 startup.s中相应的代码: ;&n ...…

查看全部问答∨

linux嵌入式开发群列表

linux嵌入式开发群列表,很多群: http://linuxembed.5d6d.com/thread-57-1-1.html…

查看全部问答∨

beaglebone心得五:画个转接板

根据淘来的东东画个转接板,很简单,先上图,这也是周计划的一部分。 原理: PCB 3D: …

查看全部问答∨

移动电源制作

前段时间作比赛,认为可以报销花费。所以就买了一个5V(6000mAh)的锂聚物电池,现在闲置下来。想把它改造成一个手机移动电源来使用,电池的输出 电压为5.2V,电流暂时还没测。而且不清楚手机的最大输入电压与输入电流的值的大小,希望大家有做过 ...…

查看全部问答∨

国嵌C语言加密视频

国嵌C语言讲的不错 ,分享一下 http://pan.baidu.com/s/1tHFxE…

查看全部问答∨

zigbee2006协议栈定时器

协议栈中到底用了几个定时器?我们应该怎么看啊?我看HAL层吧所有的驱动都写好了,。,。,…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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