利用XPT2046制作一個電位器AD轉換裝置


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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM