51单片机实验五:A/D和D/A转换

发布于:2025-04-19 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、实验环境与实验器材

环境:KeliSTC-ISP烧写软件,Proteus.         

器材:TX-1C单片机(STC89C52RC)、电脑。

二、 实验内容及实验步骤

1.A/D转换

概念:模数转换是将连续的模拟信号转换为离散的数字信号的过程。模拟信号是连续的,而数字信号是离散的,ADC 的作用就是对模拟信号进行采样和量化,将其转换为数字形式。

需求:用单片机控制ADC0804进行模数转换,当拧动实验板上A/D旁边的电位器Re2时,在数码管的前三位以十进制方式动态显示出A/D转换的数字量(8位A/D转换后数值在0~255变化)。

代码:

#include "reg52.h"				   // 52系列单片机头文件
#include "intrins.h"
#define  uchar unsigned char
#define uint unsigned int 
sbit dula=P2^6;					   // 申明U1锁存器的锁存端
sbit wela=P2^7;					   // 申明U2锁存器的锁存端
sbit adwr=P3^6;					   // 定义A/D的WR端口
sbit adrd=P3^7;					   // 定义A/D的RD端口
uchar code table[]={
	0x3f,0x06,0x5b,0x4f,
	0x66,0x6d,0x7d,0x07,
	0x7f,0x6f,0x77,0x7c,
	0x39,0x5e,0x79,0x71
};

void delayms(uint xms)
{
	uint i,j;
	for(i=xms;i>0;i--)				// i=xms即延时约xms毫秒
		for(j=110;j>0;j--);
}

void display(uchar bai,uchar shi,uchar ge)	// 显示子函数
{
	dula=1;
	P0=table[bai];				   // 送段选数据
	dula=0;
	P0=0xff;					   // 送位选数据前关闭所有显示,防止打开位选锁存时
	wela=1;						   // 原来段选数据通过位选锁存器造成混乱
	P0=0x7e;					   // 送位选数据
	wela=0;
	delayms(50);				   // 延时	

	dula=1;
	P0=table[shi];				
	dula=0;
	P0=0xff;					   
	wela=1;						   
	P0=0x7d;					   
	wela=0;
	delayms(50);


	dula=1;
	P0=table[ge];				
	dula=0;
	P0=0xff;					   
	wela=1;						   
	P0=0x7b;					   
	wela=0;
	delayms(50);
}

void main()					  // 主程序
{
	uchar a,A1,A2,A3,adval;
	wela=1;
	P0=0x7f;				 // 置CSAD为0,选通ADCS以后不必再管ADCS
	wela=0;
	while(1)
	{
		adwr=1;
		_nop_();			 // 延时一个机器周期
		adwr=0;
		_nop_();
		adwr=1;
	for(a=10;a>0;a--)			  //TX-1C实验班A/D工作频率较低,所以启动转换后
								  //要多留点时间用来转换
		{						  //把显示部分放这里的原因也是为了延长转换时间
			display(A1,A2,A3);
		}
		P1=0xff;				  //读取P1之前先给其写全1
		adrd=1;					  //选通ADCS
		_nop_();
		adrd=0;					  //A/D读使能
		_nop_();
		adval=P1;
		adrd=1;
		A1=adval/100;			  //分出百,十和个位
		A2=adval%100/10;
		A3=adval%10;
	}

}

图2.1.1 模数转化硬件效果1 

图2.1.2 模数转化硬件效果2  

Proteus仿真图:

图 2.1.3 模数转换proteus仿真图

因为延时过短原因,数码管一闪一闪显示107,我们可以调节变阻器RV1来使它的值变化

仿真视频:

AD转换

 

2.D/A转换

概念:数模转换是将离散的数字信号转换为连续的模拟信号的过程。DAC 的作用是将数字信号还原为模拟信号。

要求:用单片机控制DAC0832芯片输出电流,让发光二极管D12由灭均匀变到亮,再由最亮均匀熄灭。在最亮和最暗时使用蜂鸣器分别警告一声,完成整个周期时间控制再5s左右,循环变化。

代码:

#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int 
sbit dula=P2^6;
sbit wela=P2^7;
sbit dawr=P3^6;
sbit dacs=P3^2;
sbit beep=P2^3;

void delayms(uint xms)
{
	uint i,j;
	for(i=xms;i>0;i--)
		for(j=110;j>0;j--);	
}

