網(wǎng)上有很多關(guān)于智能pos機(jī)平面電容觸摸屏,探索者 STM32F407 開發(fā)板資料連載第三十三章 觸摸屏實(shí)驗(yàn)的知識(shí),也有很多人為大家解答關(guān)于智能pos機(jī)平面電容觸摸屏的問題,今天pos機(jī)之家(m.afbey.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!
本文目錄一覽:
智能pos機(jī)平面電容觸摸屏
)實(shí)驗(yàn)平臺(tái):alientek 阿波羅 STM32F767 開發(fā)板
2)摘自《STM32F7 開發(fā)指南(HAL 庫(kù)版)》關(guān)注官方微信號(hào)公眾號(hào),獲取更多資料:正點(diǎn)原子
第三十三章 觸摸屏實(shí)驗(yàn)
本章,我們將介紹如何使用 STM32F4 來(lái)驅(qū)動(dòng)觸摸屏,ALIENTEK 探索者 STM32F4 開發(fā)板
本身并沒有觸摸屏控制器,但是它支持觸摸屏,可以通過(guò)外接帶觸摸屏的 LCD 模塊(比如
ALIENTEK TFTLCD 模塊),來(lái)實(shí)現(xiàn)觸摸屏控制。在本章中,我們將向大家介紹 STM32 控制
ALIENTKE TFTLCD 模塊(包括電阻觸摸與電容觸摸),實(shí)現(xiàn)觸摸屏驅(qū)動(dòng),最終實(shí)現(xiàn)一個(gè)手寫
板的功能。本章分為如下幾個(gè)部分:
33.1 電阻與電容觸摸屏簡(jiǎn)介
33.2 硬件設(shè)計(jì)
33.3 軟件設(shè)計(jì)
33.4 下載驗(yàn)證
33.1 觸摸屏簡(jiǎn)介
目前最常用的觸摸屏有兩種:電阻式觸摸屏與電容式觸摸屏。下面,我們來(lái)分別介紹。
33.1.1 電阻式觸摸屏
在 Iphone 面世之前,幾乎清一色的都是使用電阻式觸摸屏,電阻式觸摸屏利用壓力感應(yīng)進(jìn)
行觸點(diǎn)檢測(cè)控制,需要直接應(yīng)力接觸,通過(guò)檢測(cè)電阻來(lái)定位觸摸位置。
ALIENTEK 2.4/2.8/3.5 寸 TFTLCD 模塊自帶的觸摸屏都屬于電阻式觸摸屏,下面簡(jiǎn)單介紹
下電阻式觸摸屏的原理。
電阻觸摸屏的主要部分是一塊與顯示器表面非常配合的電阻薄膜屏,這是一種多層的復(fù)合
薄膜,它以一層玻璃或硬塑料平板作為基層,表面涂有一層透明氧化金屬(透明的導(dǎo)電電阻)
導(dǎo)電層,上面再蓋有一層外表面硬化處理、光滑防擦的塑料層、它的內(nèi)表面也涂有一層涂層、
在他們之間有許多細(xì)小的(小于 1/1000 英寸)的透明隔離點(diǎn)把兩層導(dǎo)電層隔開絕緣。 當(dāng)手指
觸摸屏幕時(shí),兩層導(dǎo)電層在觸摸點(diǎn)位置就有了接觸,電阻發(fā)生變化,在 X 和 Y 兩個(gè)方向上產(chǎn)生
信號(hào),然后送觸摸屏控制器??刂破鱾蓽y(cè)到這一接觸并計(jì)算出(X,Y)的位置,再根據(jù)獲得的
位置模擬鼠標(biāo)的方式運(yùn)作。這就是電阻技術(shù)觸摸屏的最基本的原理。
電阻觸摸屏的優(yōu)點(diǎn):精度高、價(jià)格便宜、抗干擾能力強(qiáng)、穩(wěn)定性好。
電阻觸摸屏的缺點(diǎn):容易被劃傷、透光性不太好、不支持多點(diǎn)觸摸。
從以上介紹可知,觸摸屏都需要一個(gè) AD 轉(zhuǎn)換器, 一般來(lái)說(shuō)是需要一個(gè)控制器的。
ALIENTEK TFTLCD 模塊選擇的是四線電阻式觸摸屏,這種觸摸屏的控制芯片有很多,包括:
ADS7843、ADS7846、TSC2046、XPT2046 和 AK4182 等。這幾款芯片的驅(qū)動(dòng)基本上是一樣的,
也就是你只要寫出了 ADS7843 的驅(qū)動(dòng),這個(gè)驅(qū)動(dòng)對(duì)其他幾個(gè)芯片也是有效的。而且封裝也有一
樣的,完全 PIN TO PIN 兼容。所以在替換起來(lái),很方便。
ALIENTEK TFTLCD 模塊自帶的觸摸屏控制芯片為 XPT2046。XPT2046 是一款 4 導(dǎo)線制觸
摸屏控制器,內(nèi)含 12 位分辨率 125KHz 轉(zhuǎn)換速率逐步逼近型 A/D 轉(zhuǎn)換器。XPT2046 支持從 1.5V
到 5.25V 的低電壓 I/O 接口。XPT2046 能通過(guò)執(zhí)行兩次 A/D 轉(zhuǎn)換查出被按的屏幕位置, 除此
之外,還可以測(cè)量加在觸摸屏上的壓力。內(nèi)部自帶 2.5V 參考電壓可以作為輔助輸入、溫度測(cè)量
和電池監(jiān)測(cè)模式之用,電池監(jiān)測(cè)的電壓范圍可以從 0V 到 6V。XPT2046 片內(nèi)集成有一個(gè)溫度傳
感器。 在 2.7V 的典型工作狀態(tài)下,關(guān)閉參考電壓,功耗可小于 0.75mW。XPT2046 采用微小
的封裝形式:TSSOP-16,QFN-16(0.75mm 厚度)和 VFBGA-48。工作溫度范圍為-40℃~+85℃。
該芯片完全是兼容 ADS7843 和 ADS7846 的,關(guān)于這個(gè)芯片的詳細(xì)使用,可以參考這兩個(gè)
芯片的 datasheet。
電阻式觸摸屏就介紹到這里。
33.1.2 電容式觸摸屏
現(xiàn)在幾乎所有智能手機(jī),包括平板電腦都是采用電容屏作為觸摸屏,電容屏是利用人體感
應(yīng)進(jìn)行觸點(diǎn)檢測(cè)控制,不需要直接接觸或只需要輕微接觸,通過(guò)檢測(cè)感應(yīng)電流來(lái)定位觸摸坐標(biāo)。
ALIENTEK 4.3/7 寸 TFTLCD 模塊自帶的觸摸屏采用的是電容式觸摸屏,下面簡(jiǎn)單介紹下
電容式觸摸屏的原理。
電容式觸摸屏主要分為兩種:
1、 表面電容式電容觸摸屏。
表面電容式觸摸屏技術(shù)是利用 ITO(銦錫氧化物,是一種透明的導(dǎo)電材料)導(dǎo)電膜,通過(guò)電
場(chǎng)感應(yīng)方式感測(cè)屏幕表面的觸摸行為進(jìn)行。但是表面電容式觸摸屏有一些局限性,它只能識(shí)別
一個(gè)手指或者一次觸摸。
2、 投射式電容觸摸屏。
投射電容式觸摸屏是傳感器利用觸摸屏電極發(fā)射出靜電場(chǎng)線。一般用于投射電容傳感技術(shù)
的電容類型有兩種:自我電容和交互電容。
自我電容又稱絕對(duì)電容,是最廣為采用的一種方法,自我電容通常是指掃描電極與地構(gòu)成
的電容。在玻璃表面有用 ITO 制成的橫向與縱向的掃描電極,這些電極和地之間就構(gòu)成一個(gè)電
容的兩極。當(dāng)用手或觸摸筆觸摸的時(shí)候就會(huì)并聯(lián)一個(gè)電容到電路中去,從而使在該條掃描線上
的總體的電容量有所改變。在掃描的時(shí)候,控制 IC 依次掃描縱向和橫向電極,并根據(jù)掃描前后
的電容變化來(lái)確定觸摸點(diǎn)坐標(biāo)位置。筆記本電腦觸摸輸入板就是采用的這種方式,筆記本電腦
的輸入板采用 X*Y 的傳感電極陣列形成一個(gè)傳感格子,當(dāng)手指靠近觸摸輸入板時(shí),在手指和傳
感電極之間產(chǎn)生一個(gè)小量電荷。采用特定的運(yùn)算法則處理來(lái)自行、列傳感器的信號(hào)來(lái)確定手指
的位置。
交互電容又叫做跨越電容,它是在玻璃表面的橫向和縱向的 ITO 電極的交叉處形成電容。
交互電容的掃描方式就是掃描每個(gè)交叉處的電容變化,來(lái)判定觸摸點(diǎn)的位置。當(dāng)觸摸的時(shí)候就
會(huì)影響到相鄰電極的耦合,從而改變交叉處的電容量,交互電容的掃面方法可以偵測(cè)到每個(gè)交
叉點(diǎn)的電容值和觸摸后電容變化,因而它需要的掃描時(shí)間與自我電容的掃描方式相比要長(zhǎng)一些,
需要掃描檢測(cè) X*Y 根電極。目前智能手機(jī)/平板電腦等的觸摸屏,都是采用交互電容技術(shù)。
ALIENTEK 所選擇的電容觸摸屏,也是采用的是投射式電容屏(交互電容類型),所以后
面僅以投射式電容屏作為介紹。
透射式電容觸摸屏采用縱橫兩列電極組成感應(yīng)矩陣,來(lái)感應(yīng)觸摸。以兩個(gè)交叉的電極矩陣,
即: X 軸電極和 Y 軸電極,來(lái)檢測(cè)每一格感應(yīng)單元的電容變化,如圖 33.1.2.1 所示:
圖 33.1.2.1 投射式電容屏電極矩陣示意圖
示意圖中的電極,實(shí)際是透明的,這里是為了方便大家理解。圖中,X、Y 軸的透明電極
電容屏的精度、分辨率與 X、Y 軸的通道數(shù)有關(guān),通道數(shù)越多,精度越高。以上就是電容觸摸
屏的基本原理,接下來(lái)看看電容觸摸屏的優(yōu)缺點(diǎn):
電容觸摸屏的優(yōu)點(diǎn):手感好、無(wú)需校準(zhǔn)、支持多點(diǎn)觸摸、透光性好。
電容觸摸屏的缺點(diǎn):成本高、精度不高、抗干擾能力差。
這里特別提醒大家電容觸摸屏對(duì)工作環(huán)境的要求是比較高的,在潮濕、多塵、高低溫環(huán)境
下面,都是不適合使用電容屏的。
電容觸摸屏一般都需要一個(gè)驅(qū)動(dòng) IC 來(lái)檢測(cè)電容觸摸,且一般是通過(guò) IIC 接口輸出觸摸數(shù)據(jù)
的。ALIENTEK 7’ TFTLCD 模塊的電容觸摸屏,采用的是 15*10 的驅(qū)動(dòng)結(jié)構(gòu)(10 個(gè)感應(yīng)通道,
15 個(gè)驅(qū)動(dòng)通道),采用的是 GT811/FT5206 做為驅(qū)動(dòng) IC。ALIENTEK 4.3’ TFTLCD 模塊有兩種
成觸摸屏:1,使用 OTT2001A 作為驅(qū)動(dòng) IC,采用 13*8 的驅(qū)動(dòng)結(jié)構(gòu)(8 個(gè)感應(yīng)通道,13 個(gè)驅(qū)動(dòng)
通道);2,使用 GT9147 作為驅(qū)動(dòng) IC,采用 17*10 的驅(qū)動(dòng)結(jié)構(gòu)(10 個(gè)感應(yīng)通道,17 個(gè)驅(qū)動(dòng)通
道)。
這兩個(gè)模塊都只支持最多 5 點(diǎn)觸摸,本例程支持 ALIENTEK 的 4.3 寸屏模塊和新版的 7 寸
屏模塊(采用 SSD1963+FT5206 方案),電容觸摸驅(qū)動(dòng) IC,這里只介紹 OTT2001A 和 GT9147,
GT811/FT5206 的驅(qū)動(dòng)方法同這兩款 IC 是類似的,大家可以參考著學(xué)習(xí)即可。
OTT2001A 是臺(tái)灣旭曜科技生產(chǎn)的一顆電容觸摸屏驅(qū)動(dòng) IC,最多支持 208 個(gè)通道。支持
SPI/IIC 接口,在 ALIENTEK 4.3’ TFTLCD 電容觸摸屏上,OTT2001A 只用了 104 個(gè)通道,采
用 IIC 接口。IIC 接口模式下,該驅(qū)動(dòng) IC 與 STM32F4 的連接僅需要 4 根線:SDA、SCL、RST
和 INT,SDA 和 SCL 是 IIC 通信用的,RST 是復(fù)位腳(低電平有效),INT 是中斷輸出信號(hào),
關(guān)于 IIC 我們就不詳細(xì)介紹了,請(qǐng)參考第二十九章。
OTT2001A 的器件地址為 0X59(不含最低位,換算成讀寫命令則是讀:0XB3,寫:0XB2),
接下來(lái),介紹一下 OTT2001A 的幾個(gè)重要的寄存器。
1, 手勢(shì) ID 寄存器
手勢(shì) ID 寄存器(00H)用于告訴 MCU,哪些點(diǎn)有效,哪些點(diǎn)無(wú)效,從而讀取對(duì)應(yīng)的數(shù)據(jù),
該寄存器各位描述如表 33.1.2.1 所示:
表 33.1.2.1 手勢(shì) ID 寄存器
OTT2001A 支持最多 5 點(diǎn)觸摸,所以表中只有 5 個(gè)位用來(lái)表示對(duì)應(yīng)點(diǎn)坐標(biāo)是否有效,其余
位為保留位(讀為 0),通過(guò)讀取該寄存器,我們可以知道哪些點(diǎn)有數(shù)據(jù),哪些點(diǎn)無(wú)數(shù)據(jù),如果
讀到的全是 0,則說(shuō)明沒有任何觸摸。
2, 傳感器控制寄存器(ODH)
傳感器控制寄存器(ODH),該寄存器也是 8 位,僅最高位有效,其他位都是保留,當(dāng)最
高位為 1 的時(shí)候,打開傳感器(開始檢測(cè)),當(dāng)最高位設(shè)置為 0 的時(shí)候,關(guān)閉傳感器(停止檢測(cè))。
3, 坐標(biāo)數(shù)據(jù)寄存器(共 20 個(gè))
坐標(biāo)數(shù)據(jù)寄存器總共有 20 個(gè),每個(gè)坐標(biāo)占用 4 個(gè)寄存器,坐標(biāo)寄存器與坐標(biāo)的對(duì)應(yīng)關(guān)系如
表 33.1.2.2 所示:
表 33.1.2.2 坐標(biāo)寄存器與坐標(biāo)對(duì)應(yīng)表
從表中可以看出,每個(gè)坐標(biāo)的值,可以通過(guò) 4 個(gè)寄存器讀出,比如讀取坐標(biāo) 1(X1,Y1),
我們則可以讀取 01H~04H,就可以知道當(dāng)前坐標(biāo) 1 的具體數(shù)值了,這里我們也可以只發(fā)送寄存
器 01,然后連續(xù)讀取 4 個(gè)字節(jié),也可以正常讀取坐標(biāo) 1,寄存器地址會(huì)自動(dòng)增加,從而提高讀
取速度。
OTT2001A 相關(guān)寄存器的介紹就介紹到這里,更詳細(xì)的資料,請(qǐng)參考:OTT2001A IIC 協(xié)議
指導(dǎo).pdf 這個(gè)文檔。OTT2001A 只需要經(jīng)過(guò)簡(jiǎn)單的初始化就可以正常使用了,初始化流程:復(fù)
位→延時(shí) 100ms→釋放復(fù)位→設(shè)置傳感器控制寄存器的最高位位 1,開啟傳感器檢查。就可以
正常使用了。
另外,OTT2001A 有兩個(gè)地方需要特別注意一下:
1,
OTT2001A 的寄存器是 8 位的,但是發(fā)送的時(shí)候要發(fā)送 16 位(高八位有效),才可
以正常使用。
2,
OTT2001A 的輸出坐標(biāo),默認(rèn)是以:X 坐標(biāo)最大值是 2700,Y 坐標(biāo)最大值是 1500
的分辨率輸出的,也就是輸出范圍為:X:0~2700,Y:0~1500;MCU 在讀取到坐
標(biāo)后,必須根據(jù) LCD 分辨率做一個(gè)換算,才能得到真實(shí)的 LCD 坐標(biāo)。
下面我們簡(jiǎn)單介紹下 GT9147,該芯片是深圳匯頂科技研發(fā)的一顆電容觸摸屏驅(qū)動(dòng) IC,支
持 100Hz 觸點(diǎn)掃描頻率,支持 5 點(diǎn)觸摸,支持 18*10 個(gè)檢測(cè)通道,適合小于 4.5 寸的電容觸摸
屏使用。
和 OTT2001A 一樣,GT9147 與 MCU 連接也是通過(guò) 4 根線:SDA、SCL、RST 和 INT。不
過(guò),GT9147 的 IIC 地址,可以是 0X14 或者 0X5D,當(dāng)復(fù)位結(jié)束后的 5ms 內(nèi),如果 INT 是高電
平,則使用 0X14 作為地址,否則使用 0X5D 作為地址,具體的設(shè)置過(guò)程,請(qǐng)看:GT9147 數(shù)據(jù)
手冊(cè).pdf 這個(gè)文檔。本章我們使用 0X14 作為器件地址(不含最低位,換算成讀寫命令則是讀:
0X29,寫:0X28),接下來(lái),介紹一下 GT9147 的幾個(gè)重要的寄存器。
1,控制命令寄存器(0X8040)
該寄存器可以寫入不同值,實(shí)現(xiàn)不同的控制,我們一般使用 0 和 2 這兩個(gè)值,寫入 2,即
可軟復(fù)位 GT9147,在硬復(fù)位之后,一般要往該寄存器寫 2,實(shí)行軟復(fù)位。然后,寫入 0,即可
正常讀取坐標(biāo)數(shù)據(jù)(并且會(huì)結(jié)束軟復(fù)位)。
2,配置寄存器組(0X8047~0X8100)
這里共 186 個(gè)寄存器,用于配置 GT9147 的各個(gè)參數(shù),這些配置一般由廠家提供給我們(一
個(gè)數(shù)組),所以我們只需要將廠家給我們的配置,寫入到這些寄存器里面,即可完成 GT9147 的
配置。由于 GT9147可以保存配置信息(可寫入內(nèi)部FLASH,從而不需要每次上電都更新配置),
我們有幾點(diǎn)注意的地方提醒大家:1,0X8047 寄存器用于指示配置文件版本號(hào),程序?qū)懭氲陌?/p>
本號(hào),必須大于等于 GT9147 本地保存的版本號(hào),才可以更新配置。2,0X80FF 寄存器用于存
儲(chǔ)校驗(yàn)和,使得 0X8047~0X80FF 之間所有數(shù)據(jù)之和為 0。3,0X8100 用于控制是否將配置保存
在本地,寫 0,則不保存配置,寫 1 則保存配置。
3,產(chǎn)品 ID 寄存器(0X8140~0X8143)
這里總共由 4 個(gè)寄存器組成,用于保存產(chǎn)品 ID,對(duì)于 GT9147,這 4 個(gè)寄存器讀出來(lái)就是:
9,1,4,7 四個(gè)字符(ASCII 碼格式)。因此,我們可以通過(guò)這 4 個(gè)寄存器的值,來(lái)判斷驅(qū)動(dòng)
IC 的型號(hào),從而判斷是 OTT2001A 還是 GT9147,以便執(zhí)行不同的初始化。
4,狀態(tài)寄存器(0X814E)
該寄存器各位描述如表 33.1.2.3 所示:
表 33.1.2.3 狀態(tài)寄存器各位描述
這里,我們僅關(guān)心最高位和最低 4 位,最高位用于表示 buffer 狀態(tài),如果有數(shù)據(jù)(坐標(biāo)/
按鍵),buffer 就會(huì)是 1,最低 4 位用于表示有效觸點(diǎn)的個(gè)數(shù),范圍是:0~5,0,表示沒有觸摸,
5 表示有 5 點(diǎn)觸摸。這和前面 OTT2001A 的表示方法稍微有點(diǎn)區(qū)別,OTT2001A 是每個(gè)位表示
一個(gè)觸點(diǎn),這里是有多少有效觸點(diǎn)值就是多少。最后,該寄存器在每次讀取后,如果 bit7 有效,
則必須寫 0,清除這個(gè)位,否則不會(huì)輸出下一次數(shù)據(jù)??!這個(gè)要特別注意?。?!
5,坐標(biāo)數(shù)據(jù)寄存器(共 30 個(gè))
這里共分成 5 組(5 個(gè)點(diǎn)),每組 6 個(gè)寄存器存儲(chǔ)數(shù)據(jù),以觸點(diǎn) 1 的坐標(biāo)數(shù)據(jù)寄存器組為例,
如表 33.1.2.4 所示:
表 33.1.2.4 觸點(diǎn) 1 坐標(biāo)寄存器組描述
我們一般只用到觸點(diǎn)的 x,y 坐標(biāo),所以只需要讀取 0X8150~0X8153 的數(shù)據(jù),組合即可得
到觸點(diǎn)坐標(biāo)。其他 4 組分別是:0X8158、0X8160、0X8168 和 0X8170 等開頭的 16 個(gè)寄存器組成,分別針對(duì)觸點(diǎn) 2~4 的坐標(biāo)。同樣 GT9147 也支持寄存器地址自增,我們只需要發(fā)送寄存器
組的首地址,然后連續(xù)讀取即可,GT9147 會(huì)自動(dòng)地址自增,從而提高讀取速度。
GT9147 相關(guān)寄存器的介紹就介紹到這里,更詳細(xì)的資料,請(qǐng)參考:GT9147 編程指南.pdf
這個(gè)文檔。
GT9147 只需要經(jīng)過(guò)簡(jiǎn)單的初始化就可以正常使用了,初始化流程:硬復(fù)位→延時(shí) 10ms→
結(jié)束硬復(fù)位→設(shè)置 IIC 地址→延時(shí) 100ms→軟復(fù)位→更新配置(需要時(shí))→結(jié)束軟復(fù)位。此時(shí)
GT9147 即可正常使用了。
然后,我們不停的查詢 0X814E 寄存器,判斷是否有有效觸點(diǎn),如果有,則讀取坐標(biāo)數(shù)據(jù)
寄存器,得到觸點(diǎn)坐標(biāo),特別注意,如果 0X814E 讀到的值最高位為 1,就必須對(duì)該位寫 0,否
則無(wú)法讀到下一次坐標(biāo)數(shù)據(jù)。
電容式觸摸屏部分,就介紹到這里。
33.2 硬件設(shè)計(jì)
本章實(shí)驗(yàn)功能簡(jiǎn)介:開機(jī)的時(shí)候先初始化 LCD,讀取 LCD ID,隨后,根據(jù) LCD ID 判斷
是電阻觸摸屏還是電容觸摸屏,如果是電阻觸摸屏,則先讀取 24C02 的數(shù)據(jù)判斷觸摸屏是否已
經(jīng)校準(zhǔn)過(guò),如果沒有校準(zhǔn),則執(zhí)行校準(zhǔn)程序,校準(zhǔn)過(guò)后再進(jìn)入電阻觸摸屏測(cè)試程序,如果已經(jīng)
校準(zhǔn)了,就直接進(jìn)入電阻觸摸屏測(cè)試程序。
如果是 4.3 寸電容觸摸屏,則先讀取芯片 ID,判斷是不是 GT9147,如果是則執(zhí)行 GT9147
的初始化代碼,如果不是,則執(zhí)行 OTT2001A 的初始化代碼;如果是 7 寸電容觸摸屏(僅支持
新款 7 寸屏,使用 SSD1963+FT5206 方案),則執(zhí)行 FT5206 的初始化代碼,在初始化電容觸
摸屏完成后,進(jìn)入電容觸摸屏測(cè)試程序(電容觸摸屏無(wú)需校準(zhǔn)?。。?。
電阻觸摸屏測(cè)試程序和電容觸摸屏測(cè)試程序基本一樣,只是電容觸摸屏支持最多 5 點(diǎn)同時(shí)
觸摸,電阻觸摸屏只支持一點(diǎn)觸摸,其他一模一樣。測(cè)試界面的右上角會(huì)有一個(gè)清空的操作區(qū)
域(RST),點(diǎn)擊這個(gè)地方就會(huì)將輸入全部清除,恢復(fù)白板狀態(tài)。使用電阻觸摸屏的時(shí)候,可
以通過(guò)按 KEY0 來(lái)實(shí)現(xiàn)強(qiáng)制觸摸屏校準(zhǔn),只要按下 KEY0 就會(huì)進(jìn)入強(qiáng)制校準(zhǔn)程序。
所要用到的硬件資源如下:
1) 指示燈 DS0
2) KEY0 按鍵
3) TFTLCD 模塊(帶電阻/電容式觸摸屏)
4) 24C02
所有這些資源與 STM32F4 的連接圖,在前面都已經(jīng)介紹了,這里我們只針對(duì) TFTLCD 模
塊與 STM32F4 的連接端口再說(shuō)明一下,TFTLCD 模塊的觸摸屏(電阻觸摸屏)總共有 5 跟線
與 STM32F4 連接,連接電路圖如圖 33.2.1 所示:
圖 33.2.1 觸摸屏與 STM32F4 的連接圖
從圖中可以看出, T_MOSI、T_MISO、T_SCK、T_CS 和 T_PEN 分別連接在 STM32F4 的:PF11、
PB2、PB0、PC13 和 PB1 上。
如果是電容式觸摸屏,我們的接口和電阻式觸摸屏一樣(上圖右側(cè)接口),只是沒有用到
五根線了,而是四根線,分別是: T_PEN(CT_INT) 、 T_CS(CT_RST) 、 T_CLK(CT_SCL) 和
T_MOSI(CT_SDA)。其中:CT_INT、CT_RST、CT_SCL 和 CT_SDA 分別是 OTT2001A/GT9147/FT5206
的:中斷輸出信號(hào)、復(fù)位信號(hào),IIC 的 SCL 和 SDA 信號(hào)。這里,我們用查詢的方式讀取
OTT2001A/GT9147/FT5206 的數(shù)據(jù),對(duì)于 OTT2001A/FT5206 沒有用到中斷信號(hào)(CT_INT),所以
同 STM32F4 的連接,只需要 3 根線即可,不過(guò) GT9147 還需要用到 CT_INT 做 IIC 地址設(shè)定,所
以需要 4 根線連接。
33.3 軟件設(shè)計(jì)
打開本章實(shí)驗(yàn)工程目錄可以看到,我們?cè)?HARDWARE 文件夾下新建了一個(gè) TOUCH 文件
夾,然后新建了 touch.c、touch.h、ctiic.c、ctiic.h、ott2001a.c、ott2001a.h、gt9147.c、gt9147.h、
ft5206.c 和 ft5206.h 等十個(gè)文件用來(lái)存放觸摸屏相關(guān)的代碼。同時(shí)引入這些源文件到工程
HARDWARE 分組之下,并將 TOUCH 文件夾加入頭文件包含路徑。其中,touch.c 和 touch.h
是電阻觸摸屏部分的代碼,順帶兼電容觸摸屏的管理控制,其他則是電容觸摸屏部分的代碼。
打開 touch.c 文件,里面主要是與觸摸屏相關(guān)的代碼(主要是電阻觸摸屏的代碼),這里我
們也不全部貼出來(lái)了,僅介紹幾個(gè)重要的函數(shù)。
首先我們要介紹的是 TP_Read_XY2 這個(gè)函數(shù),該函數(shù)專門用于從電阻式觸摸屏控制 IC 讀取
坐標(biāo)的值(0~4095),TP_Read_XY2 的代碼如下:
//連續(xù) 2 次讀取觸摸屏 IC,且這兩次的偏差不能超過(guò)//ERR_RANGE,滿足條件,則認(rèn)為讀數(shù)正確,否則讀數(shù)錯(cuò)誤.//該函數(shù)能大大提高準(zhǔn)確度//x,y:讀取到的坐標(biāo)值//返回值:0,失敗;1,成功。#define ERR_RANGE 50 //誤差范圍u8 TP_Read_XY2(u16 *x,u16 *y){u16 x1,y1;u16 x2,y2;u8 flag; flag=TP_Read_XY(&x1,&y1); if(flag==0)return(0); flag=TP_Read_XY(&x2,&y2); if(flag==0)return(0);//前后兩次采樣在+-50 內(nèi) if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE)) &&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE))) { *x=(x1+x2)/2;*y=(y1+y2)/2; return 1; }else return 0;}
該函數(shù)采用了一個(gè)非常好的辦法來(lái)讀取屏幕坐標(biāo)值,就是連續(xù)讀兩次,兩次讀取的值之差
不能超過(guò)一個(gè)特定的值(ERR_RANGE),通過(guò)這種方式,我們可以大大提高觸摸屏的準(zhǔn)確度。另
外該函數(shù)調(diào)用的 TP_Read_XY 函數(shù),用于單次讀取坐標(biāo)值。TP_Read_XY 也采用了一些軟件濾波
算法,具體見光盤的源碼。接下來(lái),我們介紹另外一個(gè)函數(shù) TP_Adjust,該函數(shù)源碼如下:
/觸摸屏校準(zhǔn)代碼//得到四個(gè)校準(zhǔn)參數(shù)void TP_Adjust(void){u16 pos_temp[4][2];//坐標(biāo)緩存值u8 cnt=0; u32 tem1,tem2;u16 d1,d2; u16 outtime=0;double fac;POINT_COLOR=BLUE;BACK_COLOR =WHITE;LCD_Clear(WHITE);//清屏POINT_COLOR=RED;//紅色LCD_Clear(WHITE);//清屏POINT_COLOR=BLACK;LCD_ShowString(40,40,160,100,16,(u8*)TP_REMIND_MSG_TBL);//顯示提示信息TP_Drow_Touch_Point(20,20,RED);//畫點(diǎn) 1tp_dev.sta=0;//消除觸發(fā)信號(hào)tp_dev.xfac=0;//xfac 用來(lái)標(biāo)記是否校準(zhǔn)過(guò),所以校準(zhǔn)之前必須清掉!以免錯(cuò)誤while(1)//如果連續(xù) 10 秒鐘沒有按下,則自動(dòng)退出{tp_dev.scan(1);//掃描物理坐標(biāo)if((tp_dev.sta&0xc0)==TP_CATH_PRES) //按鍵按下了一次(此時(shí)按鍵松開了.){outtime=0;tp_dev.sta&=~(1<<6);//標(biāo)記按鍵已經(jīng)被處理過(guò)了pos_temp[cnt][0]=tp_dev.x;pos_temp[cnt][1]=tp_dev.y;cnt++;switch(cnt){case 1:TP_Drow_Touch_Point(20,20,WHITE);//清除點(diǎn) 1TP_Drow_Touch_Point(lcddev.width="360px",height="auto" />
abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2tem1*=tem1;tem2*=tem2;d1=sqrt(tem1+tem2);//得到 1,2 的距離tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4tem1*=tem1;tem2*=tem2;d2=sqrt(tem1+tem2);//得到 3,4 的距離fac=(float)d1/d2;if(fac<0.95||fac>1.05||d1==0||d2==0)//不合格{cnt=0; TP_Drow_Touch_Point(lcddev.width="360px",height="auto" />TP_Adjust 是此部分最核心的代碼,在這里,給大家介紹一下我們這里所使用的觸摸屏校
正原理:我們傳統(tǒng)的鼠標(biāo)是一種相對(duì)定位系統(tǒng),只和前一次鼠標(biāo)的位置坐標(biāo)有關(guān)。而觸摸屏則
是一種絕對(duì)坐標(biāo)系統(tǒng),要選哪就直接點(diǎn)哪,與相對(duì)定位系統(tǒng)有著本質(zhì)的區(qū)別。絕對(duì)坐標(biāo)系統(tǒng)的
特點(diǎn)是每一次定位坐標(biāo)與上一次定位坐標(biāo)沒有關(guān)系,每次觸摸的數(shù)據(jù)通過(guò)校準(zhǔn)轉(zhuǎn)為屏幕上的坐
標(biāo),不管在什么情況下,觸摸屏這套坐標(biāo)在同一點(diǎn)的輸出數(shù)據(jù)是穩(wěn)定的。不過(guò)由于技術(shù)原理的
原因,并不能保證同一點(diǎn)觸摸每一次采樣數(shù)據(jù)相同,不能保證絕對(duì)坐標(biāo)定位,點(diǎn)不準(zhǔn),這就是
觸摸屏最怕出現(xiàn)的問題:漂移。對(duì)于性能質(zhì)量好的觸摸屏來(lái)說(shuō),漂移的情況出現(xiàn)并不是很嚴(yán)重。
所以很多應(yīng)用觸摸屏的系統(tǒng)啟動(dòng)后,進(jìn)入應(yīng)用程序前,先要執(zhí)行校準(zhǔn)程序。 通常應(yīng)用程序中使
用的 LCD 坐標(biāo)是以像素為單位的。比如說(shuō):左上角的坐標(biāo)是一組非 0 的數(shù)值,比如(20,20),
而右下角的坐標(biāo)為(220,300)。這些點(diǎn)的坐標(biāo)都是以像素為單位的,而從觸摸屏中讀出的是點(diǎn)
的物理坐標(biāo),其坐標(biāo)軸的方向、XY 值的比例因子、偏移量都與 LCD 坐標(biāo)不同,所以,需要在
程序中把物理坐標(biāo)首先轉(zhuǎn)換為像素坐標(biāo),然后再賦給 POS 結(jié)構(gòu),達(dá)到坐標(biāo)轉(zhuǎn)換的目的。
校正思路:在了解了校正原理之后,我們可以得出下面的一個(gè)從物理坐標(biāo)到像素坐標(biāo)的轉(zhuǎn)
換關(guān)系式:
LCDx=xfac*Px+xoff;LCDy=yfac*Py+yoff;
其中(LCDx,LCDy)是在 LCD 上的像素坐標(biāo),(Px,Py)是從觸摸屏讀到的物理坐標(biāo)。xfac,
yfac 分別是 X 軸方向和 Y 軸方向的比例因子,而 xoff 和 yoff 則是這兩個(gè)方向的偏移量。
這樣我們只要事先在屏幕上面顯示 4 個(gè)點(diǎn)(這四個(gè)點(diǎn)的坐標(biāo)是已知的),分別按這四個(gè)點(diǎn)就
可以從觸摸屏讀到 4 個(gè)物理坐標(biāo),這樣就可以通過(guò)待定系數(shù)法求出 xfac、yfac、xoff、yoff 這四
個(gè)參數(shù)。我們保存好這四個(gè)參數(shù),在以后的使用中,我們把所有得到的物理坐標(biāo)都按照這個(gè)關(guān)
系式來(lái)計(jì)算,得到的就是準(zhǔn)確的屏幕坐標(biāo)。達(dá)到了觸摸屏校準(zhǔn)的目的。
TP_Adjust 就 是根 據(jù) 上面 的 原理 設(shè) 計(jì)的 校準(zhǔn)函 數(shù) ,注 意 該函 數(shù)里面 多 次使 用 了
lcddev.width="360px",height="auto" />
480*320 和 800*480 的屏都可以兼容)。
接下來(lái)看看觸摸屏初始化函數(shù):TP_Init,該函數(shù)根據(jù) LCD 的 ID(即 lcddev.id)判別是電
阻屏還是電容屏,執(zhí)行不同的初始化,該函數(shù)代碼如下:
//觸摸屏初始化//返回值:0,沒有進(jìn)行校準(zhǔn) 1,進(jìn)行過(guò)校準(zhǔn)u8 TP_Init(void){if(lcddev.id==0X5510)//電容觸摸屏{if(GT9147_Init()==0) //是 GT9147?{tp_dev.scan=GT9147_Scan; //掃描函數(shù)指向 GT9147 觸摸屏掃描}else{OTT2001A_Init();tp_dev.scan=OTT2001A_Scan;//掃描函數(shù)指向 OTT2001A 觸摸屏掃描}tp_dev.touchtype|=0X80;//電容屏tp_dev.touchtype|=lcddev.dir&0X01;//橫屏還是豎屏return 0;} else if(lcddev.id==0X1963){FT5206_Init();tp_dev.scan=FT5206_Scan;//掃描函數(shù)指向 GT9147 觸摸屏掃描tp_dev.touchtype|=0X80;//電容屏tp_dev.touchtype|=lcddev.dir&0X01;//橫屏還是豎屏return 0;} else{ __HAL_RCC_GPIOB_CLK_ENABLE();//開啟 GPIOB 時(shí)鐘__HAL_RCC_GPIOC_CLK_ENABLE();//開啟 GPIOC 時(shí)鐘__HAL_RCC_GPIOF_CLK_ENABLE();//開啟 GPIOF 時(shí)鐘//GPIOB1,2 初始化設(shè)置GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_2;//PB1/PB2 設(shè)置為上拉輸入GPIO_Initure.Mode=GPIO_MODE_INPUT;//輸入模式GPIO_Initure.Pull=GPIO_PULLUP;//上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化//PB0GPIO_Initure.Pin=GPIO_PIN_0;//PB0 設(shè)置為推挽輸出GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化//PC13GPIO_Initure.Pin=GPIO_PIN_13;//PC13 設(shè)置為推挽輸出HAL_GPIO_Init(GPIOC,&GPIO_Initure);//初始化//PF11GPIO_Initure.Pin=GPIO_PIN_11;//PF11 設(shè)置推挽輸出HAL_GPIO_Init(GPIOF,&GPIO_Initure);//初始化TP_Read_XY(&tp_dev.x[0],&tp_dev.y[0]);//第一次讀取初始化AT24CXX_Init();//初始化 24CXXif(TP_Get_Adjdata())return 0;//已經(jīng)校準(zhǔn)else//未校準(zhǔn)?{LCD_Clear(WHITE);//清屏TP_Adjust();//屏幕校準(zhǔn)TP_Save_Adjdata();}TP_Get_Adjdata();}return 1;}
該函數(shù)比較簡(jiǎn)單,重點(diǎn)說(shuō)一下:tp_dev.scan,這個(gè)結(jié)構(gòu)體函數(shù)指針,默認(rèn)是指向 TP_Scan
的,如果是電阻屏則用默認(rèn)的即可,如果是電容屏,則指向新的掃描函數(shù) GT9147_Scan、
OTT2001A_Scan 或 FT5206_Scan(根據(jù)芯片 ID 判斷到底指向那個(gè)),執(zhí)行電容觸摸屏的掃描函
數(shù),這幾個(gè)函數(shù)在后續(xù)會(huì)介紹。
其他的函數(shù)我們這里就不多介紹了,接下來(lái)打開 touch.h 文件,代碼如下:
#define TP_PRES_DOWN 0x80 //觸屏被按下#define TP_CATH_PRES 0x40 //有按鍵按下了#define CT_MAX_TOUCH 5//電容屏支持的點(diǎn)數(shù),固定為 5 點(diǎn)//觸摸屏控制器typedef struct{u8 (*init)(void);//初始化觸摸屏控制器u8 (*scan)(u8);//掃描觸摸屏.0,屏幕掃描;1,物理坐標(biāo);void (*adjust)(void);//觸摸屏校準(zhǔn)u16 x[CT_MAX_TOUCH]; //當(dāng)前坐標(biāo)u16 y[CT_MAX_TOUCH]; //電容屏有最多 5 組坐標(biāo),電阻屏則用 x[0],y[0]代表: 此次//掃描時(shí)觸屏的坐標(biāo),用 x[4],y[4]存儲(chǔ)第一次按下時(shí)的坐標(biāo).u8 sta;//筆的狀態(tài)//b7:按下 1/松開 0; //b6:0,沒有按鍵按下;1,有按鍵按下.//b5:保留//b4~b0:電容觸摸屏按下的點(diǎn)數(shù)(0,表示未按下,1 表示按下)/////////////////////觸摸屏校準(zhǔn)參數(shù)(電容屏不需要校準(zhǔn))//////////////////////float xfac;float yfac;short xoff;short yoff;//新增的參數(shù),當(dāng)觸摸屏的左右上下完全顛倒時(shí)需要用到.//b0:0,豎屏(適合左右為 X 坐標(biāo),上下為 Y 坐標(biāo)的 TP)// 1,橫屏(適合左右為 Y 坐標(biāo),上下為 X 坐標(biāo)的 TP)//b1~6:保留.//b7:0,電阻屏// 1,電容屏u8 touchtype;}_m_tp_dev;extern _m_tp_dev tp_dev;//觸屏控制器在 touch.c 里面定義//電阻屏芯片連接引腳#define PENPBin(1)//T_PEN#define DOUTPBin(2) //T_MISO#define TDINPFout(11) //T_MOSI#define TCLKPBout(0) //T_SCK#define TCSPCout(13) //T_CS//電阻屏函數(shù)void TP_Write_Byte(u8 num);//向控制芯片寫入一個(gè)數(shù)據(jù)u16 TP_Read_AD(u8 CMD);//讀取 AD 轉(zhuǎn)換值u16 TP_Read_XOY(u8 xy);//帶濾波的坐標(biāo)讀取(X/Y)……(//省略部分代碼)u8 TP_Scan(u8 tp);//掃描u8 TP_Init(void);//初始化#endif
上述代碼,我們重點(diǎn)看看_m_tp_dev 結(jié)構(gòu)體,改結(jié)構(gòu)體用于管理和記錄觸摸屏(包括電阻
觸摸屏與電容觸摸屏)相關(guān)信息。通過(guò)結(jié)構(gòu)體,在使用的時(shí)候,我們一般直接調(diào)用 tp_dev 的相
關(guān)成員函數(shù)/變量屏即可達(dá)到需要的效果,這種設(shè)計(jì)簡(jiǎn)化了接口,且方便管理和維護(hù),大家可以
效仿一下。
ctiic.c 和 ctiic.h 是電容觸摸屏的 IIC 接口部分代碼,與第二十九章的 myiic.c 和 myiic.h 基本
一樣,這里就不單獨(dú)介紹了。接下來(lái)看看文件 ott2001a.c 代碼如下:
//向 OTT2001A 寫入一次數(shù)據(jù)//reg:起始寄存器地址//buf:數(shù)據(jù)緩緩存區(qū)//len:寫數(shù)據(jù)長(zhǎng)度//返回值:0,成功;1,失敗.u8 OTT2001A_WR_Reg(u16 reg,u8 *buf,u8 len){u8 i; u8 ret=0;CT_IIC_Start();CT_IIC_Send_Byte(OTT_CMD_WR);CT_IIC_Wait_Ack();//發(fā)送寫命令CT_IIC_Send_Byte(reg>>8); CT_IIC_Wait_Ack();//發(fā)送高 8 位地址CT_IIC_Send_Byte(reg&0XFF); CT_IIC_Wait_Ack(); //發(fā)送低 8 位地址for(i=0;i<len;i++){CT_IIC_Send_Byte(buf[i]); ret=CT_IIC_Wait_Ack(); //發(fā)數(shù)據(jù)if(ret)break;} CT_IIC_Stop();//產(chǎn)生一個(gè)停止條件return ret;}//從 OTT2001A 讀出一次數(shù)據(jù)//reg:起始寄存器地址//buf:數(shù)據(jù)緩緩存區(qū)//len:讀數(shù)據(jù)長(zhǎng)度void OTT2001A_RD_Reg(u16 reg,u8 *buf,u8 len){u8 i;CT_IIC_Start();CT_IIC_Send_Byte(OTT_CMD_WR); CT_IIC_Wait_Ack();//發(fā)送寫命令CT_IIC_Send_Byte(reg>>8); CT_IIC_Wait_Ack();//發(fā)送高 8 位地址CT_IIC_Send_Byte(reg&0XFF); CT_IIC_Wait_Ack(); //發(fā)送低 8 位地址CT_IIC_Start();CT_IIC_Send_Byte(OTT_CMD_RD); CT_IIC_Wait_Ack();//發(fā)送讀命令for(i=0;i<len;i++) buf[i]=CT_IIC_Read_Byte(i==(len-1)?0:1); //發(fā)數(shù)據(jù) CT_IIC_Stop();//產(chǎn)生一個(gè)停止條件}//傳感器打開/關(guān)閉操作//cmd:1,打開傳感器;0,關(guān)閉傳感器void OTT2001A_SensorControl(u8 cmd){u8 regval=0X00;if(cmd)regval=0X80;OTT2001A_WR_Reg(OTT_CTRL_REG,?val,1);}//初始化觸摸屏//返回值:0,初始化成功;1,初始化失敗u8 OTT2001A_Init(void){u8 regval=0; GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOB_CLK_ENABLE();//開啟 GPIOB 時(shí)鐘 __HAL_RCC_GPIOC_CLK_ENABLE();//開啟 GPIOC 時(shí)鐘 //PB1 GPIO_Initure.Pin=GPIO_PIN_1;//PB1 設(shè)置為上拉輸入 GPIO_Initure.Mode=GPIO_MODE_INPUT; //輸入 GPIO_Initure.Pull=GPIO_PULLUP;//上拉 GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化 //PC13 GPIO_Initure.Pin=GPIO_PIN_13;//PC13 設(shè)置為推挽輸出 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 HAL_GPIO_Init(GPIOC,&GPIO_Initure);//初始化CT_IIC_Init(); //初始化電容屏的 I2C 總線OTT_RST=0;//復(fù)位delay_ms(100);OTT_RST=1;//釋放復(fù)位delay_ms(100);OTT2001A_SensorControl(1);//打開傳感器OTT2001A_RD_Reg(OTT_CTRL_REG,?val,1);//讀取傳感器運(yùn)行寄存器的值來(lái)判斷//I2C 通信是否正常printf("CTP ID:%x\\",regval); if(regval==0x80)return 0;return 1;}const u16 OTT_TPX_TBL[5]={OTT_TP1_REG,OTT_TP2_REG,OTT_TP3_REG,OTT_TP4_REG,OTT_TP5_REG};//掃描觸摸屏(采用查詢方式)//mode:0,正常掃描.//返回值:當(dāng)前觸屏狀態(tài).//0,觸屏無(wú)觸摸;1,觸屏有觸摸u8 OTT2001A_Scan(u8 mode){u8 buf[4], i=0, res=0;static u8 t=0;//控制查詢間隔,從而降低 CPU 占用率t++;if((t)==0||t<10)//空閑時(shí),每進(jìn)入 10 次,才檢測(cè) 1 次,從而節(jié)省 CPU 使用率{OTT2001A_RD_Reg(OTT_GSTID_REG,&mode,1);//讀取觸摸點(diǎn)的狀態(tài)if(mode&0X1F){tp_dev.sta=(mode&0X1F)|TP_PRES_DOWN|TP_CATH_PRES;for(i=0;i<5;i++){if(tp_dev.sta&(1<<i)) //觸摸有效?{OTT2001A_RD_Reg(OTT_TPX_TBL[i],buf,4); //讀取 XY 坐標(biāo)值if(tp_dev.touchtype&0X01)//橫屏{tp_dev.y[i]=(((u16)buf[2]<<8)+buf[3])*OTT_SCAL_Y;tp_dev.x[i]=800-((((u16)buf[0]<<8)+buf[1])*OTT_SCAL_X);}else{tp_dev.x[i]=(((u16)buf[2]<<8)+buf[3])*OTT_SCAL_Y;tp_dev.y[i]=(((u16)buf[0]<<8)+buf[1])*OTT_SCAL_X;}//printf("x[%d]:%d,y[%d]:%d\\",i,tp_dev.x[i],i,tp_dev.y[i]);}}res=1;if(tp_dev.x[0]==0 && tp_dev.y[0]==0)mode=0; //數(shù)據(jù)全 0,則忽略此次數(shù)據(jù)t=0;//觸發(fā)一次,則會(huì)最少連續(xù)監(jiān)測(cè) 10 次,從而提高命中率}}if((mode&0X1F)==0)//無(wú)觸摸點(diǎn)按下{if(tp_dev.sta&TP_PRES_DOWN) tp_dev.sta&=~(1<<7);//之前是按下,標(biāo)記松開else //之前就沒有被按下{tp_dev.x[0]=0xffff; tp_dev.y[0]=0xffff;tp_dev.sta&=0XE0;//清除點(diǎn)有效標(biāo)記}}if(t>240)t=10;//重新從 10 開始計(jì)數(shù)return res;}
此部分總共 5 個(gè)函數(shù),其中 OTT2001A_WR_Reg 和 OTT2001A_RD_Reg 分別用于讀寫
OTT2001A 芯片,這里特別注意寄存器地址是 16 位的,與 OTT2001A 手冊(cè)介紹的是有出入的,
必須 16 位才能正常操作。另外,重點(diǎn)介紹下 OTT2001A_Scan 函數(shù),OTT2001A_Scan 函數(shù)用
于掃描電容觸摸屏是否有按鍵按下,由于我們不是用的中斷方式來(lái)讀取 OTT2001A 的數(shù)據(jù)的,
而是采用查詢的方式,所以這里使用了一個(gè)靜態(tài)變量來(lái)提高效率,當(dāng)無(wú)觸摸的時(shí)候,盡量減少
對(duì) CPU 的占用,當(dāng)有觸摸的時(shí)候,又保證能迅速檢測(cè)到。至于對(duì) OTT2001A 數(shù)據(jù)的讀取,則
完全是我們?cè)谏厦娼榻B的方法,先讀取手勢(shì) ID 寄存器(OTT_GSTID_REG),判斷是不是有有
效數(shù)據(jù),如果有,則讀取,否則直接忽略,繼續(xù)后面的處理。
其他的函數(shù)我們這里就不多介紹了,接下來(lái)看下 gt9147.c 里面的代碼,這里我們僅介紹
GT9147_Init 和 GT9147_Scan 兩個(gè)函數(shù),代碼如下:
//初始化 GT9147 觸摸屏//返回值:0,初始化成功;1,初始化失敗u8 GT9147_Init(void){u8 temp[5];__HAL_RCC_GPIOB_CLK_ENABLE();//開啟 GPIOB 時(shí)鐘 __HAL_RCC_GPIOC_CLK_ENABLE();//開啟 GPIOC 時(shí)鐘 //PB1 GPIO_Initure.Pin=GPIO_PIN_1;//PB1 設(shè)置為上拉輸入 GPIO_Initure.Mode=GPIO_MODE_INPUT; //輸入 GPIO_Initure.Pull=GPIO_PULLUP;//上拉 GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化 //PC13 GPIO_Initure.Pin=GPIO_PIN_13;//PC13 設(shè)置為推挽輸出 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 HAL_GPIO_Init(GPIOC,&GPIO_Initure);//初始化CT_IIC_Init();//初始化電容屏的 I2C 總線GT_RST=0;//復(fù)位delay_ms(10);GT_RST=1;//釋放復(fù)位delay_ms(10);GPIO_Initure.Pin=GPIO_PIN_1;//PB1 設(shè)置為上拉輸入 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //輸出模式 GPIO_Initure.Pull=GPIO_NOPULL;//無(wú)上下拉 GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化delay_ms(100);GT9147_RD_Reg(GT_PID_REG,temp,4);//讀取產(chǎn)品 IDtemp[4]=0;printf("CTP ID:%s\\",temp);//打印 IDif(strcmp((char*)temp,"9147")==0)//ID==9147{temp[0]=0X02;GT9147_WR_Reg(GT_CTRL_REG,temp,1);//軟復(fù)位 GT9147GT9147_RD_Reg(GT_CFGS_REG,temp,1);//讀取 GT_CFGS_REG 寄存器if(temp[0]<0X60)//默認(rèn)版本比較低,需要更新 flash 配置{printf("Default Ver:%d\\",temp[0]);GT9147_Send_Cfg(1);//更新并保存配置}delay_ms(10);temp[0]=0X00;GT9147_WR_Reg(GT_CTRL_REG,temp,1);//結(jié)束復(fù)位return 0;}return 1;}const u16 GT9147_TPX_TBL[5]={GT_TP1_REG,GT_TP2_REG,GT_TP3_REG,GT_TP4_REG,GT_TP5_REG};//掃描觸摸屏(采用查詢方式)//mode:0,正常掃描.//返回值:當(dāng)前觸屏狀態(tài).//0,觸屏無(wú)觸摸;1,觸屏有觸摸u8 GT9147_Scan(u8 mode){u8 buf[4]; u8 i=0; u8 res=0; u8 temp;static u8 t=0;//控制查詢間隔,從而降低 CPU 占用率t++;if((t)==0||t<10)//空閑時(shí),每進(jìn)入 10 次,函數(shù)才檢測(cè) 1 次,從而節(jié)省 CPU 使用率{GT9147_RD_Reg(GT_GSTID_REG,&mode,1);//讀取觸摸點(diǎn)的狀態(tài)if((mode&0XF)&&((mode&0XF)<6)){temp=0XFF<<(mode&0XF);//將點(diǎn)的個(gè)數(shù)轉(zhuǎn)換為 1 的位數(shù),匹配 tp_dev.sta 定義tp_dev.sta=(~temp)|TP_PRES_DOWN|TP_CATH_PRES;for(i=0;i<5;i++){if(tp_dev.sta&(1<<i)) //觸摸有效?{GT9147_RD_Reg(GT9147_TPX_TBL[i],buf,4); //讀取 XY 坐標(biāo)值if(tp_dev.touchtype&0X01)//橫屏{tp_dev.y[i]=((u16)buf[1]<<8)+buf[0];tp_dev.x[i]=800-(((u16)buf[3]<<8)+buf[2]);}else{tp_dev.x[i]=((u16)buf[1]<<8)+buf[0];tp_dev.y[i]=((u16)buf[3]<<8)+buf[2];}}}res=1;if(tp_dev.x[0]==0 && tp_dev.y[0]==0)mode=0; //數(shù)據(jù)全 0,則忽略此次數(shù)據(jù)t=0;//觸發(fā)一次,則會(huì)最少連續(xù)監(jiān)測(cè) 10 次,從而提高命中率}if(mode&0X80&&((mode&0XF)<6)) //清標(biāo)志?{ temp=0; GT9147_WR_Reg(GT_GSTID_REG,&temp,1);}}if((mode&0X8F)==0X80)//無(wú)觸摸點(diǎn)按下{if(tp_dev.sta&TP_PRES_DOWN) tp_dev.sta&=~(1<<7);//之前是按下,標(biāo)記松開else //之前就沒有被按下{tp_dev.x[0]=0xffff;tp_dev.y[0]=0xffff;tp_dev.sta&=0XE0;//清除點(diǎn)有效標(biāo)記}}if(t>240)t=10;//重新從 10 開始計(jì)數(shù)return res;}
以上代碼,GT9147_Init 用于初始化 GT9147,該函數(shù)通過(guò)讀取 0X8140~0X8143 這 4 個(gè)寄存
器,并判斷是否是:“9147”,來(lái)確定是不是 GT9147 芯片,在讀取到正確的 ID 后,軟復(fù)位 GT9147,
然后根據(jù)當(dāng)前芯片版本號(hào),確定是否需要更新配置,通過(guò) GT9147_Send_Cfg 函數(shù),發(fā)送配置信
息(一個(gè)數(shù)組),配置完后,結(jié)束軟復(fù)位,即完成 GT9147 初始化。GT9147_Scan 函數(shù),用于讀
取觸摸屏坐標(biāo)數(shù)據(jù),這個(gè)和前面的 OTT2001A_Scan 大同小異,大家看源碼即可。
最后我們打開 main.c,修改部分代碼,這里就不全部貼出來(lái)了,僅介紹三個(gè)重要的函數(shù):
//5 個(gè)觸控點(diǎn)的顏色(電容觸摸屏用)const u16 POINT_COLOR_TBL[5]={RED,GREEN,BLUE,BROWN,GRED};//電阻觸摸屏測(cè)試函數(shù)void rtp_test(void){u8 key; u8 i=0;while(1){key=KEY_Scan(0);tp_dev.scan(0);if(tp_dev.sta&TP_PRES_DOWN)//觸摸屏被按下{if(tp_dev.x[0]<lcddev.width="360px",height="auto" />
下面分別介紹一下這三個(gè)函數(shù)。
rtp_test,該函數(shù)用于電阻觸摸屏的測(cè)試,該函數(shù)代碼比較簡(jiǎn)單,就是掃描按鍵和觸摸屏,
如果觸摸屏有按下,則在觸摸屏上面劃線,如果按中“RST”區(qū)域,則執(zhí)行清屏。如果按鍵 KEY0
按下,則執(zhí)行觸摸屏校準(zhǔn)。
ctp_test,該函數(shù)用于電容觸摸屏的測(cè)試,由于我們采用 tp_dev.sta 來(lái)標(biāo)記當(dāng)前按下的觸摸
屏點(diǎn)數(shù),所以判斷是否有電容觸摸屏按下,也就是判斷 tp_dev.sta 的最低 5 位,如果有數(shù)據(jù),
則劃線,如果沒數(shù)據(jù)則忽略,且 5 個(gè)點(diǎn)劃線的顏色各不一樣,方便區(qū)分。另外,電容觸摸屏不
需要校準(zhǔn),所以沒有校準(zhǔn)程序。
main 函數(shù),則比較簡(jiǎn)單,初始化相關(guān)外設(shè),然后根據(jù)觸摸屏類型,去選擇執(zhí)行 ctp_test 還
是 rtp_test。
軟件部分就介紹到這里,接下來(lái)看看下載驗(yàn)證。
33.4 下載驗(yàn)證
在代碼編譯成功之后,我們通過(guò)下載代碼到 ALIENTEK 探索者 STM32F4 開發(fā)板上,電阻
觸摸屏測(cè)試如圖 33.4.1 所示界面:
圖 33.4.1 電阻觸摸屏測(cè)試程序運(yùn)行效果
圖中我們?cè)陔娮杵辽袭嬃艘恍﹥?nèi)容,右上角的 RST 可以用來(lái)清屏,點(diǎn)擊該區(qū)域,即可清屏
重畫。另外,按 KEY0 可以進(jìn)入校準(zhǔn)模式,如果發(fā)現(xiàn)觸摸屏不準(zhǔn),則可以按 KEY0,進(jìn)入校準(zhǔn),
重新校準(zhǔn)一下,即可正常使用。
如果是電容觸摸屏,測(cè)試界面如圖 33.4.2 所示:
圖 33.4.2 電容觸摸屏測(cè)試界面
圖中,同樣輸入了一些內(nèi)容。電容屏支持多點(diǎn)觸摸,每個(gè)點(diǎn)的顏色都不一樣,圖中的波浪
線就是三點(diǎn)觸摸畫出來(lái)的,最多可以 5 點(diǎn)觸摸。注意:電容觸摸屏支持:ALIENTEK 4.3 寸電
容觸摸屏模塊或者 ALIENTEK 新款 7 寸電容觸摸屏模塊(SSD1963+FT5206 方案),老款的 7
寸電容觸摸屏模塊(CPLD+GT811 方案)本例程不支持?。?/p>
同樣,按右上角的 RST 標(biāo)志,可以清屏。電容屏無(wú)需校準(zhǔn),所以按 KEY0 無(wú)效。KEY0 校
準(zhǔn)僅對(duì)電阻屏有效。
以上就是關(guān)于智能pos機(jī)平面電容觸摸屏,探索者 STM32F407 開發(fā)板資料連載第三十三章 觸摸屏實(shí)驗(yàn)的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于智能pos機(jī)平面電容觸摸屏的知識(shí),希望能夠幫助到大家!
![](/style/images/zhouzong.jpg)