ADC 模数转换实验

本文详细介绍了XPT2046 ADC模块的工作原理及其在51单片机上的应用。主要内容包括ADC的基本概念、XPT2046芯片特性、硬件电路设计、软件编程方法以及如何读取和显示AD转换结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

           在日常电子系统中,我们经常需要获取环境中的模拟信号,例如温度、声音、电压、压力等。这些模拟量本质上是连续变化的物理信号,而我们使用的单片机(如51单片机)只能处理数字信号(0和1组成的二进制)。因此,必须引入一个桥梁——模数转换器(ADC,Analog-to-Digital Converter),将模拟信号转换为数字信号,以便计算机或单片机理解、存储和处理。

为什么需要模数转换?

           单片机无法“看懂”模拟信号,它只理解数字电平(高/低电平),因此需要:

  • 把温度、光强、电压等连续变化的电压信号
  • 转换成用二进制编码表示的离散数值(比如 00001100 表示 0.7V)

什么是 ADC?

           ADC(Analog-to-Digital Converter) 是一种电子器件,其功能是将模拟电压信号转换为数字量(Binary Code),便于单片机等数字系统读取。

           在单片机系统中,如果单片机本身没有集成 ADC(如标准 51 单片机),通常会通过外接 ADC 芯片来采集模拟信号。


ADC 的关键技术指标

分辨率(Resolution)

定义:ADC 能将输入模拟信号划分为多少个不同的数值段。

  • 通常以“位数比特(bit)”表示,常见如 8位、10位、12位等。
  • 每多 1 位,表示的数值精度就翻一倍。
分辨率(bit)可表示的离散值个数最小可分辨电压(以 10V 满量程为例)
8位2⁸ = 25610V / 256 ≈ 39.06mV
12位2¹² = 409610V / 4096 ≈ 2.44mV

           分辨率越高,ADC 能“看出”的电压变化就越细微。 

转换误差(Conversion Error)

定义:ADC 实际输出值与理论应输出值之间的偏差。

  • 通常用 **LSB(Least Significant Bit,最小有效位)**的倍数表示。
  • 例如:某 ADC 标称最大误差为 ±0.5 LSB,表示误差不会超过 1 个最小数字单位的一半。

           误差产生的原因包括参考电压不稳定、温度漂移、器件非线性等。

转换速率(Sampling Rate)

定义:ADC 每秒最多完成的转换次数,单位通常是 SPS(Samples Per Second)Hz

  • 速率越快,就能越精准捕捉到快速变化的模拟信号。
  • 常见采样速率从几千到几百万次每秒不等。

           每次转换所需的时间也包括“采样”、“保持”和“转换”阶段。

           ADC 是连接模拟世界和数字世界的桥梁,分辨率越高、速率越快、误差越小,转换效果就越理想。

示例

           假设你使用一个 10 位 ADC,输入信号范围是 0~5V:

  • 10 位 ADC → 可分成 2¹⁰ = 1024 个等级
  • 每个等级表示的电压 = 5V / 1024 ≈ 4.88mV

           如果你采集到电压为 2.44V,则:数字输出≈2.44V÷4.88mV≈500(十进制)≈0b0111110100(二进制),单片机看到的就是 0x1F4。

ADC 转换原理

           ADC(模数转换器)通过以下四个步骤实现模拟量到数字量的转换:采样、保持、量化和编码。

           采样:将时间连续的模拟信号转换为时间离散的信号(类似于微积分中的离散化处理方法)。采样过程如图所示:

            保持:将采样结果存储并保持,直到下一次采样操作。采样器和保持电路通常集成在一起,称为采样保持电路

            量化:将采样得到的模拟电平值近似为最接近的离散数字电平。

            编码:将量化后的结果按照特定数制转换为数字代码。

            根据转换方法的不同,ADC主要分为两种类型:

  • 直接比较型:是将输入模拟信号直接与标准的参考电压比较,从而得到数字量。常见的有并行 ADC 和逐次逼近型 ADC。
  • 间接比较型:输入模拟量不是直接与参考电压比较,而是将二者变为中间的某种物理量再进行比较,然后将比较所得的结果进行数字编码。常见的有双积分型 ADC。

           在实际应用中,逐次逼近型ADC和双积分型ADC是最常见的两种转换方案。

