ADC简介
ADC(Analog-to-Digital Converter)即模数转换器,其主要作用是把模拟信号转换为数字信号。
ADC主要参数
分辨率
ADC 的分辨率是指对于允许范围内的模拟信号所对应输出离散数字信号值的个数。这些信号值一般由多位二进制数字组成。
举例,一个8位分辨率的ad芯片,其范围是0~2^8,即0~255,总共有256个数,那么对应的分辨率就是1/256。
转换速率
ADC的转换速率指的是 ADC 每秒能进行采样转换的最大次数,它与 ADC 完成一次从模拟到数字的转换所需要的时间互为倒数关系。
举例,一个ad芯片他转换一次需要0.5s,那么他一秒中所能转换的次数就是1/0.5=2次,所以他的转换速率就是2sps。
转换误差
转换误差指的是ad转换时所导致的误差,转换误差通常是以输出误差的最大值形式给出。它表示 A/D 转换器实际输出 的数字量和理论上的输出数字量之间的差别。
举例,如果相对误差≤±LSB/2,这就表明转换输出的数字量和理论上应得到的输出数字量之间的误差小于最低位的半个字。
ADC工作原理
逐次逼近型
逐次逼近的基本原理是以Ux为基准电压,Uo为由转换器转换后的电压值,通过多次比较来不断逼近实际电压值。
举例,寄存器初始的所有位都为0,从最高位开始置1,送入D/A转换器中进行转换,然后把转换的电压Uo与Ux进行比较,如果Ux>Uo(说明转换电压小于基准电压,需要把寄存器的值加大)则该位置1,反之,如果Ux<Uo(说明转换电压大于基准电压,需要把寄存器的值减小)则该位置0,然后在第一位确定的基础是对第二位值1进行比较,不断逼近实际电压值,直到最后一位。
双积分型
双积分ADC的基本原理是对输入模拟电压和参考电压分别进行两次积分,将输入电压平均值变成与之成正比的时间间隔,然后利用时钟脉冲和计数器测出此时间间隔,进而得到相应的数字量输出。
先对输入模拟电压进行固定时间的积分,然后转为对标准电压的反相积分,直至积分输入返回初始值,这两个积分时间的长短正比于二者的大小,进而可以得出对应模拟电压的数字量。这种A/D转换器的转换速度较慢,但精度较高。由双积分式发展为四重积分、五重积分等多种方式,在保证转换精度的前提下提高了转换速度。
XPT2046驱动例程
XPT2046简介
XPT2046 是一款 4 线制电阻式触摸屏控制器,内含 12 位分辨率,125KHz 转换速率,逐步逼近型 A/D 转换器。XPT2046 支持从 1.5V 到 5.25V 的低电压 I/O 接口。XPT2046 能通过执行两次 A/D 转换查出被按的屏幕位置,除此之外, 还可以测量加在触摸屏上的压力。内部自带 2.5V 参考电压,可以作为辅助输入、 温度测量和电池监测之用,电池监测的电压范围可以从 0V 到 6V。XPT2046 片内集成有一个温度传感器。在 2.7V 的典型工作状态下,关闭参考电压,功耗可 小于 0.75mW。XPT2046 采用微小的封装形式:TSSOP-16,QFN-16 和 VFBGA-48。 工作温度范围为-40℃~+85℃。与 ADS7846、TSC2046、AK4182A 完全兼容。
控制字节由 DIN 输入控制,它用来启动转换,寻址,设置 ADC 分辨率,配置和对XPT2046 进行掉电控制。
起始位——第一位,即 S 位。控制字的首位必须是 1,即 S=1。在 XPT2046 的 DIN 引脚检测到起始位前,所有的输入将被忽略。
地址——接下来的 3 位(A2、A1 和 A0)选择多路选择器的现行通道(见表 3、表 4 和图 6),触摸屏驱动和参考源输入。
MODE——模式选择位,用于设置 ADC 的分辨率。MODE=0,下一次的转换将是 12 位模式;MODE=1,下一次的转换将是 8 位模式。
SER/DFR’——SER/DFR’位控制参考源模式,选择单端模式(SER/DFR’=1),或者差分模式(SER/DFR’=0)。在X坐标、Y坐标和触摸压力测量中,为达到最佳性能,首选差分工作模式。参考电压来自开关驱动器的电压。在单端模式下,转换器的参考电压固定为VREF相对于GND引脚的电压。
PD0 和 PD1——表 5 展示了掉电和内部参考电压配置的关系。ADC 的内部参考电压可以单独关闭或者打开,但是,在转换前,需要额外的时间让内部参考电压稳定到最终稳定值;如果内部参考源处于掉电状态,还要确保有足够的唤醒时间。ADC 要求是即时使用,无唤醒时间的。另外还得注意,当 BUSY 是高电平的时候,内部参考源禁止进入掉电模式。XPT2046 的通道改变后,如果要关闭参考源,则要重新对 XPT2046 写入命令。
单端模式和差分模式
单端模式
单端模式所得出的数值为所选通道和GND之间的电压差。
差分模式
差分模式所得出的数值为两个所选通道之间的电压差。
时序讲解
根据时序图,一次完整的转换需要24个时钟周期,我们可以把xpt2046的时序分为两个部分,分别是8个周期的写入指令和16个周期的读取数据。
写入指令
写入指令主要是DCLK和DIN的电平变换,首先,在开始转换时,我们要把CS线拉低,DCLK每发送一个脉冲,我们就可以在DIN写入一个字节/
for(i=0;i<8;i++)//写入指令
{
xpt2046_din=cammand&(0x80>>i);
xpt2046_dclk=1;
xpt2046_dclk=0;
}
读取数据
读取数据主要是DCLK和DOUT的电平变换,DCLK每发送一个脉冲,我们就可以读取一个字节的数据。
for(i=0;i<16;i++)//读取数据
{
xpt2046_dclk=1;
xpt2046_dclk=0;
if(xpt2046_dout==1)
{
date|=(0x8000>>i);
}
}
xpt2046驱动代码
函数中有两个变量,一个是输入指令,一个是分辨率设置。
在使用中,我们可以默认xpt2046达的分辨率设置为12位,通过对读取的数据进行位移来改变分辨率。
unsigned int XPT2046_ReadAD(unsigned char cammand,unsigned char bits)
{
unsigned char i=0;
unsigned int date=0x00;
xpt2046_cs=0;//
xpt2046_dclk=0;
for(i=0;i<8;i++)//写入指令
{
xpt2046_din=cammand&(0x80>>i);
xpt2046_dclk=1;
xpt2046_dclk=0;
}
for(i=0;i<16;i++)//读取数据
{
xpt2046_dclk=1;
xpt2046_dclk=0;
if(xpt2046_dout==1)
{
date|=(0x8000>>i);//
}
}
xpt2046_cs=1;
return date>>(16-bits);
}
XPT2046采集电压例程(以普中51开发板为例)
我们尝试在普中的51开发板使用XPT2046的AUX通道对电压进行采集并用数码管显示。在采集过程中我们默认为12位的分辨率。
首先,我们先配置好数码管对应数字的驱动代码。
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1); //显示一段时间
P0=0x00; //段码清0,消影
}
然后,对数字进行拆分并单独显示在数码管上
void show_number(int number,int n)
{
int i=1,s=0;
for(i=1;i<=number;i++)
{
s=n%10;
Nixie((number-i+1),s);
n=n/10;
}
}
最后,我们根据前面对XPT2046的配置教程进行最后的主函数编写,选择AUX通道对电压进行采集,并通过运算把采集出来的数值转换为电压数值。
void main()
{
int val,i;
while(1)
{
for(i=0;i<100;i++)
{
val=XPT2046_ReadAD(XPT2046_AUX,12);
val=(float)val/4096*5.0*1000;
show_number(4,val);
Delay(10);
}
val=val/100;
}
}