【正点原子STM32连载】第三十七章 触摸屏实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
1)實驗平臺:正點原子MiniPro H750開發板
2)平臺購買地址:https://detail.tmall.com/item.htm?id=677017430560
3)全套實驗源碼+手冊+視頻下載地址:http://www.openedv.com/thread-336836-1-1.html
4)對正點原子STM32感興趣的同學可以加群討論:879133275
第三十七章 觸摸屏實驗
本章,我們將介紹如何使用STM32H750來驅動觸摸屏,STM32H750本身并沒有觸摸屏控制器,但是它支持觸摸屏,可以通過外接帶觸摸屏的LCD模塊(比如正點原子TFTLCD模塊),來實現觸摸屏控制。在本章中,我們將向大家介紹STM32控制正點原子TFTLCD模塊(包括電阻觸摸與電容觸摸),實現觸摸屏驅動,最終實現一個手寫板的功能。
本章分為如下幾個小節:
37.1 觸摸屏簡介
37.2 硬件設計
37.3 程序設計
37.4 下載驗證
37.1 觸摸屏簡介
觸摸屏是在顯示屏的基礎上,在屏幕或屏幕上方分布一層與屏幕大小相近的傳感器形成的組合器件。觸摸和顯示功能由軟件控制,可以獨立也可以組合實現,用戶可以通過偵測傳感器的觸點再配合相應的軟件實現觸摸效果。目前最常用的觸摸屏有兩種:電阻式觸摸屏與電容式觸摸屏。下面,我們來分別介紹。
37.1.1 電阻式觸摸屏
正點原子2.4/2.8/3.5寸TFTLCD模塊自帶的觸摸屏都屬于電阻式觸摸屏,下面簡單介紹下電阻式觸摸屏的原理。
電阻觸摸屏的主要部分是一塊與顯示器表面非常貼合的電阻薄膜屏,這是一種多層的復合薄膜,具體結構如下圖37.1.1.1所示。
圖37.1.1.1 電阻觸摸屏多層結構圖
表面硬涂層起保護作用,主要是一層外表面硬化處理、光滑防擦的塑料層。玻璃
底層用于支撐上面的結構,主要是玻璃或者塑料平板。透明隔離點用來分離開外層ITO和內層ITO。ITO層是觸摸屏關鍵結構,是涂有銦錫金屬氧化物的導電層。還有一個結構上圖沒有標出,就是PET層。PET層是聚酯薄膜,處于外層ITO和表面硬涂層之間,很薄很有彈性,觸摸時向下彎曲,使得ITO層接觸。
當手指觸摸屏幕時,兩個ITO層在觸摸點位置就有接觸,電阻發生變化,在X和Y兩個方向上產生電信號,然后送到觸摸屏控制器,具體情況如下圖37.1.1.2所示。觸摸屏控制器偵測到這一接觸并計算出X和Y方向上的AD值,簡單來講,電阻觸摸屏將觸摸點(X,Y)的物理位置轉換為代表X坐標和Y坐標的電壓值。單片機與觸摸屏控制器進行通信獲取到AD值,通過一定比例關系運算,獲得X和Y軸坐標值。
圖37.1.1.2 電阻式觸摸屏的觸點坐標結構
電阻觸摸屏的優點:精度高、價格便宜、抗干擾能力強、穩定性好。
電阻觸摸屏的缺點:容易被劃傷、透光性不太好、不支持多點觸摸。
從以上介紹可知,觸摸屏都需要一個AD轉換器,一般來說是需要一個控制器的。正點原子 TFTLCD模塊選擇的是四線電阻式觸摸屏,這種觸摸屏的控制芯片有很多,包括:ADS7543、ADS7846、TSC2046、XPT2046和HR2046等。這幾款芯片的驅動基本上是一樣的,也就是你只要寫出了XPT2046的驅動,這個驅動對其他幾個芯片也是有效的。而且封裝也有一樣的,完全PIN-TO-PIN兼容。所以在替換起來,很方便。
正點原子TFTLCD模塊自帶的觸摸屏控制芯片為XPT2046或HR2046。這里以XPT2046作為介紹。XPT2046是一款4導線制觸摸屏控制器,使用的是SPI通信接口,內含12位分辨率125KHz轉換速率逐步逼近型A/D轉換器。XPT2046支持從1.5V到5.25V的低電壓I/O接口。XPT2046能通過執行兩次A/D轉換(一次獲取X位置,一次獲取Y位置)查出被按的屏幕位置,除此之外,還可以測量加在觸摸屏上的壓力。內部自帶2.5V參考電壓可以作為輔助輸入、溫度測量和電池監測模式之用,電池監測的電壓范圍可以從0V到6V。XPT2046片內集成有一個溫度傳感器。在2.7V的典型工作狀態下,關閉參考電壓,功耗可小于0.75mW。
XPT2046的驅動方法也是很簡單,主要看懂XPT2046通信時序圖,如下圖37.1.1.3所示。
圖37.1.1.3 XPT2046通信時序圖
依照時序圖,就可以很好寫出這個通信代碼,上圖具體過程:拉低片選,選中器件發送命令字清除BUSY讀取16位數據(高12位數據有效即轉換的AD值)拉高片選,結束操作。這里的難點就是需要搞清楚命令字該發送什么?只要搞清楚發送什么數值,就可以獲取到AD值。命令字的詳情如下圖37.1.1.4所示:
圖37.1.1.4 命令字詳情圖
位7,開始位,置1即可。位3,為了提供精度,MODE位清0選擇12位分辨率。位2,是進行工作模式選擇,為了達到最佳性能,首選差分工作模式即該位清0即可。位1-0是功耗相關的,直接清0即可。而位6-4的值要取決于工作模式,在確定了差分功能模式后,通道選擇位也確定了,如圖37.1.1.5所示。
圖37.1.1.5 差分模式輸入配置圖(SER/DFR=0)
從上圖,就可以知道:當我們需要檢測Y軸位置時,A2A1A0賦值為001;檢測X軸位置時,A2A1A0賦值為101。結合前面對其他位的賦值,在X,Y方向與屏幕相同的情況下,命令字0xD0就是讀取X坐標AD值,0x90就是讀取Y坐標的AD值。假如X,Y方向與屏幕相反,0x90就是讀取X坐標的AD值,而0xD0就是讀取Y坐標的AD值。
關于這個芯片其他的功能,也可以參考芯片的datasheet。
電阻式觸摸屏就介紹到這里。
37.1.2 電容式觸摸屏
現在幾乎所有智能手機,包括平板電腦都是采用電容屏作為觸摸屏,電容屏是利用人體感應進行觸點檢測控制,不需要直接接觸或只需要輕微接觸,通過檢測感應電流來定位觸摸坐標。正點原子4.3/7寸TFTLCD模塊自帶的觸摸屏采用的是電容式觸摸屏,下面簡單介紹下電容式觸摸屏的原理。
電容式觸摸屏主要分為兩種:
1、表面電容式電容觸摸屏。
表面電容式觸摸屏技術是利用ITO(銦錫氧化物,是一種透明的導電材料)導電膜,通過電場感應方式感測屏幕表面的觸摸行為進行。但是表面電容式觸摸屏有一些局限性,它只能識別一個手指或者一次觸摸。
2、投射式電容觸摸屏。
投射電容式觸摸屏是傳感器利用觸摸屏電極發射出靜電場線。一般用于投射電容傳感技術的電容類型有兩種:自我電容和交互電容。
自我電容又稱絕對電容,是最廣為采用的一種方法,自我電容通常是指掃描電極與地構成的電容。在玻璃表面有用ITO制成的橫向與縱向的掃描電極,這些電極和地之間就構成一個電容的兩極。當用手或觸摸筆觸摸的時候就會并聯一個電容到電路中去,從而使在該條掃描線上的總體的電容量有所改變。在掃描的時候,控制IC依次掃描縱向和橫向電極,并根據掃描前后的電容變化來確定觸摸點坐標位置。筆記本電腦觸摸輸入板就是采用的這種方式,筆記本電腦的輸入板采用XY的傳感電極陣列形成一個傳感格子,當手指靠近觸摸輸入板時,在手指和傳感電極之間產生一個小量電荷。采用特定的運算法則處理來自行、列傳感器的信號來確定手指的位置。
交互電容又叫做跨越電容,它是在玻璃表面的橫向和縱向的ITO電極的交叉處形成電容。交互電容的掃描方式就是掃描每個交叉處的電容變化,來判定觸摸點的位置。當觸摸的時候就會影響到相鄰電極的耦合,從而改變交叉處的電容量,交互電容的掃面方法可以偵測到每個交叉點的電容值和觸摸后電容變化,因而它需要的掃描時間與自我電容的掃描方式相比要長一些,需要掃描檢測XY根電極。目前智能手機/平板電腦等的觸摸屏,都是采用交互電容技術。
正點原子所選擇的電容觸摸屏,也是采用的是投射式電容屏(交互電容類型),所以后面僅以投射式電容屏作為介紹。
投射式電容觸摸屏采用縱橫兩列電極組成感應矩陣,來感應觸摸。以兩個交叉的電極矩陣,即:X軸電極和Y軸電極,來檢測每一格感應單元的電容變化,如圖37.1.2.1所示:
圖37.1.2.1 投射式電容屏電極矩陣示意圖
示意圖中的電極,實際是透明的,這里是為了方便大家理解。圖中,X、Y軸的透明電極電容屏的精度、分辨率與X、Y軸的通道數有關,通道數越多,精度越高。以上就是電容觸摸屏的基本原理,接下來看看電容觸摸屏的優缺點:
電容觸摸屏的優點:手感好、無需校準、支持多點觸摸、透光性好。
電容觸摸屏的缺點:成本高、精度不高、抗干擾能力差。
這里特別提醒大家電容觸摸屏對工作環境的要求是比較高的,在潮濕、多塵、高低溫環境下面,都是不適合使用電容屏的。
電容觸摸屏一般都需要一個驅動IC來檢測電容觸摸,正點原子的電容觸摸屏使用的是IIC接口輸出觸摸數據的觸摸芯片。正點原子7’TFTLCD模塊的電容觸摸屏,采用的是15*10的驅動結構(10個感應通道,15個驅動通道),采用的是GT911/FT5206作為驅動IC。正點原子4.3’TFTLCD模塊采用的驅動IC是:GT9xxx(GT9147/GT917S/GT911/GT1151/GT9271),不同型號感應通道和驅動通道數量都不一樣,詳看數據手冊,但是這些驅動IC驅動方式都類似,這里我們以GT9147為例給大家做介紹,其他的大家參考著學習即可。
GT9147與MCU通過4根線連接:SDA、SCL、RST和INT。GT9147的IIC地址,可以是0X14或者0X5D,當復位結束后的5ms內,如果INT是高電平,則使用0X14作為地址,否則使用0X5D作為地址,具體的設置過程,請看:GT9147數據手冊.pdf這個文檔。本章我們使用0X14作為器件地址(不含最低位,換算成讀寫命令則是讀:0X29,寫:0X28),接下來,介紹一下GT9147的幾個重要的寄存器。
1,控制命令寄存器(0X8040)
該寄存器可以寫入不同值,實現不同的控制,我們一般使用0和2這兩個值,寫入2,即可軟復位GT9147。在硬復位之后,一般要往該寄存器寫2,實行軟復位。然后,寫入0,即可正常讀取坐標數據(并且會結束軟復位)。
2,配置寄存器組(0X8047~0X8100)
這里共186個寄存器,用于配置GT9147的各個參數,這些配置一般由廠家提供給我們(一個數組),所以我們只需要將廠家給我們的配置,寫入到這些寄存器里面,即可完成GT9147的配置。由于GT9147可以保存配置信息(可寫入內部FLASH,從而不需要每次上電都更新配置),我們有幾點注意的地方提醒大家:1,0X8047寄存器用于指示配置文件版本號,程序寫入的版本號,必須大于等于GT9147本地保存的版本號,才可以更新配置。2,0X80FF寄存器用于存儲校驗和,使得0X8047~0X80FF之間所有數據之和為0。3,0X8100用于控制是否將配置保存在本地,寫0,則不保存配置,寫1則保存配置。
3,產品ID寄存器(0X8140~0X8143)
這里總共由4個寄存器組成,用于保存產品ID,對于GT9147,這4個寄存器讀出來就是:9,1,4,7四個字符(ASCII碼格式)。因此,我們可以通過這4個寄存器的值,來判斷驅動IC的型號,以便執行不同的初始化。
4,狀態寄存器(0X814E)
該寄存器各位描述如表表37.1.2.1所示:
表 37.1.2.1 狀態寄存器各位描述
這里,我們僅關心最高位和最低4位,最高位用于表示buffer狀態,如果有數據(坐標/按鍵),buffer就會是1,最低4位用于表示有效觸點的個數,范圍是:0~5,0,表示沒有觸摸,5表示有5點觸摸。最后,該寄存器在每次讀取后,如果bit7有效,則必須寫0,清除這個位,否則不會輸出下一次數據!!這個要特別注意!!!
5,坐標數據寄存器(共30個)
這里共分成5組(5個點),每組6個寄存器存儲數據,以觸點1的坐標數據寄存器組為例,如表37.1.2.2所示:
表37.1.2.2 觸點1坐標寄存器組描述
我們一般只用到觸點的x,y坐標,所以只需要讀取0X81500X8153的數據,組合即可得到觸點坐標。其他4組分別是:0X8158、0X8160、0X8168和0X8170等開頭的16個寄存器組成,分別針對觸點24的坐標。同樣GT9147也支持寄存器地址自增,我們只需要發送寄存器組的首地址,然后連續讀取即可,GT9147會自動地址自增,從而提高讀取速度。
GT9147相關寄存器的介紹就介紹到這里,更詳細的資料,請參考:GT9147編程指南.pdf 這個文檔。
GT9147只需要經過簡單的初始化就可以正常使用了,初始化流程:硬復位延時10ms結束硬復位設置IIC地址延時100ms軟復位更新配置(需要時)結束軟復位。此時GT9147即可正常使用了。然后,我們不停的查詢0X814E寄存器,判斷是否有有效觸點,如果有,則讀取坐標數據寄存器,得到觸點坐標。特別注意,如果0X814E讀到的值最高位為1,就必須對該位寫0,否則無法讀到下一次坐標數據。
電容式觸摸屏部分,就介紹到這里。
37.1.3 觸摸控制原理
前面已經簡單地介紹了電阻屏和電容屏的原理,并且知道了不同類型的觸摸屏其實是屏幕+觸摸傳感器組成。那么這里就會有兩組相互獨立的參數:屏幕坐標和觸摸坐標。要實現觸摸功能,就是要把觸摸點和屏幕坐標對應起來。
我們以LCD顯示屏為例,我們知道屏幕的掃描方向是可以編程設定的,而觸摸點,在觸摸傳感器安裝好后,AD值的變化向方向則是固定的,我們以最常見的屏幕坐標方向:先從左到右,再從上到下掃描為例,此時,屏幕坐標和觸點AD的坐標有類似的規律:從坐標原點出發,水平方向屏幕坐標增加時,AD值的X方向也增加;屏幕坐標的Y方向坐標增加,AD值的Y方向也增加;坐標減少時對應的關系也類似,可以用圖37.1.3.1的示意圖來表示這種關系:
圖37.1.3.1 屏幕坐標和觸摸坐標的一種對應關系
這里再來引入兩個概念,物理坐標和邏輯坐標。物理坐標指觸摸屏上點的實際位置,通常以液晶上點的個數來度量。邏輯坐標指這點被觸摸時A/D轉換后的坐標值。仍以圖37.1.3.1為例,我們假定液晶最左上角為坐標軸原點A,在液晶上任取一點B(實際人手比像素點大得多,一次按下會有多個觸點,此處取十字線交叉中心),B在X方向與A相距100個點,在Y方向與A距離200個點,則這點的物理坐標B為(100,200)。如果我們觸摸這一點時得到的X向A/D轉換值為200,Y向A/D轉換值為400,則這點的邏輯坐標B’為(200,400)。
需要特別說明的是,正點原子的電容屏的參數已經在出廠時由廠家調好,所以無需進行校準,而且可以直接讀到轉換后的觸點坐標;對于電阻屏,請大家理解并熟記物理坐標和邏輯坐標邏輯上的對應關系,我們后面編程需要用到。
37.2 硬件設計
正點原子的觸摸屏種類很多,并且設計了規格相對統一的接口。根據屏幕的種類不同,設置了相應的硬件ID(正點原子自編ID),可以通過軟件判斷觸摸屏的種類。
本章實驗功能簡介:開機的時候先初始化LCD,讀取LCD ID,隨后,根據LCD ID判斷是電阻觸摸屏還是電容觸摸屏,如果是電阻觸摸屏,則先讀取24C02的數據判斷觸摸屏是否已經校準過,如果沒有校準,則執行校準程序,校準過后再進入電阻觸摸屏測試程序,如果已經校準了,就直接進入電阻觸摸屏測試程序。
如果是4.3寸電容觸摸屏,則執行GT9xxx的初始化代碼;如果是7寸電容觸摸屏(僅支持新款7寸屏,使用SSD1963+FT5206方案),則執行FT5206的初始化代碼,在初始化電容觸摸屏完成后,進入電容觸摸屏測試程序(電容觸摸屏無需校準!!)。
電阻觸摸屏測試程序和電容觸摸屏測試程序基本一樣,只是電容觸摸屏支持最多5點同時觸摸,電阻觸摸屏只支持一點觸摸,其他一模一樣。測試界面的右上角會有一個清空的操作區域(RST),點擊這個地方就會將輸入全部清除,恢復白板狀態。使用電阻觸摸屏的時候,可以通過按KEY0來實現強制觸摸屏校準,只要按下KEY0就會進入強制校準程序。
1)RGB燈
RED :LED0 - PB4
2)獨立按鍵
KEY0 - PA1
3)EEPROM AT24C02
4)正點原子2.8/3.5/4.3/7/10寸TFTLCD模塊(僅限MCU屏,16位8080并口驅動)
5)串口1(PA9/PA10連接在板載USB轉串口芯片CH340上面)
LCD模塊的觸摸屏(電阻觸摸屏)總共有5根線與STM32H750連接,連接電路圖如下圖所示:
圖37.2.1 觸摸屏與STM32H750的連接圖
從圖中可以看出,T_MISO、T_PEN、T_CS、T_MOSI和T_SCK分別連接在STM32H750的:PD6、PB1、PC5、PB3和PB0上。
如果是電容式觸摸屏,我們的接口和電阻式觸摸屏一樣,只是沒有用到五根線了,而是四根線,分別是:T_PEN(CT_INT)、T_CS(CT_RST)、T_CLK(CT_SCL)和T_MOSI(CT_SDA)。其中:CT_INT、CT_RST、CT_SCL和CT_SDA分別是GT9147/FT5206的:中斷輸出信號、復位信號,IIC的SCL和SDA信號。這里,我們用查詢的方式讀取GT9147/FT5206的數據,對于FT5206沒有用到中斷信號(CT_INT),所以同STM32H750的連接,最少只需要3根線即可,不過GT9147還需要用到CT_INT做IIC地址設定,所以需要4根線連接。
37.3 程序設計
37.3.1 HAL庫驅動
觸摸芯片我們使用到的是IIC和SPI的驅動,這部分的時序分析可以參考之前IIC/SPI的章節,我們直接使用的是軟件模擬的方式,所以只需要使用HAL庫的驅動的GPIO操作部分。
觸摸IC初始化步驟
1)初始化通信接口與其IO(使能時鐘、配置GPIO工作模式)
觸摸IC用到的GPIO口,主要是PD6、PB1、PC5、PB3和PB0,因為都是用軟件模擬的方式,因此在這里我們只需使能GPIOB、GPIOC和GPIOD時鐘即可。參考代碼如下:
__HAL_RCC_GPIOB_CLK_ENABLE(); /* 使能GPIOB時鐘 /
__HAL_RCC_GPIOC_CLK_ENABLE(); / 使能GPIOC時鐘 /
__HAL_RCC_GPIOD_CLK_ENABLE(); / 使能GPIOD時鐘 */
GPIO模式設置通過調用HAL_GPIO_Init函數實現,詳見本例程源碼。
2)編寫通信協議基礎讀寫函數
通過參考時序圖,在IIC驅動或SPI驅動基礎上,編寫基礎讀寫函數。讀寫函數均以一字節數據進行操作。
3)參考觸摸IC時序圖,編寫觸摸IC讀寫驅動函數
根據觸摸IC的讀寫時序進行編寫觸摸IC的讀寫函數,詳見本例程源碼。
4)編寫坐標獲取函數(電阻觸摸屏和電容觸摸屏)
查閱數據手冊獲得命令詞(電阻觸摸屏)/寄存器(電容觸摸屏),通過讀寫函數獲取坐標數據,詳見本例程源碼。
37.3.2 程序流程圖
圖37.3.2.1 觸摸屏實驗流程圖
37.3.3 程序解析
這里我們只講解核心代碼,詳細的源碼請大家參考光盤本實驗對應源碼。TOUCH驅動源碼包括八個文件:ctiic.c、ctiic.h 、ft5206.c、ft5206.h、gt9xxx.c、gt9xxx.h、touch.c和touch.h。
由于正點原子的TFTLCD的型號很多,觸摸控制這部分驅動代碼根據不同屏幕搭載的觸摸芯片驅動而有不同,在我們的屏幕上使用的是LCD ID來幫助軟件上區分。為了解決多種驅動芯片的問題,我們設計了touch.c/touch.h這兩個文件統一管理各類型的驅動。不同的驅動芯片類型可以在touch.c中集中添加,并通過touch.c中的接口統一調用,不同的觸摸芯片各自編寫獨立的.c/.h文件,需要時被touch.c調用。電阻觸摸屏相關代碼也在touch.c中實現。
因為需要支持的觸摸驅動比較多,為了方便管理和添加新的驅動,我們用touch.c文件來統一管理這些觸摸驅動,然后針對各類觸摸芯片編寫獨立的驅動。為了方便管理觸摸,我們在touch.h中定義一個用于管理觸摸信息的結構體類型,具體代碼如下:
這里我們定義了函數指針,只要把相對應的觸摸芯片的函數指針賦值給它,就可以通過這個通用接口很方便調用不同芯片的函數接口。正點原子不同的觸摸屏區別如下:
1、在使用4.3寸屏、10.1寸屏電容屏時,使用的是匯頂科技的GT9xxx系列觸摸屏驅動IC,這是一個IIC接口的驅動芯片,我們要編寫gt9xxx系列芯片的初始化程序,并編寫一個坐標掃描程序,這里我們先預留這兩個接口分別為gt9xxx_init()和gt9xxx_scan(),在gt9xxx.c文件中再專門實現這兩個驅動,標記使用的為電容屏;
2、類似地,在使用SSD1963 7寸屏、7寸800480/1024600 RGB屏時,我們的屏幕搭載的觸摸驅動芯片是ft5206/GT911,FT5206觸摸IC預留這兩個接口分別為ft5206_init()和ft5206_scan(),在ft5206.c文件中再專門實現這兩個驅動,標記使用的為電容屏;GT911也是調用gtxxx_init()和gt9xxx_scan()接口。
3、當為其它ID時,默認為電阻屏,而電阻屏默認使用的是SPI接口的XPT2046芯片。由于電阻屏存在線性誤差,所以在使用前需要進行校準,這也是為什么在前面的結構體類型中存在關于校準參數的成員。為了避免每次都要進行校準的麻煩,所以會使用AT24C02來存儲校準成功后的數據。如何進行校準也會在后面進行講解。作為電阻屏,它也有一個掃描坐標函數即tp_scan()。
(*init)(void)這個結構體函數指針,默認指向tp_init的,而在tp_init里對觸摸屏進行初始化并對(*scan)(uint8_t)函數指針根據觸摸芯片類型重新做了指向。在這里簡單看一下touch.c的觸摸屏初始化函數tp_init,其代碼如下:
正點原子的電容屏在出廠時已經由廠家較對好參數了,而電阻屏由于工藝和每個屏的線性有所差異,我們需要先對其進行“校準”,我們在下一點補充說明它的實現。
通過上面的觸摸初始化后,我們就可以讀取相關的觸點信息用于顯示編程了,注意到上面還有很多個函數還沒實現,比如讀取坐標和校準,我們在接下來的代碼中將它補充完整。
2. 電阻屏觸摸函數
前面我們介紹過了電阻式觸摸屏的原理,由于電阻屏的驅動代碼都比較類似,我們決定把電阻屏的驅動函數直接添加在touch.c/touch.h中實現。
在touch.c的初始化函數tp_init中,對使用到的SPI接口IO進行了初始化。接下來介紹一下獲取觸摸點在屏幕上坐標的算法:先獲取邏輯坐標(AD值),再轉換成屏幕坐標。
如何獲取邏輯坐標(AD值),在前面已經分析過了,所以這里我們看一下tp_read_ad()函數接口:
這里我們使用的是軟件模擬SPI,遵照時序編寫SPI讀函數接口。而發送命令字是通過寫函數tp_write_byte來實現,詳看源碼。
一次讀取的誤差會很大,我們采用平均值濾波的方法,多次讀取數據并丟棄波動最大的最大和最小值,取余下的平均值。具體可以查看tp_read_xoy函數內部實現。
/* 電阻觸摸驅動芯片 數據采集 濾波用參數 */
有了前述代碼,我們就可以通過tp_read_xoy(uint8_t cmd)接口調取需要的x或者y坐標的AD值了。這里我們加上橫屏或者豎屏的處理代碼,編寫一個可以通過指針一次得到x和y的兩個AD值的接口,代碼如下:
/*** @brief 讀取x, y坐標* @param x,y: 讀取到的坐標值* @retval 無*/ static void tp_read_xy(uint16_t *x, uint16_t *y) {uint16_t xval, yval;if (tp_dev.touchtype & 0X01) /* X,Y方向與屏幕相反 */{xval = tp_read_xoy(0X90); /* 讀取X軸坐標AD值, 并進行方向變換 */yval = tp_read_xoy(0XD0); /* 讀取Y軸坐標AD值 */}else /* X,Y方向與屏幕相同 */{xval = tp_read_xoy(0XD0); /* 讀取X軸坐標AD值 */yval = tp_read_xoy(0X90); /* 讀取Y軸坐標AD值 */}*x = xval;*y = yval; }為了進一步保證參數的精度,我們連續讀兩次觸摸數據并取平均值作為最后的觸摸參數,并對這兩次濾波值平均后再傳給目標存儲區,由于AD的精度為12位,故該函數讀取坐標的值0~4095,tp_read_xy2的代碼如下:
/* 連續兩次讀取X,Y坐標的數據誤差最大允許值 */
根據以上的流程,可以得到電阻屏觸摸點的比較精確的AD信息。每次觸摸屏幕時會對應一組X、Y的AD值,由于坐標的AD值是在X、Y方向都是線性的,很容易想到要把觸摸信息的AD值和屏幕坐標聯系起來,這里需要編寫一個坐標轉換函數,前面在編寫初始化接口時講到的校準函數這時候就派上用場了。
從前面的知識我們就知道觸摸屏的AD的XAD、YAD可以構成一個邏輯平面,LCD屏的屏幕坐標X、Y也是一個邏輯平面,由于存在誤差,這兩個平面并不重合,校準的作用就是要將邏輯平面映射到物理平面上,即得到觸點在液晶屏上的位置坐標。校準算法的中心思想也就是要建立這樣一個映射函數現有的校準算法大多是基于線性校準,即首先假定物理平面和邏輯平面之間的誤差是線性誤差,由旋轉和偏移形成。
常用的電阻式觸摸屏校正方法有兩點校準法和三點校準法。本文這里介紹的是結合了不同的電阻式觸摸屏校正法的優化算法:五點校正法。其中主要的原理是使用4點校正法的比例運算以及三點校正法的基準點運算。五點校正法優勢在于可以更加精確的計算出X和Y方向的比例縮放系數,同時提供了中心基準點,對于一些線性電阻系數比較差電阻式觸摸屏有很好的校正功能。校正相關的變量主要有:
?x[5],y[5]五點定位的物理坐標(LCD坐標)
?xl[5],yl[5]五點定位的邏輯坐標(觸摸AD值)
?KX,KY橫縱方向伸縮系數
?XLC,YLC中心基點邏輯坐標
?XC,YC中心基點物理坐標(數值采用LCD顯示屏的物理長寬分辨率的一半)
x[5],y[5]五點定位的物理坐標是已知的,其中4點分別設置在LCD的角落,一點設置在LCD正中心,作為基準校正點,校正關鍵點和距離布局如圖37.3.3.1所示。
圖37.3.3.1 電阻屏五點校準法的參考點設定
校正步驟如下:
S1 = x[1]- x[0]
S3 = x[2]- x[3]
S2 = y[2]- y[1]
S4 = y[3]- y[0]
一般取點可以人為的設定S1=S3和S2=S4,以方便運算。
計算邏輯坐標的四點“間距”,由于實際觸點肯定會存在誤差,所以觸摸點會落在實際設定點的更大范圍內,在圖37.3.1中,設定點為五個點,但實際采樣時觸點有時會落在稍大的外圈范圍,圖中用紅色的圓圈標注了,所以有必要設定一個誤差范圍:
S1’ = xl[1]- xl[0]
S3’ = xl[2]- xl[3]
S2’ = yl[2]- yl[1]
S4’ = yl[3]- yl[0]
由于觸點的誤差,對于邏輯點S1’和S3’則大概率不會相等,同樣的,S2’和S4’也很驗取到相等的點,那么為了簡化計算,我們強制以(S1’+S3’)/2的線長作一個矩形一邊,以(S2’+S4’)/2為矩形另一邊,這樣構建的矩形在誤差范圍是可以接受的,也方便計算,于是得到X和Y方向的近似縮放系數:
KX = (S1’ + S3’) / 2 / S1
KY = (S2’ + S4’) / 2 / S2
X = (XL - XLC) / KX + XC
Y = (YL - YLC) / KY + YC
最后一步的轉換公式可能不好理解,大家換個角度,如果我們求到的縮放比例是正確的,在取新的觸摸的時候,這個觸摸點的邏輯坐標和物理坐標的轉換,必然與中心點在兩方向上的縮放比例相等,用中學數學直線斜率相等的情況,變換便可得到上述公式。
通過上述得到校準參數后,在以后的使用中,我們把所有得到的物理坐標都按照這個關系式來計算,得到的就是觸摸點的屏幕坐標。為了省去每次都需要校準的麻煩,我們保存這些參數到AT24Cxx的指定扇區地址,這樣只要校準一次就可以重復使用這些參數了。
根據上面的原理,我們設計的校準函數tp_adjust如下:
注意該函數里面多次使用了lcddev.width和lcddev.height,用于坐標設置,故在程序調用前需要預先初始化LCD得到LCD的一些屏幕信息,主要是為了兼容不同尺寸的LCD(比如320240、480320和800*480的屏都可以兼容)。
有了校準參數后,由于我們需要頻繁地進行屏幕坐標和物理坐標的轉換,我們為電阻屏增加一個tp_scan(uint8_t mode)用于轉換,為了實際使用上更靈活,我們使這個參數支持物理坐標和屏幕坐標,設計的函數如下:
要進行電阻觸摸屏的觸摸掃描,只要調取tp_scan()函數,就能靈活地得到觸摸坐標。電阻屏的觸摸就講到這里。
3. 電容屏觸摸驅動代碼
電容觸摸芯片使用的是IIC接口。IIC接口部分代碼,我們可以參考 myiic.c和myiic.h的代碼,為了使代碼獨立,我們在“TOUCH”文件夾下也是采用軟件模擬IIC的方式實現ctiic.c和ctiic.h,這樣IO的使用更靈活,這里部分參考IIC章節的知識就可以了,這里不重復介紹了。
電容觸摸芯片除了IIC接口相關引腳CT_SCL和CT_SDA,還有CT_INT和CT_RST,接口圖如圖37.3.3.2所示。
圖37.3.3.1 電容觸摸芯片接口圖
gt9xxx_init的實現也比較簡單,實現CT_INT和CT_RST引腳初始化和調用ct_iic_init函數實現對CT_SDA和CT_SCL初始化。由于電容觸摸屏在設計時是根據屏幕進行參數設計的,參數已經保存在芯片內部。所以在初始化后,就可以參考手冊推薦的IIC時序從相對應的坐標數據寄存器中把對應的XY坐標數據讀出來,再通過數據整理轉成LCD坐標。
與電阻屏不同的是,我們是通過IIC讀取狀態寄存器的值并非引腳電平。而gt9xxx系列是支持中斷或輪詢方式得到觸摸狀態,本實驗使用的是輪詢方式:
1、按照讀時序,先讀取寄存器0x814E,若當前buffer(buffer status為1)數據準備好,則依據有效觸點個數到相對應的坐標數據地址處進行坐標數據讀取。
2、若在1中發現buffer數據(buffer status為0)未準備好,則等待1ms再進行讀取。
這樣,gt9xxx_scan()函數的實現如下:這樣,gt9xxx_scan()函數的實現如下:
/* GT9XXX 10個觸摸點(最多) 對應的寄存器表 */
/* 10個觸控點的顏色(電容觸摸屏用) */
const uint16_t POINT_COLOR_TBL[10] = {RED, GREEN, BLUE, BROWN, YELLOW, MAGENTA, CYAN, LIGHTBLUE, BRRED, GRAY};
上面沒有把main.c全部代碼列出來,只是列出重要函數,這里簡單介紹一下這三個函數。
rtp_test,該函數用于電阻觸摸屏的測試,該函數代碼比較簡單,就是掃描按鍵和觸摸屏,如果觸摸屏有按下,則在觸摸屏上面劃線,如果按中“RST”區域,則執行清屏。如果按鍵KEY0按下,則執行觸摸屏校準。
ctp_test,該函數用于電容觸摸屏的測試,由于我們采用tp_dev.sta來標記當前按下的觸摸屏點數,所以判斷是否有電容觸摸屏按下,也就是判斷tp_dev.sta的最低5位,如果有數據,則畫線,如果沒數據則忽略,且5個點畫線的顏色各不一樣,方便區分。另外,電容觸摸屏不需要校準,所以沒有校準程序。
main函數,則比較簡單,初始化相關外設,然后根據觸摸屏類型,去選擇執行ctp_test還是rtp_test。
軟件部分就介紹到這里,接下來看看下載驗證。
37.4 下載驗證
在代碼編譯成功之后,我們通過下載代碼到開發板上,電阻觸摸屏測試如圖37.4.1所示界面:
圖37.4.1 電阻觸摸屏測試程序運行效果
圖中我們在電阻屏上畫了一些內容,右上角的RST可以用來清屏,點擊該區域,即可清屏重畫。另外,按 KEY0 可以進入校準模式,如果發現觸摸屏不準,則可以按 KEY0,進入校準, 重新校準一下,即可正常使用。
如果是電容觸摸屏,測試界面如圖37.4.2所示:
圖37.4.2 電容觸摸屏測試界面
圖中,同樣輸入了一些內容。電容屏支持多點觸摸,每個點的顏色都不一樣,圖中的波浪線就是三點觸摸畫出來的,最多可以5點觸摸。按右上角的RST標志,可以清屏。電容屏無需校準,所以按KEY0無效。KEY0校準僅對電阻屏有效。
總結
以上是生活随笔為你收集整理的【正点原子STM32连载】第三十七章 触摸屏实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: save(),saveOrUpdate(
- 下一篇: IE浏览器防黑技术