逐次渐近型型 ADC

          结构如下图所示,该模数转换器由比较器、D/A数模转换器(DAC)、N位逐次渐近寄存器、输出锁存缓存器和控制逻辑电路组成:

              工作原理:逐次渐近型A/D转换器是一种反馈比较型A/D转换器,采用从高位到低位的逐次渐近方式比较,它的转换原理与天平称物体重量的过程相似。先放一个最重的砝码与被称物体重量进行比较,如砝码比物体轻,则砝码保留;如砝码比物体重,则去掉,换上一个次重量的砝码,再与被称物体的重量进行比较。按照此方法,直加到最轻的一个砝码为止。将所有留下的砝码重量相加,就是最接近被称物体的重量。根据这一思路可构成逐次渐近型A/D转换器。

          具体转换步骤如下:

  1. 初始化阶段将逐次渐近寄存器所有位(D7~D0)清零;
  2. 转换启动后,首先将逐次渐近寄存器最高位D7置位为1,经转换器DAC转换后得到模拟电压U0;
  3. 将U0与待转换的模拟量 Ux比较:若U0<Ux,则说明置入的数字量偏小,保留D7位的1,否则清除D7位;
  4. 重复上述过程,依次对D6至D0各位进行置位、转换和比较;
  5. 转换完成后,将逐次逼近寄存器的数值存入锁存缓存器输出。

          整个逐次逼近过程由控制电路精确协调完成。

双积分型 ADC

              双积分型A/D转换器是一种间接型A/D转换器,它是将输入的模拟电压转换成与之成正比的时间间隔,然后利用计数器在此时间内对标准时钟脉冲进行计数,计数器输出的计数结果就是对应的数字量。

              其基本结构如下图所示,主要由基准电压VREF、积分器、过零比较器、计数器、定时触发器、时钟控制门等部分组成。:

积分器。由运算放大器和RC电路组成,它是A/D转换器的核心部分。由于运算放大器具有很高的输入阻抗,因此,流经电阻R和电容C的电流相等。通过开关S2对被测模拟电压 Vi 和与其极性相反的基准电压-V _{REF}进行两次方向相反的积分,时间常数 τ=RC。这也是双积分A/D转换器的来历。

过零比较器。它在积分器之后,用以检查积分器输出电压Uo的过零时刻。当Uo>=0时,比较器的积分输出Uc=0;当Uo<0时,Uc=1。过零比较器的输出信号用以控制时钟控制门G(在图中控制逻辑里)的开通与关闭。

时钟控制门。它有三个输入端,一个接过零比较器的输出Uc,第二个接转换控制信号Us,第三个接标准时钟脉冲源CP,其周期Tc作为测量时间间隔的标准时间。当Uc=1,Us=1时,时钟控制门打开,计数器对时钟脉冲CP计数;当Uc=0时,时钟控制门关闭,计数器停止计数。

计数器和定时触发器。计数器由n个触发器组成,用以对输入时钟脉冲CP 进行计数。当计到2"个时钟脉冲时,触发器由11…1回到00…0状态,最高位触发器的输出端输出进位信号使定时触发器置1,即定时触发器的输出端Q=1,电子开关接基准电压-V _{REF},计数器由0开始计数,将与输入模拟电压 Vi 成正比的时间间隔转换成数字量。

              具体转换过程如下:

  1. 电子开关开关首先接通待转换模拟量Vi,Vi 采样后输入至积分器
  2. 积分器从零开始进行固定时长T的正向积分\int_{0}^{T}
  3. 时间T到达后,开关切换至与Vi极性相反的基准电压V _{REF}
  4. 积分器开始反向积分\int_{T}^{0},直至输出为 0V 时停止积分
  5. 模拟电压 Vi越大,积分器输出电压越高,反向积分时间也越长
  6. 计数器在反向积分时间内记录的计数值,即为Vi对应的数字量

              通过上述过程完成模拟量到数字量的转换。

 XPT2046 芯片简介

                XPT2046 是一款专为电阻式触摸屏设计的 4 线制控制芯片,集成了 12 位分辨率、125KHz 转换速率的逐次逼近型 A/D 转换器。

主要特性概览:

特性说明
ADC 类型逐次逼近型 SAR ADC(12 位)
最大转换速率125kHz
输入电压范围1.5V ~ 5.25V(供电 & IO)
通信方式SPI 三线同步串口
内部参考电压2.5V
附加功能支持压力检测、温度检测、电池电压测量
低功耗工作在 2.7V、关闭内部参考电压时功耗 < 0.75mW
工作温度范围-40℃ ~ +85℃
封装形式TSSOP-16、QFN-16、VFBGA-48
兼容性与 ADS7846、TSC2046 等完全兼容

