S5PV210(TQ210)学习笔记——触摸屏驱动编写

发布者:数字航海家最新更新时间:2015-08-19 来源: eefocus关键字:S5PV210  触摸屏  驱动编写 手机看文章 扫描二维码
随时随地手机看文章
电阻式触摸屏的驱动比较简单,可以采用输入子系统驱动框架来编写,而电容式触摸屏的驱动程序相对比较复杂,因为电容触控一般采用I2C接口控制,我在自己编写电容触控驱动的时候郁闷了好几天,当然,并不是因为I2C电容触控驱动繁琐,主要是天嵌TQ210的触摸屏驱动程序是以模块方式提供的,并不开放源代码,也没有提供触控的芯片手册,我曾通过技术咨询群和电话咨询的方式咨询过天嵌相关人士,想跟他们索取触控协议而不要所谓的触控驱动程序源码,但受保密协议限制不提供源码及手册。我们不去追究这些无聊的问题,只要找到触控芯片的型号并根据触控芯片型号找到对应的手册,然后就可以自己编写所谓的电容式触摸屏驱动了。

一 触控芯片分析

首先,卸下触摸屏的四个螺丝并翻过触摸屏来观察,可以在在触摸屏排线上看到触控芯片,仔细观察芯片型号(如果看不清可以用放大镜配合手电筒观看),我们可以看到,TQ210的触摸屏控制芯片是GT811,然后我找到了GT811的芯片手册(这些资料都上传到了我的CSDN资源里,请您支持一下),有了手册,编写驱动就不难了。

GT811引出了6根脚,分别是VCC、GND、I2CSDA、I2CSCL、INT和RESET,虽然INT脚不是必须的,但是开发高效省资源的触屏驱动程序往往都采用中断方式,下面是GT811的引脚图:

我用万能表实际测量了一下触控模块的各个引脚,实际线序是GND、SDA、SDL、INT、RESET和VDD。GT811的初始化顺序如下:

  1. (1) 初始化INT脚为悬浮输入态并初始化RESET脚为输出态,并输出低电平  
  2. (2) 延时1ms  
  3. (3) 初始化RESET脚为悬浮输入态,并使能上拉  
  4. (4) 写入GT811寄存器配置表  
  5. (5) 根据需要配置INT脚  
具体的操作可以参见代码部分。

 

二 I2C驱动编写

