51单片机的A/D转换总结(XPT2046、PCF8591、内部集成AD转换器)

目录

一、A/D转换的介绍

二、基于XPT2046的AD转换(SPI通信)

三、基于PCF8591的A/D转换(IIC通信)

四、内部集成AD转换器

 五、总结


一、A/D转换的介绍

AD转换即模拟信号转换为数字信号的过程,全称为模拟-数字转换(Analog-to-Digital Conversion)。在电子、通信和控制领域等方面,模拟信号是人能直接识别的形式,如音频、视频、温度、压力、力度等,但是它们需要经过处理(传输、存储、处理)时必须转换成数字信号,以便于数字设备进行数字化处理,如滤波、放大、压缩、编码等。因此, AD转换是将模拟信号通过一个特定的电路处理,将其转化为数字信号的过程,换言之,就是将连续时间上(analog)的信号转化为离散时间上(digital)的信号的过程。这个数字信号可以用计算机进行处理、传输、存储。常见的AD转换器包括逐次逼近型、窗口型、积分型等。在很多电子产品中,如手机、数码相机、音响设备等,都使用到了AD转换器。AD转换(Analog-to-Digital Conversion)的意义在于将模拟信号转换为数字信号,以便于数字系统的处理和分析。在实际应用中,例如传感器采集、仪器控制、音频处理等领域,模拟信号是无法直接处理和存储的,必须先进行AD转换将其转换为数字信号。因此,AD转换是数字系统中非常重要的一环,同时也是电子工程技术中的基础知识之一。

51单片机的ADC(Analog to Digital Converter)模块,可以将模拟信号转换为相应的数字信号,方便单片机进行数字运算和处理。在单片机应用中,ADC模块广泛应用于模拟量采集、传感器信号处理、电压检测等方面。51单片机的ADC模块通常有8位或10位的分辨率,采样速度也有快、中、慢三种模式,可以根据实际应用需求进行设置。

ADC模块工作流程如下:

1. 选定通道:通过寄存器配置选择要转换的模拟信号通道。

2. 启动转换:设置ADC启动位或者转换启动模式,让ADC开始转换模拟信号。

3. 转换过程:在启动转换后,ADC从模拟信号输入端口采样模拟信号,将其转化为一个数字量,通过数据总线传输给单片机。

4. 数据获取:单片机通过数据总线获取ADC转换后的数字数据,进行处理。

5. 中断处理:ADC转换结果可能通过中断的方式向单片机发送,单片机在中断服务程序中获取ADC数据。

不同的单片机的ADC模块是不同的,在使用前需要仔细阅读相关的芯片手册和数据手册,并根据实际情况进行配置和调试。

二、基于XPT2046的AD转换(SPI通信)

在使用XPT2046之前,我们首先要了解什么是SPI通信协议:

SPI(Serial Peripheral Interface)是一种同步串行通信协议,其使用了4根线实现全双工的通信。SPI协议包含四个时钟信号:SCK(时钟线)、MOSI(主机输出从机输入线)、MISO(主机输入从机输出线)和SS(片选线)。

在SPI通信中,主机通过SS信号对从机进行选择,然后通过SCK时钟信号同步发送和接收数据。主机和从机的数据传输是通过MOSI和MISO两根线进行的。

SPI通信的协议由以下几个方面组成:

1. 传输时序:SPI通信需要对时钟信号进行同步控制,通信方按同样的时钟转换数据,即轮流传输数据位。

2. 数据长度:可以按照需要设定数据位的个数。SPI通信每次传输的数据最大位数由从机还是主机确定,通常在一个字节到数千个字节之间。

3. 传输数据的时钟极性和相位:SPI通信的时钟极性和相位是可以设定的,以确保不能出错。通常SPI设备的数据都在沿时刻传输给SPI总线(也许是上升沿或下降沿),并且总线上下降沿总是发生在每个字节或数据位之间。

4. 确定状态:SPI通信中还需要一个确定通讯状态的控制信号,它可以是用于连接器的一个独立引脚或者SPI数据流中的一个特定字节,通常SPI设备的数据流中,最后一个字节会包含控制选项和CRC等特殊字节。

SPI通信的流程如下:

1. 由主设备发起传输请求,选择从设备并拉低片选(CS)信号;
2. 主设备通过时钟信号(SCK)来同步数据传输,将数据通过MOSI(Master Output Slave Input)引脚传给从设备;
3. 从设备在下降沿时读取MOSI引脚上的数据,并将自己的应答数据通过MISO(Master Input Slave Output)引脚返回给主设备;
4. 主设备在下降沿时读取MISO引脚上的数据,等待从设备的应答,然后拉高片选信号,传输完成。

