(十六)ADC转换实验

这篇博客介绍了如何利用XPT2046 AD芯片进行模拟电压到数字量的转换,以读取并显示滑动变阻器的电压变化。文中详细阐述了ADC的概念,包括分辨率、转换误差和转换速率等关键参数,并解释了ADC转换的采样、量化和编码三个步骤。硬件部分讲解了XPT2046的特性及其与51单片机的连接方式,软件部分则给出了XPT2046的读写程序以及数码管显示的实现。
摘要由CSDN通过智能技术生成

        本节主要是回顾有关于ADC的对应内容,我们这章通过一个AD芯片xpt2046来读取外部电压的变化,将电压的数字量显示在数码管上。

关于ADC:

        我们都知道单片机内部都是数字量,就是1或者0,而我们的电流电压在传递的时候是模拟量,也就是模拟量很可能是一个动态连续的电压,如果我们直接把这个电压放到单片机上,通过我们内部电路转化,大于多少电压值的为1,小于多少电压的为0,但是这个并不能表示电压值的具体大小,所以有了ADC来把模拟电压值转化为多位数字电压值,而你转化的电压的位数越多,说明你的转化越准确。那么对于一个ADC来说就有了几个比较重要的指标。1就是分辨率:分辨率就是说我输出的电压是用多少位来表示的,ADC的分辨率一般是8位或者12位,就以8位和12位举例同时转化10v电压举例,当我们是12位的时候:

\frac{1}{2^{12}}\cdot 10V=2.4mV

        我们说它的分辨率是12位,它的每个刻度是2.4mV,而当我们是8位的时候:

\frac{1}{2^{8}}*10V=39mV

        这个时候我们说它的分辨率是8位,它的每个刻度就是39mV,很明显验证了前面的结论,12位的分辨率高的多。2是转换误差,我们说的转换误差就是我们最小刻度的一半,比如12位的转换误差在转换10V时的转换误差就是1.2mV。3是转换速率,即每秒转换的次数,而完成一次A/D转换所需的时间,则是转换速率的倒数。

关于ADC转换

        ADC转换主要分三步,分别是采样,量化和编码。采样主要是说说明采样原理,采样原理主要是说采样频率必须是信号频率的2倍,但是采样频率也不能过于太大,太大的话会导致采样点过多,采样时间太长,比较理想的采样频率应该是信号频率的3到5倍。而关于量化,我们都知道数字上的变化不是连续的,于是任何一个数字量的大小,都是以某个最小单位的整数倍来表示的,因此在用数字量表示电压时,也必须把它化成最小单位的整数倍,这个过程就是量化。而我们把一段连续的电压的每个采样值表示为最小单位的整数倍,并将这个整数倍值用二进制编码,那么就是编码,这个二进制信号就是我们AD的输出值。

硬件:

        XPT2046是一款四线制电阻式触摸屏,内含有12位分辨率AD转换器,XPT2046有很多的功能,但是本节我们主要是电压检测这个用法,我的51单片机上有一个滑动变阻器,我们可以通过调整滑动变阻器的电压值来改变电压的输入,图如下所示:

         其中的AIN0即与我们的XPT2046的输入引脚相连,关于XPT2046的硬件图如下所示

               X,Y,Z,VBAT,AUX通过片内的控制寄存器选择后进入ADC,ADC可以配置为单端或差分模式,选择VBAT,AUX或者X,Z的应该配置为单端模式。而作为触摸屏应用时,应该选择为差分模式,我们通过手册可得我们需要把A2,A1,A0配置为001,整个XPT2046的时序图如下所示:

                 其中位7的含义如下所示:

         我们选择位7为1

         由以上的列表可以知道我们要发的配置信号为0x94。

软件:

        其中关于XPT2046程序如下,我们的电压值虽然是5V,但是我们并不需要算出电压值的实际大小,我们只需要得到实际的份数,至于后续的处理就暂时不处理了。其中关于XPT2046读写程序如下:

#include "xpt2046.h"
#include <intrins.h>
void delay_us(unsigned int xus){
	while(xus--);
}
unsigned int spi_read(){
	int i;
	unsigned int dat = 0;
	DCLK = 0;
	for(i = 0;i < 12;i++){
		dat <<= 1;
		
		DCLK = 1;
		DCLK = 0;
		dat |= DOUT;
			
	}
	return dat;	
}

void spi_write(unsigned char dat){
	int i;
	DCLK = 0;
	for(i = 0;i < 8;i++){
		DIN= (dat >> 7) & 0x01;
		dat <<= 1;
		DCLK = 0;
		DCLK = 1;
	}	
}

unsigned int read_data(unsigned char cmd){
	unsigned int val;
	int i;
	
	DCLK = 0;
	CS= 0;
	spi_write(cmd);
	for(i = 0;i < 6;i++);
	DCLK = 1;
	_nop_();
	_nop_();
	DCLK = 0;
	_nop_();
	_nop_();
	val = spi_read();
	CS = 1;
	return val;	 
}

        关于数码管的程序如下:

#include "key.h"
unsigned char smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void key_scan(unsigned int val){
	int i;
	
	unsigned char table[4];
	for(i = 0;i < 4;i++){
		table[i] = val % 10;
		val /= 10;
	}
	for(i = 0;i < 4;i++){
		switch(i){
			case 0:
				LSC = 0; LSB = 0; LSA = 0;
				break;
			case 1:
				LSC = 0; LSB = 0; LSA = 1;
				break;
			case 2:
				LSC = 0; LSB = 1; LSA = 0;
				break;
			case 3:
				LSC = 0;  LSB = 1; LSA = 1;
				break; 
		}
		P0 = smgduan[table[i]];
		delay_us(100);
	}
	
}

        关于主函数的程序如下:

#include "reg52.h"
#include "xpt2046.h"
#include "key.h"
void main(){
	unsigned char cmd =0x94;
	unsigned int val;
	int i = 0;
	while(1){
		if(i==50){
			val = read_data(cmd);
			i = 0;
		}
		key_scan(val);		
		i++;		
	}
}

关于两个头函数的代码如下:

#ifndef _XPT_2046_H_
#define _XPT_2046_H_
#include "reg52.h"
sbit DIN  = P3^4;
sbit DOUT = P3^7;
sbit CS   = P3^5;
sbit DCLK = P3^6;
unsigned int spi_read();
void delay_us(unsigned int xus);
unsigned int read_data(unsigned char cmd);
#endif

#ifndef _KEY_H_
#define _KEY_H_
#include "reg52.h"
#include "xpt2046.h"
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
void key_scan(unsigned int val);
#endif

由此完成了XPT2046的编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值