芯片管脚说明

                XPT2046 是一种典型的逐次逼近型模/数转换器(SAR ADC),包含采样、保持、模数转换、串口数据输出等功能。同时芯片集成有一个 2.5V 的内部参考电压源、温度检测电路,工作时使用外部时钟。XPT2046 可以单电源供电,电源电压范围为 2.7V~5.5V。参考电压值直接决定 ADC 的输入范围,参考电压可以使用内部参考电压,也可以从外部直接输入参考电压(要求外部参考电压源输出阻抗低)。X、Y、Z、VBAT、Temp 和 AUX 模拟信号经过片内的控制寄存器选择后进入 ADC,ADC 可以配置为单端或差分模式。选择 VBAT、Temp 和 AUX 时应该配置为单端模式;作为触摸屏应用时,应该配置为差分模式,这可有效消除由于驱动开关的寄生电阻及外部的干扰带来的测量误差,提高转换精度。单端和差分模式输入配置如下图所示:

                 XPT2046 数据接口是串行接口,其典型工作时序如下图所示,图中展示的信号来自带有基本串行接口的单片机或数据信号处理器。处理器和转换器之间的的通信需要 8 个时钟周期,可采用 SPI、SSI 和 Microwire 等同步串行接口。一 次完整的转换需要 24 个串行同步时钟(DCLK)来完成。

                  前 8 个时钟用来通过 DIN 引脚输入控制字节。当转换器获取有关下一次转换的足够信息后,接着根据获得的信息设置输入多路选择器和参考源输入,并进入采样模式,如果需要,将启动触摸面板驱动器。3 个多时钟周期后,控制字节设置完成,转换器进入转换状态。这时,输入采样-保持器进入保持状态,触摸面板驱动器停止工作(单端工作模式)。接着的 12 个时钟周期将完成真正的模数转换。如果是度量比率转换方式(SER/DFR=0),驱动器在转换过程中将一直 工作,第 13 个时钟将输出转换结果的最后一位。剩下的 3 个多时钟周期将用来完成被转换器忽略的最后字节(DOUT 置低)。

                  在对 XPT2046 进行控制时,控制字节由 DIN 输入的控制字命令格式如下所示:

                  如果采用单端模式测量 X 坐标、Y 坐标和触摸压力,则需要添加一个外部参考电压,并且 XPT2046 的电源也必须来自这个外部参考源。需要特别注意的一点是,当使用单端模式时,输入 ADC 的电压不能超过内部参考电压,尤其是当工作电压大于 2.7V 的时候。

                  注意:差分模式仅用于 X 坐标、Y 坐标和触摸压力的测量,其它测量要求采用单端模式。

                  如果想要更详细的了解XPT2046 芯片其工作原理,可以查看芯片资料链接: https://pan.baidu.com/s/1OxNovNPMV0DAVFxfoaZ10A?pwd=6wr6 提取码: 6wr6 。

硬件部分

        使用到硬件资源如下:

  1. 动态数码管
  2. ADC 模块

        动态数码管电路在前面动态数码管实验中介绍过,不再重复。ADC 模块电路如下图所示:

         ADC 模块电路独立,XPT2046 芯片的控制管脚接至 J33 端子上,XPT2046 芯片的 ADC 输入转换通道分别接入了 AD1 电位器、NTC1 热敏传感器、GR1 光敏传感器,还有一个外接通道 AIN3 接在 DAC 模块的 J52 端子上供外部模拟信号检测。

         可以使用任意单片机管脚连接XPT2046 芯片的控制管脚,使用 P3.4 管脚与芯片的 DIN 管脚连接,P3.5 管脚与芯片的 CS 管脚连接,P3.6 管脚与芯片的 CLK 管脚连接,P3.7 管脚与芯片的 DOUT 管脚连接。

软件部分

         所要实现的功能是:数码管上显示 AD 模块采集电位器的电压值。

         程序框架如下:

  1. 编写数码管显示功能
  2. 编写 ADC 转换函数
  3. 编写主函数

 数码管显示

#include "smg.h"

//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void smg_display(u8 dat[],u8 pos) //dat[]形参的实际参数为gsmg_code[ ],pos形参的实际参数为i-pos_temp
{
 	u8 i=0;
	u8 pos_temp=pos-1;//数码管显示位置

	for(i=pos_temp;i<8;i++)
	{
	 	switch(7-i)//位选
		{
		 	case 0:LSC=1;LSB=1;LSA=1;break;
			case 1:LSC=1;LSB=1;LSA=0;break;
			case 2:LSC=1;LSB=0;LSA=1;break;
			case 3:LSC=1;LSB=0;LSA=0;break;
			case 4:LSC=0;LSB=1;LSA=1;break;
			case 5:LSC=0;LSB=1;LSA=0;break;
			case 6:LSC=0;LSB=0;LSA=1;break;
			case 7:LSC=0;LSB=0;LSA=0;break;
		}
		SMG_A_DP_PORT=dat[i-pos_temp];//传送段选数据
		delay_10us(100);//延时一段时间,等待显示稳定
		SMG_A_DP_PORT=0x00;//消音
	}
}

