一、AD转换器的分类
直接A/D转换器
间接A/D转换器
二、A/D转换器主要参数指标
1.分辨率
分辨率为A/D转换器对输入信号的分辨能力,其计算公式如下,其中n为A/D转换器的位数:
当A/D转换器支持输入负电压时,第一位代表正负,则分辨率的计算公式为:
可以求得模拟电压的最小值如下, 满刻度为输入的模拟电压最大值:
2.转换误差
转换误差表示A/D转换器实际输出的数字量与理论输出量的区别。分为量化误差、偏移误差和满刻度误差。其中偏移误差和满刻度误差合称为非线性误差。
3.转换精度
转换精度为实际模拟量输入与理论模拟输入之差的最大值。对于A/D转换器而言,可以在每个阶梯的水平中点进行测量,它包括了所有误差。
4.转换时间
即完成一次A/D转换所需要的时间(包括稳定时间)。而转换时间的倒数为转换速率,即每秒转换的次数。
三、ADC0804
概况
ADC0804是逐次比较型A/D转换器,共有20个引脚,分辨率为8位,输入电压范围为0-5V,模数转换时间大约100us。价格便宜,应用广泛。
1.引脚详情

| 引脚 |
名称 |
解释 |
| 1 |
|
片选信号输入端,当输入低电平,表明A/D被选中 |
| 2 |
|
读信号输入端,低电平输出端有效 |
| 3 |
|
写信号输入端,低电平启用A/D转换 |
| 4 |
CLK |
时钟信号输入端 |
| 5 |
|
A/D转换结束信号,低电平表示转换完成 |
| 6-7 |
VIN(+),VIN(-) |
两模拟信号输入端,可接收单极性,双极性和差模输入信号 |
| 8 |
AGND |
模拟信号地 |
| 9 |
VREF/2 |
参考电平输入端,决定量化单位 |
| 10 |
DGND |
数字信号地 |
| 11-18 |
DB7-DB0 |
具有三态特性的数字信号输出口 |
| 19 |
CLKR |
内部时钟发生器外接电阻端 |
| 20 |
VCC(VREF) |
芯片输入电源,为5V |
2.时序图
- 启动时序图

- 读取时序图

3.例程:电位器A/D转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include<reg52.h> #include<intrins.h> typedef unsigned int u16; typedef unsigned char u8;
sbit dula = P2^6; sbit wela = P2^7; sbit adwr = P3^6; sbit adrd = P3^7;
u8 code table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; u8 bai,shi,ge;
void AD_Init(); void AD_read(); void delay(u16); void display(u8,u8,u8);
void main() { AD_Init(); while(1) { AD_read(); } }
void AD_Init() { wela=1; P0=0x7f; wela=0; }
void AD_read() { u8 i,adval; adwr=1; _nop_(); adwr=0; _nop_(); adwr=1; for(i=10;i>0;i--) display(bai,shi,ge); P1=0xff; adrd=1; _nop_(); adrd=0; _nop_(); adval=P1; adrd=1; bai=adval/100; shi=adval% 100/10; ge=adval% 10; }
void delay(u16 ms) { u16 i,j; for(i=ms;i>0;i--) for(j=110;j>0;j--); }
void display(u8 bai,u8 shi,u8 ge) { dula=1; P0=table[bai]; dula=0; P0=0xff; wela=1; P0=0x7e; wela=0; delay(5);
dula=1; P0=table[shi]; dula=0; P0=0xff; wela=1; P0=0x7d; wela=0; delay(5);
dula=1; P0=table[ge]; dula=0; P0=0xff; wela=1; P0=0x7b; wela=0; delay(5); }
|
总结:代码是在郭天祥书中摘取后加入自己的想法进行的修改,做注释,增加可读性同时使每一步与时序图相对应。但由于博主手头没有相应的硬件,无法测试代码可行性。仅帮助理解ADC0804转换的过程。
四、XPT2046
概况
XPT2046本是电阻触控屏控制器,由于触摸控制器需要测量电压,因此可以作为A/D转换器使用。采用了逐次比较型A/D转换器,共有16个引脚,分辨率为12位,输入电压范围为0-6V。
1.引脚图与控制寄存器

