XPT2046是一款四線制電阻觸摸屏控制芯片,內含12位分辨率125KHz轉換速率逐步逼近型A/D轉換器,支持從1.5V到5.25V的低電壓I/O接口。
所謂逐步逼近型,就是輸入一個模擬量,其與1000 0000 0000 對應的模擬量進行比較,大則高位取1,小則高位取0。這種思想相當於折半查詢,所以可以依次從高位到低位確定所有值,以此來確定模擬量對應的數字量。
我們該如何去用這個芯片,來完成將一個模擬量轉換成數字量呢?
初學者確實有很大的困難,我們需要學會怎么去看它的芯片手冊。
上圖是它的一個封裝圖,是不是看得很亂?
別急,這時候還要看看它每個管腳的功能描述
如下圖
這時候,我們可以大致了解這是一個串行輸入輸出的芯片。
串行數據輸出是DOUT(16管腳),也就是我們最終的數字量。
串行數據輸入是DIN(2管腳),你會想,我們不是輸入的是模擬量,怎么會要串行輸入呢?
確實,你會看到6、7、8、9管腳都是輸入管腳,它們就不是串行輸入的,所以我們可以推測它們是不同的模擬量輸入口。其實DIN管腳是模式控制輸入口,就好比我們去操作寄存器一樣,要寫進去一個數字量,來控制寄存器的運行模式,芯片也是這樣。
再看DCLK管腳,這是外部時鍾輸入口,既然是串行輸入輸出,就要有拍子來控制一個一個字節輸入輸出,所以這個管腳就是起到這個作用。
然后我們一定要看時序圖
通過看時序圖,才能了解芯片的工作方式。
首先,CS是片選,低電平有效。
首先輸入一個DIN,但是由於是串行輸入,所以這里就要用位運算來一位一位提取后輸入到DIN管腳,而輸進去的時候是發生在時鍾上升沿,時鍾下降沿結束輸入。
所以我們可以將模式輸入程序寫成這樣的格式:
1、獲得char 型模式數字量
2、DCLK = 0.
3、提取高位並將其賦值給DIN
4、DCLK = 1.鎖存當前值。
循環8次。
之后我們發現芯片進入busy階段,我們需要給它一個小延時,讓它進行AD轉換,然后我們還需要再給一個時鍾脈沖,清除busy.
接下來就是讀取DOUT的值,原理同DIN輸入。
而模式的選擇需要看你的板子上是怎么外接的
我們需要用電位器來實現AD轉換,所以模擬量輸入接口應該選擇X+(6管腳)
再看芯片手冊的模式說明
所以我們模式選擇為0x94,讀者可以自行對照每一位看看。
綜上,我就可以給出完整代碼了
1 #include <reg52.h> 2 #include<intrins.h> 3 4 #define uint unsigned int 5 #define uchar unsigned char 6 #define GPIO_DUAN P0 7 8 uchar table[]={ 9 0x3f, 0x06, 0x5b, 0x4f, 10 0x66, 0x6d, 0x7d, 0x07, 11 0x7f, 0x6f, 0x77, 0x7c, 12 0x39, 0x5e, 0x79, 0x71 13 }; 14 15 uchar DisplayData[5]; 16 sbit HCA = P2^2;//HCA,HCB,HCC是利用了74HC138譯碼器來進行位選,我們動態位選了4位 17 sbit HCB = P2^3; 18 sbit HCC = P2^4; 19 sbit CLK = P1^0; 20 sbit CS = P1^1; 21 sbit DIN = P1^2; 22 sbit DOUT = P1^3; 23 24 void DisplayDS(); 25 void delayms(uint xms); 26 uint Read_AD_Data(uchar moshi); 27 void SPI_Write(uchar moshi); 28 uint GetValue(); 29 30 void main() 31 { 32 uint temp, cnt = 50; 33 while(1){ 34 if(cnt == 50){//每50下讀取轉換值,避免數字跳動太快 35 temp = Read_AD_Data(0x94); 36 cnt = 0; 37 } 38 cnt++; 39 40 DisplayData[0] = table[temp%10000/1000]; 41 DisplayData[1] = table[temp%1000/100]; 42 DisplayData[2] = table[temp%100/10]; 43 DisplayData[3] = table[temp%10/1]; 44 45 DisplayDS(); 46 } 47 } 48 49 void DisplayDS() 50 {//動態掃描函數 51 uint i; 52 for(i = 0; i < 4; i++){ 53 GPIO_DUAN = 0x00; 54 switch(i) 55 { 56 case 0 : HCC = 0; HCB = 0; HCA = 0; break; 57 case 1 : HCC = 0; HCB = 0; HCA = 1; break; 58 case 2 : HCC = 0; HCB = 1; HCA = 0; break; 59 case 3 : HCC = 0; HCB = 1; HCA = 1; break; 60 } 61 GPIO_DUAN = DisplayData[i]; 62 delayms(1); 63 } 64 } 65 66 void delayms(uint xms) 67 { 68 uint i, j; 69 for(i = 0; i < xms; i++) 70 for(j = 0; j < 110; j++); 71 } 72 73 uint Read_AD_Data(uchar moshi) 74 {//讀取最終的數字量函數 75 uint i, ans; 76 SPI_Write(moshi); 77 for(i = 0; i < 5; i++); 78 79 CLK = 1; 80 _nop_(); 81 _nop_(); 82 CLK = 0; 83 _nop_(); 84 _nop_(); 85 86 ans = GetValue(); 87 CS = 1; 88 return ans; 89 } 90 91 void SPI_Write(uchar moshi) 92 {//寫模式函數 93 uint i; 94 CS = 0; 95 for(i = 0; i < 8; i++){ 96 CLK = 0; 97 DIN = moshi>>7; 98 CLK = 1; 99 moshi <<= 1; 100 } 101 CLK = 0; 102 } 103 104 uint GetValue() 105 {//讀取DOUT管腳,得到最終數字量函數 106 uint i, ans = 0; 107 for(i = 0; i < 12; i++){ 108 CLK = 0; 109 ans <<= 1; 110 ans |= DOUT; 111 CLK = 1; 112 } 113 CLK = 0; 114 return ans; 115 }