void main()
{
	uchar val,flag;
	dula=0;
	wela=0;
	dacs=0;
	dawr=0;
	P0=0;
	while(1)
	{
		if(flag==0)
		{
			val+=5;
			P0=val;
			if(val==255)
			{
				flag=1;
				beep=0;
				delayms(100);
				beep=1;
			}
			delayms(50);
	}
	else
	{
		val-=5;
		P0=val;
		if(val==0)
		{
			flag=0;
			beep=0;
			delayms(100);
			beep=1;
		}
		delayms(50);
	  }
	}
}

 

图2.2.1 数模转换(最亮) 

图2.2.2 数模转换(暗) 

Proteus仿真: 

图2.2.3 数模转换仿真图 

 不存在,有懂的兄弟评论区或私信帮忙一下。

图2.2.4 数模转换仿真图出错 

三.简易版

1.A/D

通过 ADC(模数转换器) 读取模拟电压值,并将结果显示在 LCD1602 液晶屏 上。

#include "reg52.h"
sbit start=P3^0;
sbit eoc=P3^1;
sbit oe=P3^2;
sbit rs=P3^3;
sbit rw=P3^4;
sbit e=P3^5;
unsigned int vol=0;
unsigned char t[]={"0123456789"};
unsigned char str[]={"VOLTAGE:"};			// 显示更美观

void delay(unsigned int n)					// 延时函数
{
	unsigned int i,j;
	for(i=0;i<n;i++)
	{
		for(j=0;j<120;j++);
	}
}

void writedat(unsigned char dat)			// 写入数据 lm016
{
	rs=1;
	rw=0;
	e=0;
	P1=dat;
	delay(100);
	e=1;
	e=0;
}

void writecom(unsigned char com)
{
	rs=0;
	rw=0;
	e=0;
	P1=com;
	delay(100);
	e=1;
	e=0;
}

void initlcd()
{
	writecom(0x38);
	writecom(0x0c);
	writecom(0x06);
	writecom(0x01);
}

void adc()
{
	start=0;
	start=1;
	delay(100);
	start=0;
	while(eoc!=1);
	oe=1;
	vol=P2;
	oe=0;
}

void display()
{
	unsigned char temp0=0,temp1=0,temp2=0;
	int i;
	vol=vol*100/51;                 // 扩大一百倍显示小数,  5v时显示255,差了51倍。
	temp0=vol/100;
	temp1=(vol%100)/10;
	temp2=(vol%10);
	for(i=0;i<8;i++)
	{
		writedat(str[i]);
		delay(100);
	}
	writecom(0x80+0x40+4);
	delay(100);
	writedat(t[temp0]);
	delay(100);
	writedat('.');
	delay(100);
	writedat(t[temp1]);
	delay(100);
	writedat(t[temp2]);
	delay(100);
	writedat('V');
	delay(100);
}

void main()
{
	initlcd();
	while(1)
	{
		adc();
		display();
	}
	
}

proteus仿真: 

存在误差

图3.1.1 A/D转换简易仿真图 

演示视频:

ADC(模数转换器) 读取模拟电压值简易版AD转换

2.D/A

通过按键控制输出信号,并实现两种不同的输出模式:PWM 方波 和 阶梯波。

#include "reg52.h"
#define uint unsigned int
sbit key0=P1^0;
sbit key1=P1^1; 
uint value=100;
uint flag=0;

void delay(uint n)
{
	uint i=0,j=0;
	for(i=0;i<n;i++)
	{
		for(j=0;j<120;j++);
	}
}

void key()
{
	if(key0==0&&flag==0)
	{
		flag=1;
	}
	if(flag==1&&key0==1)
	{
		value+=50;
		flag=0;	
	}

	if(key1==0&&flag==0)
	{
		flag=1;
	}
	if(flag==1&&key1==1)
	{
		value-=50;	
		flag=0;
	}
}

void PWM()				 // 方波
{
	P2=0;
	delay(100);
	P2=255;
	delay(value);
}

void stair()
{
	uint i=0;
	for(i=0;i<255;i++)
	{
		P2=i;
		delay(1);
	}
		for(i=255;i>0;i--)
	{
		P2=i;
		delay(1);
	}
}

void main()
{
	while(1)
	{
		//PWM();
		stair();
		key();
	}

}

proteus仿真:

 图3.2.1 D/A转换简易版仿真图

参考视频:知弦【Proteus电路仿真及应用(51单片机系列)】这位博主的51仿真视频讲的不错,博主都是从他这参考的。

 

 


网站公告

今日签到

点亮在社区的每一天
去签到