新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > AM335x(TQ335x)學習筆記——觸摸屏驅動編寫

        AM335x(TQ335x)學習筆記——觸摸屏驅動編寫

        作者: 時間:2016-11-28 來源:網絡 收藏
        前面幾篇文章已經通過配置DTS的方式完成了多個驅動的移植,接下來我們解決TQ335x的觸摸驅動問題。由于種種原因,TQ335x的觸摸屏驅動是以模塊方式提供的,且Linux官方內核中也沒有帶該觸摸屏的驅動源碼,單純的配置DTS是無法完成TQ335x的觸摸驅動移植工作的,因此,本文參考內核中原有的pixcir_i2c_ts驅動編寫TQ335x的觸摸屏(TN92)驅動。

        在之前移植TQ210時,我已經編寫過TQ210的觸摸屏驅動,我的TQ335x還是使用的TQ210的屏,因此,難度不是很大。這里需要說明一點,在TQ210驅動移植時對多點觸摸協議的理解還不夠深入,當時編寫的驅動單點觸摸是可以正常使用的,但是多點觸摸不對(這次編寫TQ335x的觸摸驅動是才意識到的)。但是編寫的TQ210驅動多點觸摸實際上使用的多點觸摸的A協議,但是用錯了一些地方,本文基于TQ335x的重新編寫的觸摸驅動是按照多點觸摸B協議編寫,使用tslib測試正常,文章末尾有效果圖。

        本文引用地址:http://www.104case.com/article/201611/322822.htm

        TN92觸摸屏使用的觸控芯片是GT811,下面我們來分析下觸摸屏驅動的編寫。

        (1) 查看原理圖

        從觸摸屏原理圖中可以看到,GT811與開發板相連的引腳有四條,分別是SDA、SDL、INT和RESET。其中,I2C_SDA和I2C_SDL是連接到AM335x的I2C1端口上的,用來與SoC通信;INT引腳是連接在GPIO1的27號引腳上的,在檢測到觸摸時GT811通過該引腳向SoC發起中斷請求;RESET引腳接到SoC的GPIO1的26號引腳上的,是用來接收SoC復位操作,對于本文,SoC就是AM335x。

        其中,GT811與SoC的管腳連接信息可以從底板原理圖中找到,SDA和SCL的我就不往外貼了,INT和RESET的連接關系如下:

        YP連接到了GT811的RESET腳上,然后通過短路帽與GPIO1_26鏈接,YM連接到GT811的INT腳上,通過短路帽與GPIO1_27鏈接,因此,需要將GPIO1_27配置為終端輸入引腳,GPIO1_26配置為輸出引腳。此外,查看GT811的芯片手冊可獲得INT和RESET的操作信息:

        1. 1.GT811檢測到觸摸時會拉低中斷引腳,因此,GPIO1_27需要配置為下降沿觸發。
        2. 2.GT811的RESET腳為低電平有效,因此,上電時需要拉低RESET引腳。
        3. 3.GT811的RESET引腳自帶上拉,因此,使用GPIO1_26將GT811的RESET拉低復位后切換為懸浮輸入太即可。
        了解這些信息后我們就可以開始分析驅動結構了。

        (2) DTS配置Platform信息

        通過前面的分析,我們知道需要配置AM335x的四條引腳才能使GT811正常工作。其中,GT811通過I2C接口連接到AM335x的I2C1上,因此,需要配置AM335x的I2C1的兩條引腳為I2C功能;GPIO1_27需要配置為中斷輸入、下降沿觸發,中斷號也可以確定下來了,就是GPIO1的27號角(內核能將引腳轉換為中斷號);最后就是RESET腳,驅動初始化GT811時需要操作RESET引腳,且GT811為拉低復位,故可將GPIO1的26角設為輸出電平狀態。通過前面幾篇文章的學習,我們知道DTS可以配置pinmux,然后分析內核自帶的DTS文件可以,DTS也可以將連接信息傳遞給內核。經過分析及參考,我最TQ335x.dts文件做了如下修改:

        Step1. 檢查I2C引腳的pinmux配置

        查找i2c1可以找到i2c1節點,該節點的pinctrl-0只想的phandler對i2c1的兩個引腳進行了相關的配置,因此,不需任何修改。

        Step2. 配置INT和RESET引腳

        在am33xx_pinmux節點內添加引腳配置信息,具體內容如下:

        1. gt811_ts_pins:gt811_ts_pins{
        2. pinctrl-single,pins=<
        3. 0x68(PIN_INPUT_PULLUP|MUX_MODE7)
        4. 0x6c(PIN_INPUT_PULLUP|MUX_MODE7)
        5. >;
        6. };
        Step3. 在i2c1節點內添加GT811設備信息

        GT811的設備節點內需要提供以下信息,i2c設備地址、pinmux配置、中斷信息、屏幕大小等,具體如下(這里就不細說了,有什么不清楚的可以留言討論)。

        1. gt811_ts@5d{
        2. compatible="gt811,gt811_ts";
        3. pinctrl-names="default";
        4. pinctrl-0=<>811_ts_pins>;
        5. reg=<0x5d>;
        6. interrupt-parent=<&gpio1>;
        7. interrupts=<272>;
        8. gpios=<&gpio1260>;
        9. touchscreen-size-x=<800>;
        10. touchscreen-size-y=<480>;
        11. touchscreen-swap=<1>;
        12. touchscreen-revert-x=<1>;
        13. touchscreen-revert-y=<1>;
        14. };
        至此,DTS的配置工作就完成了,下面就是GT811的驅動編寫。
        (3)驅動編寫

        驅動編寫根之前TQ210相比,沒有多少變化,都是采用的新式I2C設備驅動架構,重要的區別在于支持了多點觸摸,驅動的詳細分析我就不多說了,具體可以參考韋東山老師的視頻教程(絕對物有所值)。下面是GT811的多點觸摸驅動源碼。從GT811設備節點中獲取坐標信息的部分我直接貼出來了,完整的代碼還是請到資源里下載,還是有點貴哈,不過這個驅動可以直接拿去使用了,不需要任何修改。下面是不完整的代碼,可以打印出觸摸點坐標,該代碼已經把本驅動的核心的部分都寫出來了。其實很多朋友不需要下載源碼就可以補充完善這個驅動了,而且我真心的希望閱讀本文的朋友不需要下載源碼就能自己寫出觸摸驅動。

        1. #include
        2. #include
        3. #include
        4. #include
        5. #include
        6. #include
        7. #include
        8. #include
        9. #include
        10. #include
        11. #include
        12. structgt811_ts_platdata
        13. {
        14. u32size_x;
        15. u32size_y;
        16. u32size_p;
        17. u32swap;
        18. u32revert_x;
        19. u32revert_y;
        20. u32reset_pin;
        21. u32interrupt_pin;
        22. u32ponits_max;
        23. structi2c_client*client;
        24. structinput_dev*input;
        25. structwork_structwork;
        26. };
        27. staticconststructof_device_idgt811_ts_of_match[]={
        28. {.compatible="gt811,gt811_ts",.data=NULL},
        29. {}
        30. };
        31. staticinti2c_write_bytes(structi2c_client*client,uint8_t*data,intlen){
        32. structi2c_msgmsg;
        33. msg.flags=!I2C_M_RD;
        34. msg.addr=client->addr;
        35. msg.len=len;
        36. msg.buf=data;
        37. returni2c_transfer(client->adapter,&msg,1);
        38. }
        39. staticinti2c_read_bytes(structi2c_client*client,uint8_t*buf,intlen){
        40. structi2c_msgmsgs[2];
        41. msgs[0].flags=!I2C_M_RD;
        42. msgs[0].addr=client->addr;
        43. msgs[0].len=2;
        44. msgs[0].buf=&buf[0];
        45. msgs[1].flags=I2C_M_RD;
        46. msgs[1].addr=client->addr;
        47. msgs[1].len=len-2;
        48. msgs[1].buf=&buf[2];
        49. returni2c_transfer(client->adapter,msgs,2);
        50. }
        51. staticvoidgt811_ts_handler(structwork_struct*work)
        52. {
        53. structgt811_ts_platdata*pdata=container_of(work,structgt811_ts_platdata,work);
        54. structdevice*dev=&pdata->client->dev;
        55. uint8_tbuffer[36]={0x07,0x21,0};
        56. uint8_tcount,index,flags,position;
        57. intx,y;
        58. buffer[0]=0x0f;
        59. buffer[1]=0xff;
        60. if(i2c_write_bytes(pdata->client,buffer,2)<0){
        61. dev_err(dev,"Failedtowritewakeupmessage.");
        62. gotoreenable_irq;
        63. }
        64. buffer[0]=0x07;
        65. buffer[1]=0x21;
        66. if(i2c_read_bytes(pdata->client,buffer,sizeof(buffer))<0){
        67. dev_err(dev,"Failedtoreadtouchmessage.");
        68. gotoreenable_irq;
        69. }
        70. buffer[0]=0x80;
        71. buffer[1]=0x00;
        72. if(i2c_write_bytes(pdata->client,buffer,2)<0){
        73. dev_err(dev,"Failedtowritesleepmessage.");
        74. gotoreenable_irq;
        75. }
        76. buffer[25]=buffer[19];
        77. buffer[19]=0;
        78. flags=buffer[2]&0x1f;
        79. while(flags){
        80. if(!(flags&0x1)){
        81. continue;
        82. }
        83. if(index<3){
        84. position=4+index*5;
        85. }
        86. else{
        87. position=25+(index-3)*5;
        88. }
        89. x=(buffer[position]<<8)|buffer[position+1];
        90. y=(buffer[position+2]<<8)|buffer[position+3];
        91. if(pdata->swap){
        92. swap(x,y);
        93. }
        94. if(pdata->revert_x){
        95. x=pdata->size_x-x;
        96. }
        97. if(pdata->revert_y){
        98. y=pdata->size_y-y;
        99. }
        100. printk("point:(x:%03d,y:%03d)",x,y);
        101. }
        102. //組織檢測出來的觸摸點信息上報到輸入子系統節點即可
        103. reenable_irq:
        104. enable_irq(pdata->client->irq);
        105. }
        106. staticirqreturn_tgt811_ts_isr(intirq,void*dev_id)
        107. {
        108. structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)dev_id;
        109. disable_irq_nosync(pdata->client->irq);
        110. schedule_work(&pdata->work);
        111. returnIRQ_HANDLED;
        112. }
        113. staticintgt811_ts_initilize(structi2c_client*client)
        114. {
        115. structdevice*dev=&client->dev;
        116. structgt811_ts_platdata*pdata=(structgt811_ts_platdata*)i2c_get_clientdata(client);
        117. intstatus=0,count=0;
        118. uint8_tversion[4]={0x7,0x17,0};
        119. uint8_tconfig[]={
        120. 0x06,0xA2,
        121. 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,
        122. 0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,
        123. 0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,
        124. 0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,
        125. 0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,
        126. 0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,
        127. 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01
        128. };
        129. config[62]=480>>8;
        130. config[61]=480&0xff;
        131. config[64]=800>>8;
        132. config[63]=800&0xff;
        133. if(!gpio_is_valid(pdata->reset_pin)){
        134. dev_err(dev,"Theresetpinnumberisinvalid.");
        135. return-EINVAL;
        136. }
        137. count=3;
        138. while(count--){
        139. gpio_direction_output(pdata->reset_pin,0);
        140. msleep(10);
        141. gpio_direction_output(pdata->reset_pin,1);
        142. msleep(100);
        143. if(i2c_read_bytes(client,version,sizeof(version))<0){
        144. dev_err(dev,"FailedtogettheversionofGT811,tryagain...");
        145. status=-ENODEV;
        146. }
        147. else{
        148. dev_info(dev,"Gt811detected,version(%04x)...",(version[2]<<8)|version[3]);
        149. status=0;
        150. break;
        151. }
        152. }

        153. 上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 浦城县| 安乡县| 共和县| 江阴市| 兴安盟| 简阳市| 鄂托克前旗| 交城县| 应城市| 蒙自县| 中西区| 满城县| 旺苍县| 弥勒县| 盐津县| 勐海县| 盐边县| 东源县| 遂平县| 宁河县| 台江县| 万盛区| 崇义县| 昔阳县| 壤塘县| 安阳市| 桦川县| 明星| 丘北县| 二连浩特市| 马公市| 饶河县| 景宁| 平度市| 彰化县| 开封市| 永平县| 秦安县| 榆树市| 鄂尔多斯市| 珠海市|