1. 程式人生 > >S5PV210(TQ210)學習筆記——觸控式螢幕驅動編寫

S5PV210(TQ210)學習筆記——觸控式螢幕驅動編寫

電阻式觸控式螢幕的驅動比較簡單,可以採用輸入子系統驅動框架來編寫,而電容式觸控式螢幕的驅動程式相對比較複雜,因為電容觸控一般採用I2C引腳才控制,我在自己編寫電容觸控驅動的時候鬱悶了好幾天,當然,並不是因為I2C電容觸控驅動繁瑣,主要是天嵌TQ210的觸控式螢幕驅動程式是以模組方式提供的,並不開發原始碼,也沒有提供觸控的晶片手冊,我曾通過技術諮詢群和電話諮詢的方式諮詢過天嵌相關人士,想跟他們索取觸控協議而不要所謂的觸控驅動程式原始碼,但是,天嵌相關人員以保密協議為由(儘管我完全不相信做LCD屏的商家會不告訴你怎麼用屏)拒絕提供觸控協議。我們不去追究這些無聊的問題,好在天嵌這樣的公司(或者是與其合作開發的觸控式螢幕驅動的公司)還沒有實力自己做晶片,所以,只要找到觸控晶片的型號並根據觸控晶片型號找到對應的手冊,然後就可以自己編寫所謂的電容式觸控式螢幕驅動了。

一 觸控晶片分析

首先,卸下觸控式螢幕的四個螺絲並翻過觸控式螢幕來觀察,可以在在觸控式螢幕排線上看到觸控晶片,仔細觀察晶片型號(如果看不清可以用放大鏡配合手電筒觀看),我們可以看到,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 <linux/module.h>
  2. #include <linux/input.h>
  3. #include <linux/i2c.h>
  4. #include <linux/gpio.h>
  5. #include <linux/delay.h>
  6. #include <linux/input.h>
  7. #include <plat/gpio-cfg.h>
  8. #include <linux/interrupt.h>
  9. conststatic unsigned short normal_address[] = {0x5d, I2C_CLIENT_END};  
  10. static unsigned gt811_rst;  
  11. static unsigned gt811_int;  
  12. staticstruct input_dev *ts_input;  
  13. staticstruct workqueue_struct *wq;  
  14. staticstruct work_struct work;  
  15. staticstruct i2c_client * this_client = NULL;  
  16. static unsigned int status = 0;  
  17. staticint i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)  
  18. {  
  19.     struct i2c_msg msgs[2];  
  20.     int ret=-1;  
  21.     msgs[0].flags=!I2C_M_RD;  
  22.     msgs[0].addr=client->addr;  
  23.     msgs[0].len=2;  
  24.     msgs[0].buf=&buf[0];  
  25.     msgs[1].flags=I2C_M_RD;  
  26.     msgs[1].addr=client->addr;  
  27.     msgs[1].len=len-2;  
  28.     msgs[1].buf=&buf[2];  
  29.     ret=i2c_transfer(client->adapter,msgs, 2);  
  30.     return ret;  
  31. }  
  32. staticint i2c_write_bytes(struct i2c_client *client,uint8_t *data,int len)  
  33. {  
  34.     struct i2c_msg msg;  
  35.     int ret=-1;  
  36.     msg.flags=!I2C_M_RD;  
  37.     msg.addr=client->addr;  
  38.     msg.len=len;  
  39.     msg.buf=data;     
  40.     ret=i2c_transfer(client->adapter,&msg, 1);  
  41.     return ret;  
  42. }  
  43. staticconststruct i2c_device_id ts_id[] = {  
  44.     { "tq210-ts", 0 },  
  45.     { }  
  46. };  
  47. staticint ts_init_panel(struct i2c_client *client){  
  48.     short ret=-1;  
  49.     uint8_t config_info[] = {  
  50.         0x06,0xA2,  
  51.         0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,  
  52.         0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,  
  53.         0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,  
  54.         0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,  
  55.         0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,  
  56.         0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,  
  57.         0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01     
  58.     };  
  59.     config_info[62] = 480 >> 8;  
  60.     config_info[61] = 480 & 0xff;  
  61.     config_info[64] = 800 >> 8;  
  62.     config_info[63] = 800 & 0xff;  
  63.     ret = i2c_write_bytes(client, config_info, sizeof(config_info)/sizeof(config_info[0]));  
  64.     if(ret < 0)  {  
  65.         printk(KERN_ERR "GT811 Send config failed!\n");  
  66.         return ret;   
  67.     }  
  68.     return 0;  
  69. }  
  70. static irqreturn_t gt811_int_handler(int irq, void *devid){  
  71.     disable_irq_nosync(this_client->irq);  
  72.     queue_work(wq, &work);  
  73.     return IRQ_RETVAL(IRQ_HANDLED);  
  74. }  
  75. staticvoid ts_work_func(struct work_struct* work){  
  76.     int ret;  
  77.     unsigned char point_data[19] = {0x07, 0x21, 0};  
  78.     unsigned short input_x = 0;  
  79.     unsigned short input_y = 0;  
  80.     unsigned short input_p = 0;  
  81.     ret=i2c_read_bytes(this_client, point_data, sizeof(point_data)/sizeof(point_data[0]));  
  82.     if(ret <= 0){  
  83.         printk("Failed\n");  
  84.         return;  
  85.     }  
  86.     if(point_data[2]&0x1){  
  87.         status = 1;  
  88.         input_y = 479-((point_data[4]<<8)|point_data[5]);  
  89.         input_x = 799-((point_data[6]<<8)|point_data[7]);  
  90.         input_p = point_data[8];  
  91.         printk("stat: %d, x: %d, y: %d, p: %d\n", point_data[2], input_x, input_y,  
  92.             input_p);  
  93.     }  
  94.     elseif(status){  
  95.         status = 0;  
  96.         printk("up\n");  
  97.     }  
  98.     enable_irq(this_client->irq);  
  99. }  
  100. staticint ts_probe(struct i2c_client *client, conststruct i2c_device_id *id){  
  101.     int retry, ret;  
  102.     char test_data;  
  103.     printk("ts_probe\n");  
  104.     test_data = 0;  
  105.     gt811_rst = S5PV210_GPD0(3);  
  106.     gt811_int = S5PV210_GPH1(6);  
  107.     gpio_request(gt811_rst, "reset"

    相關推薦

    no