信号和数据的传输是在时钟信号的同步下完成的,可以通过SPI的时钟极性和相位来确定数据的读取和传输顺序。SPI通信的时序图如下图所示: 

 而XPT2046是基于SPI通信的一种设备,对于XPT2406来说,它的时序图为:

 参照时序图我们便可以编写XPT2046的AD转换函数:

#include <REGX52.H>

sbit XPT2046_CS = P3^5;
sbit XPT2046_DCLK = P3^6;
sbit XPT2046_DIN = P3^4;
sbit XPT2046_DOUT = P3^7;

unsigned int XPT2046_ReadAD(unsigned char Command)
{
	unsigned char i;
	unsigned int ADValue = 0;
	XPT2046_DCLK = 0;
	XPT2046_CS = 0;
	for(i = 0;i < 8;i++)
	{
		XPT2046_DIN = Command & (0x80 >> i);
		XPT2046_DCLK = 1;
		XPT2046_DCLK = 0;
	}
	for(i = 0;i < 16;i++)
	{
		XPT2046_DCLK = 1;
		XPT2046_DCLK = 0;
		if(XPT2046_DOUT){ADValue |= (0x8000 >> i);}
	}
	XPT2046_CS = 1;
	if(Command & 0x08)
	{
		return (ADValue >> 8);
	}
	else
	{
		return (ADValue >> 4);
	}
}

 需要注意的是这里要判断是8分辨模式还是12分辨模式,8分辨模式需要将读取到的数据右移八位,12位模式要右移4位,因为我们读取到的数据是16位的二进制数据。

#ifndef __XPT2046__H__
#define __XPT2046__H__

#define XPT2406_XP_8			0x9C//0x8C//8分辨率模式
#define XPT2406_YP_8			0xDC
#define XPT2406_VBAT_8		0xAC
#define XPT2406_AUX_8			0xEC

#define XPT2406_XP_12			0x94//0x84//12分辨率模式
#define XPT2406_YP_12			0xD4
#define XPT2406_VBAT_12		0xA4
#define XPT2406_AUX_12		0xE4

unsigned int XPT2046_ReadAD(unsigned char Command);

#endif

有了这个函数,我们就可以读取任意通道的模拟量并将模拟量转化为数字量:

#include <REGX52.H>
#include "Nixie.h"
#include "XPT2046.h"
#include "Delay.h"
unsigned int ADValue;

void main()
{
	
	while(1)
	{
//		ADValue = XPT2046_ReadAD(XPT2406_XP_8);//读滑动电阻
//		Nixie(1,ADValue/100);
//		Nixie(2,ADValue/10%10);
//		Nixie(3,ADValue%10);
//		ADValue = XPT2046_ReadAD(XPT2406_YP_8);//读热敏电阻
//		Nixie(1,ADValue/100);
//		Nixie(2,ADValue/10%10);
//		Nixie(3,ADValue%10);
		ADValue = XPT2046_ReadAD(XPT2406_VBAT_8);//读光敏电阻
		Nixie(1,ADValue/100);
		Nixie(2,ADValue/10%10);
		Nixie(3,ADValue%10);
		Delay(5);
	}
}

三、基于PCF8591的A/D转换(IIC通信)

PCF8591使用的IIC通信协议为另一种通信协议:

IIC(Inter-Integrated Circuit)通信协议,也被称作I2C(Inter-IC)通信协议。它是一种串行通信协议,由飞利浦公司(现已更名为恩智浦公司)在1980年代开发,用于各种数字芯片之间进行通信。IIC通信协议只需要两根线,即SDA(数据线)和SCL(时钟线),即可实现多个芯片之间的通信。

在IIC通信协议中,总线上通信的设备分为两类,一类是主设备,一类是从设备。主设备是控制总线,发送IIC通信命令和数据的设备。从设备只能在主设备允许的情况下回复命令和数据。

IIC通信协议的传输方式是字节传输,每个字节都由8个比特位组成。数据传输时,从设备需要在时钟线的上升沿之前准备好数据,主设备正好在时钟线上升沿时读取数据。通过控制位来表示数据的读写方向,实现数据的传输和通信。

I2C通信的基本流程:

1. 主设备发送起始信号(Start signal):主设备发送一个低电平脉冲信号,告诉所有从设备I2C总线现在被占用了。

2. 主设备发送从设备地址和读写模式:主设备将目标从设备的地址发送到I2C总线上,告诉从设备他想要读还是写。