I2C驱动也是基于总线结构的,不过分为两种,一种是Legacy方式,另一种是New Style方式,其中,Legacy方式在新内核中已经不支持了,不过韦东山老师的视频中还是分析的Legacy方式,New Style方式你可以自己用Source Insight追踪分析一下,我这里就不多说了,具体的可以参考下面的代码。

  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8. #include   
  9.   
  10. const static unsigned short normal_address[] = {0x5d, I2C_CLIENT_END};  
  11. static unsigned gt811_rst;  
  12. static unsigned gt811_int;  
  13. static struct input_dev *ts_input;  
  14. static struct workqueue_struct *wq;  
  15. static struct work_struct work;  
  16.   
  17. static struct i2c_client * this_client = NULL;  
  18.   
  19. static unsigned int status = 0;  
  20.   
  21. static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)  
  22. {  
  23.     struct i2c_msg msgs[2];  
  24.     int ret=-1;  
  25.       
  26.     msgs[0].flags=!I2C_M_RD;  
  27.     msgs[0].addr=client->addr;  
  28.     msgs[0].len=2;  
  29.     msgs[0].buf=&buf[0];  
  30.   
  31.     msgs[1].flags=I2C_M_RD;  
  32.     msgs[1].addr=client->addr;  
  33.     msgs[1].len=len-2;  
  34.     msgs[1].buf=&buf[2];  
  35.       
  36.     ret=i2c_transfer(client->adapter,msgs, 2);  
  37.     return ret;  
  38. }  
  39.   
  40. static int i2c_write_bytes(struct i2c_client *client,uint8_t *data,int len)  
  41. {  
  42.     struct i2c_msg msg;  
  43.     int ret=-1;  
  44.       
  45.     msg.flags=!I2C_M_RD;  
  46.     msg.addr=client->addr;  
  47.     msg.len=len;  
  48.     msg.buf=data;     
  49.       
  50.     ret=i2c_transfer(client->adapter,&msg, 1);  
  51.     return ret;  
  52. }  
  53.   
  54. static const struct i2c_device_id ts_id[] = {  
  55.     { "tq210-ts", 0 },  
  56.     { }  
  57. };  
  58.   
  59. static int ts_init_panel(struct i2c_client *client){  
  60.     short ret=-1;  
  61.     uint8_t config_info[] = {  
  62.         0x06,0xA2,  
  63.         0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,  
  64.         0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,  
  65.         0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,  
  66.         0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,  
  67.         0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,  
  68.         0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,  
  69.         0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01     
  70.     };  [page]
  71.     config_info[62] = 480 >> 8;  
  72.     config_info[61] = 480 & 0xff;  
  73.     config_info[64] = 800 >> 8;  
  74.     config_info[63] = 800 & 0xff;  
  75.     ret = i2c_write_bytes(client, config_info, sizeof(config_info)/sizeof(config_info[0]));  
  76.     if(ret < 0)  {  
  77.         printk(KERN_ERR "GT811 Send config failed! ");  
  78.         return ret;   
  79.     }  
  80.     return 0;  
  81. }  
  82.   
  83. static irqreturn_t gt811_int_handler(int irq, void *devid){  
  84.     disable_irq_nosync(this_client->irq);  
  85.     queue_work(wq, &work);  
  86.     return IRQ_RETVAL(IRQ_HANDLED);  
  87. }  
  88.   
  89. static void ts_work_func(struct work_struct* work){  
  90.     int ret;  
  91.     unsigned char point_data[19] = {0x07, 0x21, 0};  
  92.     unsigned short input_x = 0;  
  93.     unsigned short input_y = 0;  
  94.     unsigned short input_p = 0;  
  95.       
  96.     ret=i2c_read_bytes(this_client, point_data, sizeof(point_data)/sizeof(point_data[0]));  
  97.     if(ret <= 0){  
  98.         printk("Failed ");  
  99.         return;  
  100.     }  
  101.   
  102.     if(point_data[2]&0x1){  
  103.         status = 1;  
  104.         input_y = 479-((point_data[4]<<8)|point_data[5]);  
  105.         input_x = 799-((point_data[6]<<8)|point_data[7]);  
  106.         input_p = point_data[8];  
  107.   
  108.         printk("stat: %d, x: %d, y: %d, p: %d ", point_data[2], input_x, input_y,  
  109.             input_p);  
  110.     }  
  111.     else if(status){  
  112.         status = 0;  
  113.         printk("up ");  
  114.     }  
  115.   
  116.     enable_irq(this_client->irq);  
  117. }  
  118.   
  119. static int ts_probe(struct i2c_client *client, const struct i2c_device_id *id){  
  120.     int retry, ret;  
  121.     char test_data;  
  122.   
  123.     printk("ts_probe ");  
  124.   
  125.     test_data = 0;  
  126.   
  127.     gt811_rst = S5PV210_GPD0(3);  
  128.     gt811_int = S5PV210_GPH1(6);  
  129.     gpio_request(gt811_rst, "reset");  
  130.     gpio_request(gt811_rst, "tsint");  
  131.       
  132.     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))   
  133.     {  
  134.         dev_err(&client->dev, "Must have I2C_FUNC_I2C. ");  
  135.         return -ENODEV;  
  136.     }  
  137.   
  138.     s3c_gpio_setpull(gt811_rst, S3C_GPIO_PULL_UP);  
  139.       
  140.     for(retry=0;retry < 5; retry++)  
  141.     {  
  142.         gpio_direction_output(gt811_rst, 0);  
  143.         msleep(1);  
  144.         gpio_direction_input(gt811_rst);  
  145.         msleep(100);  
  146.       
  147.         ret =i2c_write_bytes(client, &test_data, 1);  
  148.         if (ret > 0)  
  149.             break;  
  150.         dev_info(&client->dev, "GT811 I2C TEST FAILED!Please check the HARDWARE connect ");  
  151.     }  
  152.   
  153.     if(ret <= 0)  
  154.     {  
  155.         dev_err(&client->dev, "Warnning: I2C communication might be ERROR! ");  
  156.         return -ENODEV;  
  157.     }  
  158.   
  159.     for(retry = 0; retry != 5; ++ retry){  
  160.         ret = ts_init_panel(client);  
  161.         if(ret != 0){  
  162.             continue;  
  163.         }  
  164.         else{  
  165.             break;  
  166.         }  
  167.     }  
  168.   
  169.     if(ret != 0){  
  170.         printk("GT811 Configue failed! ");  
  171.         return -ENODEV;  
  172.     }  
  173.   
  174.     this_client = client;  
  175.       
  176.     ts_input = input_allocate_device();  
  177.     if(IS_ERR(ts_input)){  
  178.         printk("GT811 allocate ts input device failed! ");  
  179.         return -ENOMEM;  
  180.     }  
  181.   
  182.     ts_input->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;  
  183.     ts_input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);  
  184.     ts_input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);  
  185.   
  186.     input_set_abs_params(ts_input, ABS_Y, 0,  799, 0, 0);  
  187.     input_set_abs_params(ts_input, ABS_X, 0, 479, 0, 0);  
  188.     input_set_abs_params(ts_input, ABS_PRESSURE, 0, 255, 0, 0);  
  189.   
  190.     ts_input->name = "tq210-ts";  
  191.     ts_input->phys = "input/ts";  
  192.     ts_input->id.bustype = BUS_I2C;  
  193.     ts_input->id.product = 0xBEEF;  
  194.     ts_input->id.vendor  =0xDEAD;  
  195.   
  196.     ret = input_register_device(ts_input);  
  197.     if(ret < 0){  
  198.         printk("Unable register %s input device! ", ts_input->name);  
  199.         input_free_device(ts_input);  
  200.         return -ENOMEM;  
  201.     }  
  202.   
  203.     client->irq = IRQ_EINT(14);  
  204.   
  205.     s3c_gpio_setpull(gt811_int, S3C_GPIO_PULL_UP);  
  206.   
  207.     if(request_irq(IRQ_EINT(14), gt811_int_handler, IRQF_TRIGGER_FALLING, "gt811-int", NULL) < 0){  
  208.         printk("Request irq for gt811 failed! ");  
  209.         input_unregister_device(ts_input);  
  210.         input_free_device(ts_input);  
  211.         return -ENOMEM;  
  212.     }  
  213.   
  214.     wq = create_workqueue("ts_handle_thread");  
  215.     if(wq == NULL){  
  216.         printk(KERN_ALERT "crete workqueue failed! ");  
  217.         input_unregister_device(ts_input);  
  218.         input_free_device(ts_input);  
  219.         free_irq(IRQ_EINT(14), NULL);  
  220.         return -ENOMEM;  
  221.     }  
  222.   
  223.     INIT_WORK(&work, ts_work_func);  
  224.       
  225.     return 0;  
  226. }  
  227.   
  228. static int ts_remove(struct i2c_client *client){  
  229.       
  230.     free_irq(IRQ_EINT(14), NULL);  
  231.     enable_irq(client->irq);  
  232.     flush_workqueue(wq);  
  233.     destroy_workqueue(wq);  
  234.       
  235.     input_unregister_device(ts_input);  
  236.     input_free_device(ts_input);  
  237.   
  238.     gpio_free(gt811_rst);  
  239.     gpio_free(gt811_int);  
  240.     return 0;  
  241. }  [page]
  242.   
  243. static struct i2c_driver ts_driver = {  
  244.     .driver = {  
  245.         .name = "tq210-ts",  
  246.         .owner = THIS_MODULE,  
  247.     },  
  248.   
  249.     .probe = ts_probe,  
  250.     .remove = ts_remove,  
  251.     .id_table = ts_id,  
  252.     .address_list = normal_address,  
  253. };  
  254.   
  255. static int ts_init(void){  
  256.     printk("init ");  
  257.     i2c_add_driver(&ts_driver);  
  258.     return 0;  
  259. }  
  260.   
  261. static void ts_exit(void){  
  262.     i2c_del_driver(&ts_driver);  
  263.     printk("exit ");  
  264. }  
  265.   
  266. module_init(ts_init);  
  267. module_exit(ts_exit);  
  268. MODULE_LICENSE("GPL");  
