【51单片机快速入门指南】5.2:SPI读取 12位ADC XPT2046 芯片
2022-07-15 来源:csdn
普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位机:Vofa+ 1.3.10
硬知识
摘自《普中 51 单片机开发攻略》、《XPT2046用户手册V2.0》。
ADC 简介
ADC(analog to digital converter)也称为模数转换器,是指一个将模拟 信号转变为数字信号。单片机在采集模拟信号时,通常都需要在前端加上 A/D 芯 片。下面我们看下 ADC 的主要技术指标:
分辨率
ADC 的分辨率是指对于允许范围内的模拟信号,它能输出离散数字信号值的 个数。这些信号值通常用二进制数来存储,因此分辨率经常用比特作为单位,且 这些离散值的个数是 2 的幂指数。 例如:12 位 ADC 的分辨率就是 12 位,或者说分辨率为满刻度的 1/(2^12)。 一个 10V 满刻度的 12 位 ADC 能分辨输入电压变化最小值是
。
转换误差
转换误差通常是以输出误差的最大值形式给出。它表示 A/D 转换器实际输出 的数字量和理论上的输出数字量之间的差别。常用最低有效位的倍数表示。例如 给出相对误差≤±LSB/2,这就表明实际输出的数字量和理论上应得到的输出数 字量之间的误差小于最低位的半个字。
转换速率
ADC 的转换速率是能够重复进行数据转换的速度,即每秒转换的次数。而完 成一次 A/D 转换所需的时间(包括稳定时间),则是转换速率的倒数。
ADC 转换原理
AD 转换器(ADC)将模拟量转换为数字量通常要经过 4 个步骤:采样、保持、 量化和编码。所谓采样即是将一个时间上连续变化的模拟量转换为时间上离散变化的模拟量。如下图所示:
将采样结果存储起来,直到下次采样,这个过程叫做保持。一般采样器和保持电路一起总称为采样保持电路。将采样电平归化为与之接近的离散数字电平, 这个过程叫做量化。将量化后的结果按照一定数制形式表示就是编码。将采样电 平(模拟值)转换为数字值时,主要有两类方法:直接比较型与间接比较型。
直接比较型:就是将输入模拟信号直接与标准的参考电压比较,从而得到数字量。常见的有并行 ADC 和逐次比较型 ADC。
间接比较型:输入模拟量不是直接与参考电压比较,而是将二者变为中间 的某种物理量在进行比较,然后将比较所得的结果进行数字编码。常见的有双积分型 ADC。
下面就以常用的逐次比较型 ADC 和双积分型 ADC 介绍其工作原理。
逐次逼近型 ADC
采用逐次逼近法的 AD 转换器是有一个比较器、DA 转换器、缓冲寄存器和控 制逻辑电路组成,如下图所示:
基本原理是:从高位到低位逐次试探比较,就像用天平秤物体,从重到轻逐级增减砝码进行试探。逐次逼近法的转换过程是:初始化时将逐次逼近寄存器各位清零,转换开始时,先将逐次逼近寄存器最高位置 1,送入 DA 转换器,经 DA 转换后生成的模拟量送入比较器,称为 U0,与送入比较器的待转换的模拟量 Ux 进行比较,若 U0 双积分型 ADC 采用双积分法的 AD 转换器由电子开关、积分器、比较器和控制逻辑等部件组成。如下图所示: 其基本原理:将输入电压变换成与其平均值成正比的时间间隔,再把此时间 间隔转换成数字量,属于间接转换。双积分法 AD 转换的过程是:先将开关接通 待转换的模拟量 Vi,Vi 采样输入到积分器,积分器从零开始进行固定时间 T 的 正向积分,时间 T 到后,开关再接通与 Vi 极性相反的基准电压 Vref,将 Vref 输入到积分器,进行反向积分,直到输出为 0V 时停止积分。Vi 越大,积分器输 出电压越大,反向积分时间也越长。计数器在反向积分时间内所计的数值,就是 输入模拟电压 Vi 所对应的数字量,实现了 AD 转换。 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 完全兼容。 XPT2046 是一种典型的逐次逼近型模数转换器(SAR ADC),包含了采样/保持、模数转换、串口数据 输出等功能。同时芯片集成有一个 2.5V 的内部参考 电压源、温度检测电路,工作时使用外部时钟。XPT2046 可以单电源供电,电源 电压范围为 2.7V~5.5V。参考电压值直接决定 ADC 的输入范围,参考电压可以 使用内部参考电压,也可以从外部直接输入 1V~VCC 范围内的参考电压(要求 外部参考电压源输出阻抗低)。X、Y、Z、VBAT、Temp 和 AUX 模拟信号经过片内 的控制寄存器选择后进入 ADC,ADC 可以配置为单端或差分模式。选择 VBAT、Temp 和 AUX 时应该配置为单端模式;作为触摸屏应用时,应该配置为差分模式,这可 有效消除由于驱动开关的寄生电阻及外部的干扰带来的测量误差,提高转换精度。单端和差分模式输入配置如下图所示: 参考电压 内部参考电压 XPT2046 的内部 2.5V参考电压源可通过控制位PD1进行关闭或者打开。一般地,内部参考电压只用于单端模式下VBAT、Temp和AUX输入测量。使用差分模式,触摸屏可以获得最佳性能。 如果要与ADS7843 兼容,XPT2046 的内部参考电压源必须强行关闭。因此,上电后要对控制位PD1 置 0以确保关闭内部参考源(见典型特性中参考电压从掉电到上电时间的关系)。 外部参考电压输入 +REF和-REF之间的电压差(下文用VREF表示)决定了模拟输入的电压范围。XPT2046 的参考电压输入范围为 1V~ VCC。参考电压越低,则ADC输出的二进制数据结果每一个数字位所代表的模拟电压也越低。 在 12 位工作方式下,数据结果的最低位所代表的模拟电压为VREF/4096,其余位依此类推。因此,参考电压越低,干扰引入的误差会越大,此时要求尽可能使用低噪声、低波动的参考电压源;在设计电路板时,尽可能减少干扰,输入的信号噪音也不能太高,否则会直接影响转换精度。 工作模式 单端工作模式 SER/DFR’置为高电平时,XPT2046 工作在为单端模式,单端工作模式的应用原理图 7 所示。 单端模式简单,在采样过程完成后,转换过程中可以关闭驱动开关,降低功耗。但这种模式的缺点是精度直接受参考电压源的精度限制,同时由于内部驱动开关的导通电阻存在,导通电阻与触摸屏电阻的分压作用,也会带来测量误差。 差分工作模式 SER/DFR’置为低电平时,XPT2046 为差分工作模式,如图 8 所示。 差分模式的优点是:+REF 和-REF 的输入分别直接接到 YP、YN 上,可消除由于驱动开关的导通电阻引入的坐标测量误差。缺点是:无论是采样还是转换过程中,驱动开关都需要接通,相对单端模式而言,功耗增加了。 温度测量 XPT2046 集成温度检测功能,用于温度的检测。XPT2046 的温度测量有两种方法。 方法一:直接测量 利用二极管的 PN 结温度系数相对稳定的特点,通过测试二极管的 PN 结电压来测量温度,可以预先 测试并存储室温下的 PN 结电压(典型值为 600mV 左右),PN 结的温度系数约为-2mV/℃,测试其他 温度时的 PN 结电压,就可以得到温度。这种方法测试出的温度随工艺的变化有较大变化,而且需要校正。 方法二:间接测量 注意:由于每个测温二极管的偏置电流仅仅工作 3 个采样时钟周期(仅采样期间),因此,功耗的上升是不明显的,尤其是温度测量仅仅是偶尔出现,此时的 XPT2046 内部的结温可以代表环境温度。 电池电压测量 如图 11 所示,电池电压可以从 0V到 6V之间变化,输入电压(VBAT)经过分压(1/4)后输入至ADC,所以 5.5V的电池电压被化成 1.375V输入到ADC,这样也简化了复选器和控制逻辑。为了降低功耗,分压电路仅仅工作在当A2A1A0=“010”的采样周期。 压力测量 XPT2046 也能对触摸的压力进行处理。为了判断触摸物体是笔还是手指,有必要对触摸压力进行测量。一般而言,这种测量的性能要求不高,所以采用 8 位分辨率模式(但是,下面的计算是采用 12 位分辨率模式的)即可。有好几种不同的方法实现本测量。第一种方法需要知道 X 面板的电阻,X 位置的测量值,触摸屏两附加面板之间的测量值(Z1 和 Z2),如图 12 所示。可用公式(3)计算该触摸电阻: 第二种方法要求测出 X 面板和 Y 面板的电阻,X 和 Y 的位置,和 Z1 的位置。可采用公式(4)计算触摸电阻: 数字接口 XPT2046 数据接口是串行接口,其典型工作时序如图 12 所示,图中展示的信号来自带有基本串行接口的单片机或数据信号处理器。处理器和转换器之间的的通信需要 8 个时钟周期,可采用 SPI、SSI 和Microwire 等同步串行接口。一次完整的转换需要 24 个串行同步时钟(DCLK)来完成。 前 8 个时钟用来通过DIN引脚输入控制字节。当转换器获取有关下一次转换的足够信息后,接着根据获得的信息设置输入多路选择器和参考源输入,并进入采样模式,如果需要,将启动触摸面板驱动器。3个多时钟周期后,控制字节设置完成,转换器进入转换状态。这时,输入采样-保持器进入保持状态,触摸面板驱动器停止工作(单端工作模式)。接着的 12 个时钟周期将完成真正的模数转换。如果是度量比率转换方式(SER/DFR’=0),驱动器在转换过程中将一直工作,第 13 个时钟将输出转换结果的最后一位。剩下的 3 个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)。 控制字节由 DIN 输入的控制字如表 5 所示,它用来启动转换,寻址,设置 ADC 分辨率,配置和对XPT2046 进行掉电控制。图 12、表 5 和表 6 给出控制字的各控制位的详细说明。 起始位——第一位,即 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 写入命令。 如果采用单端模式测量 X 坐标、Y 坐标和触摸压力,则需要添加一个外部参考电压,并且 XPT2046的电源也必须来自这个外部参考源。需要特别注意的一点是,当使用单端模式时,输入 ADC 的电压不能超过内部参考电压,尤其是当工作电压大于 2.7V 的时候。 注意:差分模式仅用于 X 坐标、Y 坐标和触摸压力的测量,其它测量要求采用单端模式。 笔中断输出 笔中断输出功能如图 13 所示。在PD0=0 的掉电状态下,Y驱动器工作,触摸屏的Y-面板被连到GND。PENIRQ’输出通过两个开关和XP输入连在一起。当屏幕上有触摸动作时,XP输入通过触摸屏下拉到地。 在XPT2046 的绝大部分工作方式下,内部上拉电阻标称值是 50KΩ,但它的实际值可随温度的变动而在 36 KΩ~67 KΩ之间波动。为了确保出现在PENIRQ’电路中的逻辑 0 电平电压低于 0.35·VCC,XP和YN之间的总电阻必须小于 21KΩ。 需要注意的是,上拉电阻越高,PENIRQ’对触摸屏的反应也就也越慢,所以,编写软件时要考虑到这一点。 由于电流通过触摸屏流到地,PENIRQ’变低并作为处理器的中断信号。在测量X、Y和Z坐标的过程中,XP输入将与PENIRQ’内部上拉电阻分离,这样可以避免来自这个内部上拉电阻的漏电流流过触摸屏,同时也避免了误差。此外,在X、Y和Z坐标测量中,PENIRQ’被禁止,输出为低电平;在测量VBAT、AUX和temp过程中,PENIRQ’被禁止,输出为高电平。如果最后写进XPT2046 的控制字包含了PD0=1,笔中断输出功能禁止,不能监测触摸屏上触摸动作。在这些情况下,要重新使能笔中断输出功能,需把带有PD0=0 的控制字写入XPT2046。如果在最后写入的控制字中包含了PD0=0,笔中断输出将在这次转换结束后使能。转换结束发生在输出转换数据位 1 时的DCLK时钟的下降沿。建议无论在任何时候,处理器在发控制字给XPT2046 之前都要屏蔽PENIRQ’的中断,以避免错误的中断的触发。 转换周期 16 时钟周期转换 n+1 次转换的控制位可以与第 n 次转换部分重叠,所以可以用 16 个时钟周期完成一次转换,如图15 所示。图 14 也说明了处理器和转换器之间的串行通信是可以双向独立进行的。此时,每次转换必须在开始后(接收到 start)的 1.6mS 内完成,否则输入采样保持电路取样的信号会逐渐被放电衰减,影响转换结果。另外,在转换过程中另一串行通信的存在会使 XPT2046 工作于全功耗状态下。 数字时序 15 时钟周期转换 图 16 给出了 XPT2046 的最快时序。这种方法不支持大部分的微控制器和数字信号处理器的串行接口,因为它们一般都不提供 15 周期的串行传输方式。但是,这种方法适用于 FPGA 和 ASIC。需要注意的是,这样有效地提高了转换器的最大转换速率。 数据格式 XPT2046 的输出数据格式是标准二进制格式。图 17 给出了不同电压对应的理想输出编码。 8 位转换模式 在不影响输出精度的前提下提高数据吞吐量,XPT2046 可以采用 8 位的转换模式。切换到 8 位转换模式,完成提前 4 个时钟完成一次转换。不仅每次转换缩短了都 4 位(数据吞吐量提高了 25%),而且由于精度的降低,可以工作在更快的转换速率下,时钟速度可以提高 50%,时钟速度的提高和转换周期的减少,共同可以使转换速率提高 2 倍。 示例程序 stdint.h见【51单片机快速入门指南】1:基础知识和工程创建 软件SPI程序见【51单片机快速入门指南】5:软件SPI 串口部分见【51单片机快速入门指南】3.3:USART 串口通信 根据时序图,SPI选择模式0。 XPT2046.c #include 'XPT2046.h' #include 'intrins.h' #include './Soft_SPI/Soft_SPI.h' //xpt2046_拉高 移植时需修改 void xpt2046_CS_H() { xpt2046_CS = 1; } //xpt2046_CS拉低 移植时需修改 void xpt2046_CS_L() { xpt2046_CS = 0; } /******************************************************************************* * 函 数 名 : xpt2046_wirte_data * 函数功能 : XPT2046写数据 * 输 入 : dat:写入的数据 * 输 出 : 无 *******************************************************************************/ void xpt2046_wirte_data(uint8_t dat) { SOFT_SPI_RW_MODE0(dat); } /******************************************************************************* * 函 数 名 : xpt2046_read_data * 函数功能 : XPT2046读数据 * 输 入 : 无 * 输 出 : XPT2046返回12位数据 *******************************************************************************/ uint16_t xpt2046_read_data(void) { uint8_t i; uint16_t dat = 0; i = SOFT_SPI_RW_MODE0(0x00); dat = ((uint16_t)i) << 8 | SOFT_SPI_RW_MODE0(0x00); dat >>= 3; return dat; } /******************************************************************************* * 函 数 名 : xpt2046_read_adc_value * 函数功能 : XPT2046读AD数据 * 输 入 : cmd:指令 * 输 出 : XPT2046返回AD值 *******************************************************************************/ uint16_t xpt2046_read_adc_value(uint8_t cmd) { uint16_t adc_value; xpt2046_CS_L(); xpt2046_wirte_data(cmd);//发送命令字 adc_value = xpt2046_read_data(); xpt2046_CS_H(); //关闭XPT2046 return adc_value; } XPT2046.h #ifndef XPT2046_H_ #define XPT2046_H_ #include 'stdint.h' #include //管脚定义 sbit xpt2046_CS = P3^5; //片选 //函数声明 uint16_t xpt2046_read_adc_value(uint8_t cmd); #endif 测试程序 根据原理图修改引脚: main.c 依次测量Xp, Vbat, Yp, AUX脚的电压值。实际电路中它们分别与电位器、光敏电阻、热敏电阻、DAC1相连。 实测VDD为5.122V #include #include 'intrins.h' #include 'stdint.h' #include 'USART.h' #include 'XPT2046.h' void Delay1ms() //@22.1184MHz { unsigned char i, j; _nop_(); i = 4; j = 146; do { while (--j); } while (--i); } void Delay_ms(int i) { while(i--) Delay1ms(); } #define VDD 5.122 void main(void) { float Xp, Vbat, Yp, AUX; USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 22118400, 115200, DOUBLE_BAUD_ENABLE, USART_TIMER_1); while(1) { Xp = VDD*xpt2046_read_adc_value(0x94)/4096; Vbat = VDD*xpt2046_read_adc_value(0xa4)/4096; Yp = VDD*xpt2046_read_adc_value(0xd4)/4096; AUX = VDD*xpt2046_read_adc_value(0xe4)/4096; printf('%f, ', Xp); printf('%f, ', Vbat); printf('%f, ', Yp); printf('%frn', AUX); } } 实验现象 实测电位器电压为4.404V ADC转换结果为4.390464V,误差0.31% 实测DAC1为2.723V ADC转换结果为2.726065V,误差0.11% 遮挡光敏电阻,波形有明显变化 手捂住热敏电阻,波形明显上升