3. 从设备响应:目标从设备响应主设备,并发送一个“应答信号”(ACK)回来。

4. 主设备发送要读/写的数据:主设备将要写入从设备或要读出来的数据发送到I2C总线上。

5. 从设备响应:从设备发送一个ACK回复主设备,确认数据已经处理。

6. 如果主设备想再进行读/写数据操作,重复步骤4和5。

7. 主设备发送停止信号(Stop signal):主设备发送一个高电平脉冲信号,告诉所有从设备I2C总线现在空闲了。

有了这个流程我们是不是可以用它来编写我们需要的读写和转换程序:

#include "PCF8591.h"
/**
  * @brief	AD转换
  * @param	Commend 通道
  * @retval	Value 转换后的值
  */
unsigned char ADGet(unsigned char Commend)
{
	unsigned char Value;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(Commend);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	Value = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return Value;
}
/**
  * @brief	DA转换
  * @param	Commend 
  * @retval	无
  */
//void DAGet(unsigned char Commend)
//{	
//	IIC_Start();
//	IIC_SendByte(0x90);
//	IIC_WaitAck();
//	IIC_SendByte(0x40);
//	IIC_WaitAck();
//	IIC_SendByte(Commend);
//	IIC_WaitAck();
//	IIC_Stop();
//}

PCF8591的地址字节为:

1001A2A1A0R/W

其中前四位为固定位,后四位为可编程部分,对照原理图可知,A2、A1、A0接地,则这三位为0,如图:

 因为首先我们要读取通道的模拟量,所以PCF8591的地址字节为1001 0000既0x90;

PCF的控制字节为:

D7D6D5D4D3D2D1D0

控制字节控制着PCF所有的功能

其中:

D3、D7:固定为0;

D1、D0:4路AD通道编号,AIN0~AIN3,00、01、10、11分别对应通道0、1、2、3;

D2:自动增量标志位,1表示在采集完0通道数据后继续采集通道1、2、3;单路采集时置0即可。

D4,D5:模拟量输入模式选择:00、01、10、11分别表示:四路单端输入、三路差分输入、单端与差分配合输入、两路差分输入。

D6:DA转换使能控制位:1表示DA转换,0表示AD转换。

所以我们的主函数要怎么写呢

#include <STC15F2K60S2.H>
#include "PCF8591.h"
#include "buzzer.h"
#include "Nixie.h"
#include "Delay.h"

void main()
{
	unsigned char Value = 0;
	Buzzer_Init();
	while(1)
	{
		Value = ADGet(AIN3);
		Nixie_C(1,Value/100);
		Nixie_C(2,Value/10%10);
		Nixie_C(3,Value%10);
	}
}
#ifndef __PCF8591__H__
#define __PCF8591__H__
#include "iic.h"

#define AIN0 0x00
#define AIN1 0x01 //光敏电阻
#define AIN2 0x02
#define AIN3 0x03 //滑动变阻

unsigned char ADGet(unsigned char Commend);
#endif

四、内部集成AD转换器

STC15系列单片机内部集成有高速10位AD转换器,只需要对相关寄存器进行配置,就可以采集AD转换数据,我们参照STC15单片机的手册:

 

 

 

 

参照这些寄存器我们来编写函数来采集通道7的模拟量:

void ADC_init()
{
	P1ASF |= P1ASF_7; //选择通道7
	ADC_RES = 0;    //ADC_RES[7:0]存放高八位数据,ADC_RESL存放低两位数据
	ADC_CONTR = 0x80;//打开电源
	Delay(1);
}

unsigned int ADC_GetResult(unsigned char ch)
{
	unsigned int ADC_Value;
	ADC_CONTR = 0x88|ch;//打开电源选择要采集的模拟量通道
	Delay(1);
	while(!(ADC_CONTR&ADC_FLAG));//等待转换完成
	ADC_CONTR = 0x80;//清楚转换完成标志位
	ADC_Value = ADC_RES;//ADC_RES[7:0]存放高八位数据
	ADC_Value = (ADC_Value << 2) | ADC_RESL;//ADC_RESL存放低两位数据并将数据合并
	return ADC_Value;
}

 采集数据后转化并显示在LCD1602上:

#include <STC15F2K60S2.H>
#include "LCD1602.h"
#include "ADGET.h"
#include "Delay.h"

