ADC 模数转换实验

           生活中的模拟信号,如温度、声音、压力等,需要转换为更方便储存、处理和发射的数字形式。 51 单片机无法直接操作这些模拟量,其系统内部时运算都是数字量 0 和 1,因此必须将模拟量转换成数字量。数字量,指的是用一系列 0 和 1 组成的二进制代码表示某个信号大小的量。用数字量表示一个模拟量时,数字位数可以多也可以少,位数越多表示精度越高, 位数越少表示精度越低。

ADC 简介

           模数转换器ADC(analog to digital converter),是指将一个模拟信号转变为数字信号。单片机在采集模拟信号时,通常都需要在前端加上 A/D 芯片。

           ADC 的主要技术指标:

分辨率

           分辨率是指,对于允许范围内的模拟信号,输出离散数字信号值的个数。这些信号值通常用二进制数来存储,因此分辨率经常用比特(bit)作为单位,且离散值的个数是 2 的幂指数。

           例:12 位 ADC 的分辨率就是 12 位,或者说分辨率为满刻度的 \frac{1}{2^{12}}。 一个 10V 满刻度的 12 位 ADC 能分辨输入电压变化的最小值为:

10\cdot \frac{1}{2^{12}}= 0.00244v=2.4mv

转换误差

           转换误差通常是以输出误差的最大值形式给出,表示 A/D 模/数转换器实际输出的数字量理论输出数字量之间的差别,常用最低有效位的倍数表示。例如给出相对误差:\leq \pm \frac{LSB}{2},表示实际输出的数字量和理论上的输出数字量之间的误差小于最低位的半个字,LSB为最小数字量的模拟变化量。

转换速率

           转换速率是指能够重复进行数据转换的速度,即每秒 A/D 模/数转换的次数。一次 A/D 转换所需的时间包括稳定时间。

ADC 转换原理

           ADC将模拟量转换为数字量,通常需要经过 4 个步骤:采样、保持、 量化和编码。

           采样:是指将一个时间上的连续信号转换为时间上的离散信号(类似于推导微积分的时候采用的方法)。如下图所示:

ADC 模数转换实验_第1张图片

            保持:是指存储采样结果,直到下次采样。通常将采样器和保持电路统称为采样保持电路

            量化是指将采样电平归化为与之接近的离散数字电平。

            编码是指将量化后的结果按照一定数制形式表示。

            将采样电平(模拟值)转换为数字值(0或1),主要有两类方法:直接比较型与间接比较型。

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

           通常使用的方法是逐次逼近型 ADC 和双积分型 ADC 。

逐次逼近型 ADC

          如下图所示,A/D 转换器由比较器、D/A 转换器、缓冲寄存器和控制逻辑电路组成:

ADC 模数转换实验_第2张图片

              原理:从高位到低位逐次试探比较,就像用天平秤物体,从重到轻逐级增减砝码进行试探。逐次逼近法的转换过程是:初始化时将逐次逼近寄存器(图中锁存缓存器)各位(D7~D0)清零,转换开始时,先将逐次逼近寄存器最高位D7置 1,送入 D/A 转换器,经 D/A 转换后生成的模拟量送入比较器,称为 U0,与送入比较器的待转换的模拟量 Ux 进行比较,若 U0

双积分型 ADC

              如下图所示, A/D 转换器由电子开关、积分器、比较器和控制逻辑等部件组成:

ADC 模数转换实验_第3张图片

                原理:将输入电压变换成与其平均值成正比时间间隔,再把此时间间隔转换成数字量,属于间接转换。双积分法 A/D 转换的过程:先将开关接通待转换的模拟量 Vi,Vi 采样输入到积分器,积分器从零开始进行固定时间 T 的正向积分\int_{0}^{T},时间 T 到后,开关再接通与 Vi 极性相反的基准电压 Vref,将 Vref 输入到积分器,进行反向积分\int_{T}^{0},直到输出为 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 完全兼容。

主要特性

  • 工作电压范围为 1.5V~5.25V
  • 支持 1.5V~5.25V 的数字 I/O 口
  • 内建 2.5V 参考电压源
  • 电源电压测量( 0V~6V)
  • 内建结温测量功能
  • 触摸压力测量
  • 采用 3 线制 SPI 通信接口
  • 具有自动省电功能

芯片管脚说明

ADC 模数转换实验_第4张图片

ADC 模数转换实验_第5张图片

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

ADC 模数转换实验_第6张图片

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

ADC 模数转换实验_第7张图片

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

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

ADC 模数转换实验_第8张图片

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

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

ADC 模数转换实验_第9张图片

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

硬件部分

        使用到硬件资源如下:

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

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

ADC 模数转换实验_第10张图片

         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);		
	}		
}

         源代码链接:链接: https://pan.baidu.com/s/1nLIbTWupXMcM53VYYYFrfQ?pwd=abwt 提取码: abwt 

现象

        光线较暗时:

ADC 模数转换实验_第11张图片

         光线明亮时:

ADC 模数转换实验_第12张图片

你可能感兴趣的:(51单片机,单片机,嵌入式硬件,c语言,物联网)