51单片机AD/DA学习笔记详解

AD/DA

AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。比如单片机只能识别0与5V数字信号,当输入为2.5V——模拟信号时,就需要转化为单片机所能读取的数字信号。

DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。比如单片机需要通过转换,才能发送除0、5V外的模拟信号

上图的模拟量与数字量呈正比关系。(即255对应5V,0对应0V,255/2对应2.5V,以此类推)。

AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的目的,提高硬件利用率。即一个AD可接多个模拟量检测,通过切换进行选择模拟量检测。

AD/DA与单片机数据传送可使用并口(速度快、原理简单),也可使用串口(接线少、使用方便)。需要注意的是,这里的串口不是之前沟通两个设备的串口。

可将AD/DA模块直接集成在单片机内,这样直接写入/读出寄存器就可进行AD/DA转换,单片机的IO口可直接复用为AD/DA的通道。AD一般多个通道,而DA一般只有一个通道(因为需要输出连续的信号,多个通道容易错乱);且DA一般可以用PWM进行替代。

AD/DA有时也叫ADC/DAC

AD/DA原理

 

我们以旧版的为例,因为旧版的芯片讲起来会相对简单些

DB0~DB7为输出的八个数据;IN0~IN7为输入的八个通道(8路),通过8路模拟开关进入A/D转换;ADDA~ADDC负责控制8路模拟开关的操作,选择读取哪一路的数值;A/D转换上方的三个引脚控制A/D转换,其中START控制A/D开始转换,EOC为转换结束和时钟信号,可以将输出的电压转换为一定的信号,并通过锁存器进行输出缓存,CLOCK负责锁存器的输出控制,OE负责输出使能,将数据输出出去。

 运算放大器

运算放大器(简称“运放”)是具有很高放大倍数的放大电路单元(不是像电阻那样的单独元件)。

内部集成了差分放大器、电压放大器、功率放大器三级放大电路,是一个性能完备、功能强大的通用放大电路单元,由于其应用十分广泛,现已作为基本的电路元件出现在电路图中。

运算放大器可构成的电路有:电压比较器、反相放大器、同相放大器、电压跟随器、加法器、积分器、微分器等。

运算放大器电路的分析方法:虚短、虚断(负反馈条件下)

运算放大器的特性:

1.输入阻抗非常大(同相、反向输入端几乎不流入与流出电流),以避免对前面电路产生影响。

2.内部有功率输出部分,因此输出端具有驱动能力。

接下来的图片是不同运算放大器的电路图

下面就是DA的原理

 

XPT2046时序

CS(片选)、DCLK(时钟)、DIN(数据输入)、DOUT(数据输出)为SPI中基本的信号线。

除CS线外的三根线可进行复用(多个芯片共用三根线),每个芯片都有单独的CS线(片选)可供选择来运行(同一时刻只运行一个芯片,否则容易出错)。

有时可以进行替换:DIN可以被换成MISO(主设备输入,从设备输出),DOUT可以被换成MOSI(主设备输出,从设备输入)。

 在进行操作时首先选择CS线,即应让CS线拉低,从而可以进行通信,接着调节DCLK,其上升沿输入数据,下降沿输出数据;通过DIN与DOUT线进行数据传输;需要注意的是,当DIN进行时,DOUT空闲,此时可以进行其他芯片输出。反过来同理,然后当经过一个周期(八位)后,主从机内部数据进行一次交换;最后将CS线拉高,从而完成通信。

在发送字节的时候,发送的第一个字节定义为控制字,而控制字的前三位表示模式的选择,之后发送完一个字节后可进行读出AD值。

AD数模转换代码

主函数代码

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "XPT2046.h"



unsigned int ADVAlue;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ NTC RG");
	while(1)
	{
		ADVAlue=XPT2046_ReadAD(XPT2046_XP_8);//读取AIN0,可调电阻
		LCD_ShowNum(2,1,ADVAlue,3);
		ADVAlue=XPT2046_ReadAD(XPT2046_YP_8);//读取AIN1,热敏电阻
		LCD_ShowNum(2,5,ADVAlue,3);
		ADVAlue=XPT2046_ReadAD(XPT2046_VBAT_8);//读取AIN2,光敏电阻
		LCD_ShowNum(2,9,ADVAlue,3);
		Delay(10);
	}
}

部分模块代码

#include <REGX52.H>
#include "Delay.h"

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

/**
  * @brief  ZPT2046读取AD值
  * @param  Command 命令字,范围:头文件内定义的宏,结尾的数字表示转换的位数
  * @retval AD转换后的数字量,范围:8位为0~255,12位为0~4095
  */
unsigned int XPT2046_ReadAD(unsigned char Command)
{
	unsigned char i;
	unsigned int ADVAlue=0;		//确保初始值为0
	XPT2046_DCLK=0;		//由时序图中其初始值为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);}//因为读取的数据是16位,因此用0x8000
	}
	XPT2046_CS=1;		//完成时序
	if(Command&0x08)
	{
		return ADVAlue>>8;//使得显示时后面无0填充
	}
	else
	{
		return ADVAlue>>4;//使得显示时后面无0填充
	}
	
	
}

 DA数模转换代码

主函数代码

#include <REGX52.H>
#include "Key.h"
#include "Delay.h"
#include "Nixie.h"
#include "Timer0.h"

sbit DA=P2^1;

unsigned char Counter,Compare;
unsigned char i;

void main()
{
	Timer0_Init();
	Compare=5;
	while(1)
	{
		for(i=0;i<100;i++)
		{
			Compare=i;
			Delay(10);
		}
		for(i=100;i>0;i--)
		{
			Compare=i;
			Delay(10);
		}
		
		
	}
}

void Timer0_Routine()  interrupt 1
{
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	Counter++;
	Counter%=100;
	if(Counter<Compare)
	{
		DA=1;
	}
	else
	{
		DA=0;
	}
	
	
}

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机AD/DA学习笔记详解

发表评论