| 引脚 |
名称 |
解释 |
| 1 |
BUSY |
忙时信号线,当为高电平时为高阻状态 |
| 2 |
DIN |
串行数据输入端。当为低电平时,数据在DCLK上升沿锁存进来 |
| 3 |
|
片选信号。控制转换时序和使能串行输入输出寄存器,高电平时ADC掉电 |
| 4 |
DCLK |
外部时钟信号输入端 |
| 5 |
VCC |
电源输入端 |
| 6-9 |
XP,YP,XN,YN |
信号输入端 |
| 10 |
GND |
接地端 |
| 11 |
VBAT |
电池监视输入端 |
| 12 |
AUX |
ADC辅助输入通道 |
| 13 |
VREF |
参考电压输入/输出 |
| 14 |
IOVDD |
数字电源输入端 |
| 15 |
|
笔接触中断引脚 |
| 16 |
DOUT |
串行数据输出端。数据在DCLK的下降沿移出,当高电平时为高阻状态 |
| 位序号 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
| 位符号 |
S |
A2 |
A1 |
A0 |
MODE |
|
PD1 |
PD0 |
| 位序号 |
名称 |
解释 |
| 7 |
S |
开始位。S=1表示新的控制字节到来,S=0表示忽略PIN引脚数据 |
| 6-4 |
A2-A0 |
通道选择位 |
| 3 |
MODE |
MODE=1为8位转换分辨率,MODE=0为12位转换分辨率 |
| 2 |
|
=1为单端输入方式,=0为差分输入方式 |
| 1-0 |
PD1-PD0 |
低功率模式选择位,一般采用低功率模式,赋值00 |
注:
由于博主使用的是普中单片机开发板,且XPT2046仅作为AD转换器使用,因此仅使用单端模式,控制A0,A1,A2三个位即可,其余位较为固定。
| 控制位 |
A2 |
A1 |
A0 |
输入端口 |
外部设备 |
| 0x94/0xB4 |
0 |
0/1 |
1 |
X+ |
电位器 |
| 0xD4 |
1 |
0 |
1 |
Y+ |
热敏电阻 |
| 0xA4 |
0 |
1 |
0 |
VBAT |
光敏电阻 |
| 0xE4 |
1 |
1 |
0 |
AUX |
外部信号 |
2.时序图

3.例程:电位器A/D转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| #include<reg52.h> #include<intrins.h> typedef unsigned int u16; typedef unsigned char u8;
sbit DOUT = P3^7; sbit CLK = P3^6; sbit DIN = P3^4; sbit CS = P3^5;
sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4;
u8 time; u8 disp[4]; u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void datapros(); u16 SPI_Read(void); void SPI_Write(u8 dat); u16 Read_AD_Data(u8 cmd); void delay(u16); void DigDisplay();
void main() { while(1) { datapros(); DigDisplay(); } }
void datapros() { u16 temp; if(time==50) { time=0; temp = Read_AD_Data(0x94); } time++; disp[0]=smgduan[temp/1000]; disp[1]=smgduan[temp%1000/100]; disp[2]=smgduan[temp%1000%100/10]; disp[3]=smgduan[temp%1000%100%10]; }
void SPI_Write(u8 dat) { u8 i; CLK = 0; for(i=0; i<8; i++) { DIN = dat >> 7; dat <<= 1; CLK = 0; CLK = 1; } }
u16 SPI_Read(void) { u8 i; u16 dat=0; CLK = 0; for(i=0; i<12; i++) { dat <<= 1; CLK = 1; CLK = 0; dat |= DOUT; } return dat; }
u16 Read_AD_Data(u8 cmd) { u8 i; u16 AD_Value; CLK = 0; CS = 0; SPI_Write(cmd); for(i=6; i>0; i--); CLK = 1; _nop_(); _nop_(); CLK = 0; _nop_(); _nop_(); AD_Value=SPI_Read(); CS = 1; return AD_Value; }
void delay(u16 i) { while(i--); }
void DigDisplay() { u8 i,j; for(i=0;i<4;i++) { switch(i) { case(0): LSA=0;LSB=0;LSC=0; break; case(1): LSA=1;LSB=0;LSC=0; break; case(2): LSA=0;LSB=1;LSC=0; break; case(3): LSA=1;LSB=1;LSC=0; break; } P0=disp[3-i]; delay(100); P0=0x00; } }
|
总结:代码是在普中科技A/D转换例程改写的。与ADC0804不同的是,由于XPT2046功能较多,使用了控制寄存器,且对比前面的郭天祥的板子,普中的板子没有使用锁存器,所以数据要一位一位的写入/读取。