这并不是完整的代码,一方面是没有做异常处理,另一方面是没有上报消息,只是简单的驱动了TQ210的触摸屏部分,如果您需要拿去自己略作修改即可使用。

 

三 注册TS的I2C模块设备

注册TS的I2C模块很简单,在Linux内核文件arch/arm/mach-s5pv210/mach-smdkv210.c文件的I2C通道2结构体中加入TS的I2C地址,也就是0x5d,添加后如下
  1. static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {  
  2.     /* To Be Updated */  
  3.     { I2C_BOARD_INFO("tq210-ts", 0x5d), },  
  4. ;  

四 tslib测试教程(ubuntu)

1. 安装git
  1. sudo apt-get install git  

2.  下载最新的tslib
  1. git clone https://github.com/kergoth/tslib  

3. 安装auto
  1. sudo apt-get install autoconf  automake  libtool  

4. 编译tslib
  1. ./autogen.sh   
  2. mkdir tmp  
  3. echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache  
  4. ./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp  
  5. make  
  6. make install  

5. 安装tslib
  1. cd tmp  
  2. cp * /nfsroot/rootfs -rfd  

6. 配置tslib
  1. 修改 /etc/ts.conf  
  2. 将行  
  3. # module_raw input  
  4. 改为:  
  5. module_raw input  
  6. (实际上就是去掉高行的#号和第一个空格)  

7. 配置tslib运行环境变量
  1. export TSLIB_TSDEVICE=/dev/input/event1  //这里需要根据自己的event位置进行修改,新内核在/dev/input/event*  
  2. export TSLIB_CALIBFILE=/etc/pointercal  
  3. export TSLIB_CONFFILE=/etc/ts.conf  
  4. export TSLIB_PLUGINDIR=/lib/ts  
  5. export TSLIB_CONSOLEDEVICE=none  
  6. export TSLIB_FBDEVICE=/dev/fb0  

8. 校正(电容屏实际上不需要校正,仅为了测试触屏驱动)
  1. 运行ts_calibrate,并根据提示进行校正  

9. 自由画图
  1. 运行ts_test,点击draw按钮,可以自由画图,效果如下图。  
 

五 小结

本文中列举的代码是简单的实现了触摸坐标获取,没有实现触摸消息上报等操作,这些操作需要自己来实现。
 
我自己完善了一下上面讲到的驱动,下面是在TQ210上用最新版tslib测试的效果,同时也支持了多点触摸,代码我上传到了我的资源里,需要的朋友去下载,资源分有点贵啊,见谅。。。
 
关键字:S5PV210  触摸屏  驱动编写 引用地址:S5PV210(TQ210)学习笔记——触摸屏驱动编写

上一篇:S5PV210(TQ210)学习笔记——USB HOST移植
下一篇:S5PV210(TQ210)学习笔记——LCD驱动编写

推荐阅读最新更新时间:2024-03-16 14:29

2010电子产业展望之警惕10个不好的信号
  对于电子产业而言,2009年的开头比较糟糕,不过现在已经显现出积极的信号。      感谢上帝,电子产业看起来正在恢复中。但2010年又会如何呢?进入2010年,市场上将会向大家传达一些好的、以及不好的信号。下面让我们继续分享来自不同分析师的观点:       不好的信号      1. 模拟产品价格上涨?FBR的Berger表示:“注意我们已经提高了对飞兆半导体和国际整流器公司的财务估计,这两家公司在过去几周内对第四季度做出了正面的预计。考虑到2010年第一季度渠道压力和分销商库存补给的潜力,我们认为在2010年初,分立和低利润模拟芯片供应商也许会提高这些产品的价格。”      2. 应用处理器大战即将打响。Broadpoi
[半导体设计/制造]
经验谈之解决电容式触摸屏应用中的噪声问题
触摸屏设备可能会在一天中受到许多不同噪声源的干扰,既包含内部 噪声 也包含外部噪声。充电器和显示器噪声是当今两种最常见的问题噪声源。随着市场上的充电设备变得越来越轻薄、噪声越来越大,这种挑战只会变得更加难以管理。此外,许多其他日常物件也会产生噪声,引起干扰,如无线电信号、交流电源乃至荧光灯镇流器等。在存在噪声的情况下,低性能电容式触摸系统报告的位置可能失真,从而影响准确度和可靠性。 今天的触摸屏控制器采用各种不同的方法来提高信噪比,并从噪声中过滤出不良数据,这些方法包括片上生成高压发射信号、专业化硬件加速、高频发射、自适应跳频技术以及饱和防治技术。但是,触摸技术不断持续发展,涉及的方面包括:触摸控制器如何利用上述特性,如何动态地适
[电源管理]
经验谈之解决电容式<font color='red'>触摸屏</font>应用中的噪声问题
Linux之ARM(IMX6U)裸机C语言LED驱动实验--驱动编写,编译
简介 在开始部分用汇编来初始化一下 C 语言环境,比如初始化 DDR、设置堆栈指针 SP 等等,当这些工作都做完以后就可以进入 C 语言环境,也就是运行 C 语言代码,一般都是进入 main 函数。所以我们有两部分文件要做: ①、汇编文件 汇编文件只是用来完成 C 语言环境搭建。 ②、C 语言文件 C 语言文件就是完成我们的业务层代码的,其实就是我们实际例程要完成的功能 1.汇编文件初始化C语言运行环境 设置处理器进入 SVC 模式 以前的 ARM 处理器有 7 种运行模型:User、FIQ、IRQ、Supervisor(SVC)、Abort、Undef和 System,其中 User 是非特权模式,其余 6 中都是特
[单片机]
Linux之ARM(IMX6U)裸机C语言LED<font color='red'>驱动</font>实验--<font color='red'>驱动</font><font color='red'>编写</font>,编译
触摸屏控制器ADS7845
个人数字助理、寻呼机、便携仪器等所用的触摸屏控制器ADS7845是一款12位取样A/D变换器,它具有同步串行接口和驱动触摸屏的低导通电阻开关。它的5线触摸屏接口是:UR(上右屏驱动器),UL(上左屏驱动器),LR(下右屏驱动器),LL(下左屏驱动器)和GND(地)以及WIPER(屏输入),见图1。 ADS7845触摸屏控制器是一典型的逐步近拟寄存器(SAR)A/D变换器。其结构以电容再分布为基础,因而固有地包含取样/保持功能。 这种触摸屏控制器的基本连接示于图2。 此器件需要一个外部基准(输入为VREF引脚)和一个外部时钟(输入为DCLK引脚)。外部基准可以是1V和+Vcc之间的任一电压。基准电压值直接设定输入范围,而
[应用]
低成本电容式触摸屏技术推动系统设计创新
电容式触控技术在厨房设备中的应用已经有几年了,例如在烤箱和煎锅的不透明玻璃面板后面采用分离按键实现。这些触摸控制键逐渐替代了机械按键,因为后者具有使用寿命短、不够卫生等方面的问题,而且还有在面板上开孔安装按键的相关成本。 图1:“电荷转移”技术原理示意图。 电容式感应技术由于具有耐用、易于低成本实现等特点,而逐渐成为触摸控制的首选技术。此外,由于具有可扩展性,该技术还可以提供其它技术所不能实现的用户功能。在显示屏上以软按键方式提供用户界面,这通常被称为触摸屏。量研科技(Quantum Research)公司在触摸屏技术方面的发展为新设备的设计打开了大门,并将日益成为市场主流。 采用量研的电容式触摸感应技术
[应用]
赛普拉斯触摸屏控制器可精确跟踪戴手套的多指触控动作
赛普拉斯半导体公司宣布,其用于大屏手机、智能手机、平板电脑和电子书的TrueTouch® Gen5触摸屏控制器系列现已具备多种先进功能,包括业界最佳的电容式触摸屏手套触控功能。TMA568控制器还能支持“悬停”功能,使得触摸屏能预测手指的触点,并放大相应内容(例如地图上的某个点),从而更容易查找和选择目标对象。除了这些新功能之外,TMA568控制器还具有业界领先的抗噪声、防水和大物体抑制功能。 Gen5 TMA568具有业界最佳的精确度和线性度,适用于多个不同大小的手指及不同材质不同厚度的手套,包括滑雪手套。 此外,无需用户干预,它就可实现戴手套和不戴手套状态的自动切换。 该控制器的“悬停”功能通过模拟PC上的“鼠标悬浮”
[单片机]
S5PV210开发 -- 启动流程
讲完启动模式、烧写更新,接下来我们看一下启动流程。 参看:S5PV210开发 -- 烧写/启动模式 参看:S5PV210开发 -- 通过 SD 卡烧写 参看:S5PV210开发 -- 通过 DNW、fastboot 烧写 参看:DM368开发 -- Bootloader 开发(转毕设) 学习S5PV210 启动流程部分,需要查看芯片手册和相关的文档。 下载:相关文档 一、iROM启动方式简介 在讲烧写/启动模式的时候其实已经提到,S5PV210 采用 iROM 启动方式进行启动,支持从MoviNAND/iNand, MMC/SD Card ,pure Nand, eMMC, eSSD, UART and U
[单片机]
<font color='red'>S5PV210</font>开发 -- 启动流程
触摸屏控制器的性能指标信噪比相关情况解析方案
触摸屏控制器制造商经常拿各种规格和标准来使自己的产品与众不同。其中最常提到的就是信噪比(SNR)。然而,当噪声存在时,即使数字上看起来不错,也并不意味着SNR就是一个很好的系统性能指标。这篇文章将讨论什么是信噪比,它是如何计算的,它对系统性能意味着什么,是否能很好的度量触摸性能。 什么是信噪比? 信噪比是触摸屏控制器的性能指标,现在已经作为行业标准被大家接受。信噪比的问题是没有任何行业标准的测量、计算、报告方法,尤其是在某些典型系统中,噪声具有高可变性的情况下,例如移动电话。这两个部分(信号和噪声)的测量和计算很大程度上依赖于被测装置(DUT),有代表性的是移动电话。值得注意的是,虽然信噪比作为性能衡量已被广泛接受,行业专
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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