ADC 读写函数

         根据XPT2046 时序图可知,XPT2046 完成一个完整的转换需要 24 个串行时钟,也就是需要 3 个字节的 SPI 时钟。XPT2046 前 8 个串行时钟,是接收 1 个字节的转换命令,接收到转换命令了之后,然后使用 1 个串行时钟的时间来完成数据转换(当然在编写程序的时候,为了得到精确的数据,可以适当的延时一下) ,然后返回 12 个字节长度(12 个字节长度也计时 12 个串行时 钟)的转换结果。然后最后 4 个串行时钟返回 4 个无效数据,可以忽略。                                                xpt2046_read_adc_value 函数就是按照这个时序实现。至于 xpt2046_wirte_data 和 xpt2046_read_data 函数是 IO 口模拟的 SPI 读写时序,与 DS1302 的读写是一样的。

#include "xpt2046.h"
#include "intrins.h"

void xpt2046_write_data(u8 dat)//XPT2046写数据,dat:写入的数据
{
 	u8 i;
	
	DCLK=0;
	_nop_();//该函数是在51单片机中用的延时函数,表示执行一条没有什么意义的指令,延时一个指令周期
	for(i=0;i<8;i++)
	{
	 	DIN=dat>>7;//先传高位再传低位
		dat<<=1;//为下一次(DIN=dat>>7)做准备,把次高位移到最高位,然后右移7位,将次高位传输
		DCLK=1;//CLK产生一个上升沿,从而写入数据
		_nop_();
		DCLK=0;
		_nop_();
	}
}

u16 xpt2046_read_data(void)//XPT2046读数据
{
 	u8 i;
	u16 dat=0;

	DCLK=0;
	_nop_();
	for(i=0;i<12;i++)//循环12次,每次读取一位,大于一个字节数,所以返回值类型是u16
	{
	 	dat<<=1;
		DCLK=1;
		_nop_();
		DCLK=0;//DCLK产生一个下降沿,从而读取数据
		_nop_();
		dat|=DOUT;//先读取高位,在读取低位
	}
	return dat;
}

u16 xpt2046_read_adc_value(u8 cmd)//XPT2046读AD数据,cmd:指令
{
 	u8 i;
	u16 adc_value=0;

	DCLK=0;
	CS=0;//使能xpt2046
	xpt2046_write_data(cmd);//发送命令字
	for(i=6;i>0;i--);//延时等待转换结果
	DCLK=0;
	_nop_();
	DCLK=1;//发送一个时钟,清除BUSY
	_nop_();
	adc_value=xpt2046_read_data();
	CS=1;//关闭XPT2046
	return adc_value;
}

主函数

         主函数代码首先调用外设头文件,然后定义一些变量存储 AD 值和电压值,进入 while 循环,读取光敏传感器的 AD 值,根据 XPT2046 单端模式输入配置表可知,要采集 Vbat通道的信号,则配置值为 0XA4。得到 AD 值后,可按照如下公式计算电压值:

Vref*ADC_Value/分辨率

         其中 Vref 是参考电压,XPT2046 接入的是 5V,ADC_Value 是读取的 AD 值, 分辨率是 ADC 的位数(2^{12}=4096)。

#include "public.h"
#include "smg.h"
#include "xpt2046.h"

void main()
{	
	u16 adc_value=0;
	u8 adc_buf[4];

	while(1)
	{				
		adc_value=xpt2046_read_adc_value(0xA4);//测量光敏电阻
		adc_buf[0]=gsmg_code[adc_value/1000];
		adc_buf[1]=gsmg_code[adc_value%1000/100];
		adc_buf[2]=gsmg_code[adc_value%1000%100/10];
		adc_buf[3]=gsmg_code[adc_value%1000%100%10];
		smg_display(adc_buf,5);		
	}		
}

         源代码链接:通过网盘分享的文件:23-ADC模数转换实验.zip
链接: https://pan.baidu.com/s/1WAb1qC7LTI6Xfrp-J4C0HQ 提取码: jzac

现象

        光线较暗时:

         光线明亮时:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值