unsigned int ADCTemp;
unsigned int ADCVoltage;
void main()
{
	unsigned char temp = 0;
	IO_init();
    ADC_init();
	LCD_Init();
	LCD_ShowString(1,1,"ADJ");
	while(1)
	{
		 ADCTemp = ADC_GetResult(0x07);	
         ADCVoltage = (unsigned int)(((ADCTemp*5)/1024.000)*1000);

		
		 temp=ADCTemp/1000; LCD_ShowChar(2,1,temp+'0');	
		 temp=(ADCTemp%1000)/100; LCD_ShowChar(2,2,temp+'0');		
		 temp=(ADCTemp%100)/10; LCD_ShowChar(2,3,temp+'0'); 
		 temp=ADCTemp%10; LCD_ShowChar(2,4,temp+'0');	
		
	
		 temp=ADCVoltage/1000; LCD_ShowChar(2,9,temp+'0');	
		 LCD_ShowChar(2,10,'.');	
		 temp=(ADCVoltage%1000)/100; LCD_ShowChar(2,11,temp+'0');			
		 temp=(ADCVoltage%100)/10; LCD_ShowChar(2,12,temp+'0');	 
		 temp=ADCVoltage%10; LCD_ShowChar(2,13,temp+'0');	
		 LCD_ShowChar(2,14,'V');	
		 Delay(10);
	}
}

 五、总结

本文着重介绍了使用XPT2046、PCF8591、内部集成AD转换器进行AD转换,介绍过程中,对SPI通信协议和IIC通信协议进行了简单的介绍和使用方法的说明。

  • 10
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
### 回答1: 要使用51单片机xpt2046adc来测量电压,需要先将电压信号转换为模拟信号,然后通过xpt2046adc进行模拟转数字转换,最后通过51单片机读取转换后的数字信号并计算出电压值。具体实现方法可以参考相关的电路设计和程序编写。 ### 回答2: 51单片机是一种广泛应用于嵌入式系统中的芯片,拥有较强的处理能力和丰富的外设接口。而XPT2046ADC则是一种支持触摸屏的模拟转数字转换器,可用于对电压的测量。 若要使用51单片机测量电压,我们可以将要测量的电压输入到XPT2046ADC模块的通道上,通过模拟转数字转换器转换成数字信号,再通过51单片机读取这个数字信号,即可得到要测量的电压值。 在具体实现中,我们首先需要确定电压输入的范围,以及采样率。在选择通道时,要根据输入电压的大小选择合适的通道,以避免模拟转数字转换器输出的数字信号溢出。在采样率的选择上,要根据要求的精度和响应速度进行折中。 接着,我们需要使用软件编程的方式将模拟转数字转换器51单片机的GPIO进行连接,使得模拟转数字转换器能够将转换后的数字信号传输给51单片机处理。在编程过程中,需要注意防止噪声信号对模拟转数字转换器的影响,以保证输入数据的准确性。 最后,我们可以通过串口的方式将测量结果输出到外部设备,或者使用LCD显示屏直接显示在屏幕上。同时,还需要根据实际需求采取相应的措施,如增加滤波电路、提高采样率等以提高测量精度。 总之,通过合理的硬件连接和软件编程,我们可以很方便地将XPT2046ADC模块与51单片机相连接来测量电压,这种方式具有响应速度快、成本低、易于实现等优点,在实际的嵌入式系统设计中非常有应用价值。 ### 回答3: 51单片机是一款非常常用的单片机,常用于嵌入式系统的控制。如果我们需要测量电压,可以借助51单片机内部ADC转换器。而如果我们需要实现触摸屏功能,可以使用xpt2046触摸屏控制器。那么如何使用51单片机xpt2046实现测量电压的功能呢? 首先,需要通过电路将所需测量的电压输入到51单片机ADC口。一般情况下,需要使用电阻分压电路或操作放大器等电路进行电压转换和增益调整,以保证输入电压不超出51单片机的工作范围。其次,需要在程序中进行ADC转换和数值计算。具体步骤如下: 1、初始化ADC转换器xpt2046触摸屏控制器; 2、编写中断函数,当触摸屏输入时,触发中断,读取xpt2046控制器的值; 3、根据转换系数将xpt2046读取的值转换为对应的电压值; 4、显示电压值或将电压值传输给其他设备。 需要注意的是,在进行电压测量时需要考虑电路的稳定性和精度,以及对电路和51单片机的保护。同时,也需要根据实际需要选择合适的ADC转换器xpt2046控制器,并进行相应的程序设计。 总之,通过合理的电路设计和程序实现,使用51单片机xpt2046触摸屏控制器可以实现电压测量功能,为我们的嵌入式系统提供更多的应用空间和可能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FelipeSueño

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值