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
52.h>
2 #include
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 }