?
一、環境介紹
編程語言: C語言
編程風格: 寄存器開發.
二、XPT2046芯片介紹
2.1 功能
XPT2046是一顆12位的ADC芯片,可以當做普通的ADC芯片使用,但是一般都是用在電阻觸摸屏上,方便定位觸摸屏坐標。
?
圖1: XPT2046內部原理圖
?
圖2:電阻觸摸屏---引出的4條線就接在XPT2046的YNXNYPXP上
(XPT2046支持筆中斷輸出--低電平有效,這個引腳可以配置到單片機的中斷腳上,或者輪詢判斷這個引腳狀態,判斷觸摸屏是否已經按下)
可以單獨買一個觸摸屏+一個XPT2046就可以自己做手畫板、觸摸按鍵(自己用一張紙在下面畫個模型就行)、等等很多小玩意。
?
圖3:采用的電阻觸摸屏的LCD屏(上面蓋的哪一層薄膜就是觸摸用的)
?
2.2 特性
1. 工作電壓范圍為 2.2V~5.25V
2. 支持 1.5V~5.25V 的數字 I/O 口
3. 內建 2.5V 參考電壓源
4. 電源電壓測量(0V~6)
5. 內建溫度測量功能
6. 觸摸壓力測量
7. 采用 SPI 3線控制通信接口
8. 具有自動 power-down 功能
9. 封裝:QFN-16、 TSSOP-16 和 VFBGA-48與 TSC2046、 AK4182A 完全兼容
10. XPT2046 在 125KHz 轉換速率和 2.7V 電壓下的功耗僅為750 μW。 XPT2046 11. 以其低功耗和高速率等特性,被廣泛應用在采用電池供電的小型手持設備上,比如 PDA、手機等。
12. XPT2046 有 TSSOP-16、 QFN-16 和 VFBGA 三種封裝形
式,溫度范圍是 - 40 ~ + 85℃ 。
2.3工作原理
XPT2046 是一種典型的逐次逼近型模數轉換器(SAR ADC),包含了采樣/保持、模數轉換、串口數據輸出等功能。同時芯片集成有一個 2.5V的內部參考電壓源、溫度檢測電路,工作時使用外部時鐘。 XPT2046 可以單電源供電,電源電壓范圍為 2.7V~5.5V。參考電壓值直接決定ADC的輸入范圍,參考電壓可以使用內部參考電壓,也可以從外部直接輸入1V~VCC范圍內的參考電壓(要求外部參考電壓源輸出阻抗低)。 X、 Y、 Z、 VBAT、 Temp和AUX模擬信號經過片內的
控制寄存器選擇后進入ADC, ADC可以配置為單端或差分模式。選擇VBAT、 Temp和AUX時可以配置為單端模式;作為觸摸屏應用時,可以配置為差分模式,這可有效消除由于驅動開關的寄生電阻及外部的干擾帶來的測量誤差,提高轉換準確度。
典型的應用:
?
單端工作模式
SER/DFR置為高電平時, XPT2046 工作在為單端模式,單端工作模式的應用原理如下圖所示。
單端模式簡單,在采樣過程完成后,轉換過程中可以關閉驅動開關,降低功耗。但這種模式的缺點是精度直接受參考電壓源的精度限制,同時由于內部驅動開關的導通電阻存在,導通電阻與觸摸屏電阻的分壓作用,也會帶來測量誤差。
(圖片里的A2 A1 A0 ,還有上面說的SER/DFR就是XPT2046的配置命令,具體使用方法在后面會講到)
?
差分工作模式
SER/DFR置為低電平時, XPT2046 為差分工作模式.
差分模式的優點是: +REF 和-REF 的輸入分別直接接到 YP、 YN 上,可消除由于驅動開關的導通電阻引入的坐標測量誤差。
缺點是:無論是采樣還是轉換過程中,驅動開關都需要接通,相對單端模式而言,功耗增加了。
如果不考慮功耗的話,當前就選擇差分工作模式了。
(圖片里的A2 A1 A0 ,還有上面說的SER/DFR就是XPT2046的配置命令,具體使用方法在后面會講到)
?
2.3 XPT2046采集并轉換一次數據的時序介紹
XPT2046 數據接口是串行接口,處理器和轉換器之間的通信需要 8 個時鐘周期,可采用 SPI、 SSI 和 Microwire 等同步串行接口。一次完整的轉換需要 24 個串行同步時鐘(DCLK)來完成。
前 8 個時鐘用來通過DIN引腳輸入控制字節。當轉換器獲取有關下一次轉換的足夠信息后,接著根據獲得的信息設置輸入多路選擇器和參考源輸入,并進入采樣模式,如果需要,將啟動觸摸面板驅動器。 3 個多時鐘周期后,控制字節設置完成,轉換器進入轉換狀態。這時,輸入采樣-保持器進入保持狀態,觸摸面板驅動器停止工作(單端工作模式)。
接著的12 個時鐘周期將完成真正的模數轉換。如果是度量比率轉換方式(SER/DFR ——=0),驅動器在轉換過程中將一直工作,第13 個時鐘將輸出轉換結果的最后一位。剩下的 3 個多時鐘周期將用來完成被轉換器忽略的最后字節(DOUT置低)。
時序圖如下:
?
時序圖里的控制命令字節:
位 7(MSB) | 位 6 | 位 5 | 位 4 | 位 3 | 位 2 | 位 1 | 位 0(LSB) |
S | A2 | A1 | A0 | MODE | SER/DFR | PD1 | PD0 |
控制字節每個位的含義如下:
位 | 名稱 | 功能描述 |
7 | S | 開始位。為 1 表示一個新的控制字節到來,為 0 則忽略 PIN 引腳上數據 |
6-4 | A2-A0 | 通道選擇位。這個在上面已經介紹過了 |
3 | MODE | 12 位/8 位轉換分辨率選擇位。為 1 選擇 8 位為轉換分辨率,為 0 選擇 12 位分辨率 |
2 | SER/DFR | 單端輸入方式/ 差分輸入方式選擇位。為 1 是單端輸入方式,為 0 是差分輸入方式 |
1-0 | PD1-PD0 |
低功率模式選擇位。若為11,器件總處于供電狀態;若為00,器件在變換之間處于低 功率模式 |
注意: 差分模式僅用于 X 坐標、 Y 坐標和觸摸壓力的測量,其它測量要求采用單端模式。
根據上面表格的介紹,可以得到在差分模式下,選擇12位分辨率,測量X和Y坐標的兩個命令:0xD0 和 0x90
XPT2046還有其他模式,可以測量溫度,筆中斷的開關(默認是開著的),16時鐘周期轉換,15時鐘周期轉換,這些就不再介紹。 根據前面的介紹用在觸摸屏上測量XY坐標的功能已經滿足了。
2.4 SPI時序介紹
這里的XPT2046支持標準3線SPI接口,關于SPI時序的介紹,在前面文章里有介紹過。
參考這里:STM32入門開發: 介紹SPI總線、讀寫W25Q64(FLASH)(硬件+模擬時序)_DS小龍哥的專欄-CSDN博客_w25q64
2.5 物理坐標與屏幕坐標的轉換
正常在LCD屏上使用觸摸屏,肯定是需要將采集的原始X、Y值轉為LCD屏的屏幕坐標才好使用。
轉換的方法有很多,這里采用最簡單的角系數計算方法轉換。
比如,我使用的LCD屏是3.5寸的,分辨率是320*480。
1. 得到觸摸屏左上角和右下角的坐標XY極限值
x=3831,y=3934
x=155,y=168
2. 轉換坐標值
x坐標:3831~155 --> 3676~0
y坐標:3934~168 --> 3766~0
3. 計算斜率
x坐標的斜率: 3676/320=11.4875
y坐標的斜率: 3766/480=7.84583
4. 得到實際的像素坐標
x坐標: 320-(實時采集的當前X模擬量-155)/11.4875
y坐標: 480-(實時采集的當前Y模擬量-168)/7.84583
這里相減的原因: 因為我測試用的觸摸屏采集出來的X、Y值大小和LCD屏的屏幕坐標值大小是反過來的。
三、示例代碼
采用SPI模擬時序驅動,其他平臺都可以移植。
3.1 xpt2046.c
#include "xpt2046_touch.h"
struct XPT2046_TOUCH xpt2046_touch;
/*
函數功能: 初始化
硬件連接:
T_MOSI--PF9
T_MISO--PB2
T_SCK---PB1
T_PEN---PF10
T_CS----PF11
*/
void XPT2046_TouchInit(void)
{
/*1. 時鐘初始化*/
RCC->APB2ENR|=1<<3; //PB
RCC->APB2ENR|=1<<7; //PF
/*2. 初始化GPIO口*/
GPIOB->CRL&=0xFFFFF00F;
GPIOB->CRL|=0x00000830;
GPIOF->CRH&=0xFFFF000F;
GPIOF->CRH|=0x00003830;
/*3. 上拉*/
GPIOB->ODR|=0x3<<1;
GPIOF->ODR|=0x7<<9;
}
/*
函數功能: SPI底層寫一個字節
*/
void XPT2046_SPI_WriteOneByte(u8 cmd)
{
u8 i;
for(i=0;i<8;i++)
{
XPT2046_SCK=0; //低電平寫
if(cmd&0x80)XPT2046_MOSI=1;
else XPT2046_MOSI=0;
cmd<<=1;
XPT2046_SCK=1; //高電平讀,保證數據線穩定
}
}
/*
函數功能: 讀2個字節
說明: 讀取16位數據,最低4位數據無效,有效數據是高12位
*/
u16 XPT2046_ReadData(u8 cmd)
{
u16 data;
u8 i;
XPT2046_CS=0; //選中XPT2046
XPT2046_MOSI=0;
XPT2046_SCK=0;
XPT2046_SPI_WriteOneByte(cmd);
DelayUs(8); //0.008ms ,等待XPT2046轉換完成。
//消除忙信號
XPT2046_SCK=0;
DelayUs(1);
XPT2046_SCK=1;
//連續讀取16位的數據
for(i=0;i<16;i++)
{
XPT2046_SCK=0; //通知XPT2046,主機需要數據
XPT2046_SCK=1;
data<<=1;
if(XPT2046_MISO)data|=0x01;
}
data>>=4; //丟棄最低4位
XPT2046_CS=1; //取消選中
return data;
}
/*
XPT2046的命令:
10010000 :測試Y的坐標 0x90
11010000 :測試X的坐標 0xD0
返回值: 0表示沒有讀取到坐標,1表示讀取到當前坐標
//1. 得到左上角和右下角的坐標XY極限值
x=3831,y=3934
x=155,y=168
//2. 轉換坐標值
x坐標:3831~155 --> 3676~0
y坐標:3934~168 --> 3766~0
//3. 計算斜率
x坐標的斜率: 3676/320=11.4875
y坐標的斜率: 3766/480=7.84583
//4. 得到實際的像素坐標
x坐標: 320-(模擬量-155)/11.4875
y坐標: 480-(模擬量-168)/7.84583
*/
u8 XPT2046_ReadXY(void)
{
if(XPT2046_PEN==0) //判斷觸摸屏是否按下
{
/*1. 得到物理坐標*/
xpt2046_touch.x0=XPT2046_ReadData(0xD0);
xpt2046_touch.y0=XPT2046_ReadData(0x90);
/*2. 得到像素坐標*/
xpt2046_touch.x=320-(xpt2046_touch.x0-155)/11.4875;
xpt2046_touch.y=480-(xpt2046_touch.y0-168)/7.84583;
return 1;
}
return 0;
}
3.2 xpt2046.h
#ifndef XPT2046_TOUCH_H
#define XPT2046_TOUCH_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
//觸摸屏引腳定義
#define XPT2046_MOSI PFout(9)
#define XPT2046_MISO PBin(2)
#define XPT2046_SCK PBout(1)
#define XPT2046_CS PFout(11)
#define XPT2046_PEN PFin(10)
//函數聲明
void XPT2046_TouchInit(void);
void XPT2046_SPI_WriteOneByte(u8 cmd);
u8 XPT2046_ReadXY(void);
//存放觸摸屏信息的結構體
struct XPT2046_TOUCH
{
u16 x0; //物理坐標x
u16 y0; //物理坐標y
u16 x; //像素坐標x
u16 y; //像素坐標y
};
extern struct XPT2046_TOUCH xpt2046_touch;
#endif
?
-
觸摸屏
+關注
關注
42文章
2301瀏覽量
116120 -
STM32
+關注
關注
2270文章
10895瀏覽量
355744 -
SPI
+關注
關注
17文章
1706瀏覽量
91508 -
電阻觸摸屏
+關注
關注
0文章
18瀏覽量
12056 -
XPT2046
+關注
關注
0文章
18瀏覽量
18257
發布評論請先 登錄
相關推薦
評論