51单片机练习:A/D转换篇

题目:

【例5.3.1】用单片机控制ADCO804进行模数转换,当拧动实验板上A/D旁边的电位器Re2时,在数码管的前三位以十进制方式动态显示出A/D转换后的数字量(8位A/D转换后数值在0~255变化)。(来自郭天祥老师的51单片机练习)

代码:

AD转换函数:

void ADTransform()
{
	uint i,ADval,bai,shi,ge;
	
	//写入信号
	ADWR = 1;
	_nop_();//延时一个机器周期
	ADWR = 0;//打开写入信号
	_nop_();
	ADWR = 1;//关闭写入信号
	//延时一段时间,待信号全部转换好(此处未用INTR中断标志信号已全部写入)
	for(i = 20;i > 0;i--)
	{
		display(bai,shi,ge);
	}
	
	//读出信号
	P1 = 0xff;//读之前P1全赋1
	ADRD = 1;
	_nop_();//延时一个机器周期
	ADRD = 0;//打开读出信号
	_nop_();
	ADval = P1;//将信号读出
	ADRD = 1;//关闭读出信号
	
	//处理读到的信号
	bai = ADval / 100;//百位
	shi = (ADval % 100) / 10;//十位
	ge = ADval % 10;//个位
	display(bai,shi,ge);
}

数码管显示函数:

//数码管显示函数
void display(uint bai,uint shi,uint ge)
{
	WLE = 1;
	P0 = 0x7e;//百位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[bai];//百位-段选
	DLE = 0;
	delay_1ms(5);
	
	WLE = 1;
	P0 = 0x7d;//十位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[shi];//十位-段选
	DLE = 0;
	delay_1ms(5);
	
	WLE = 1;
	P0 = 0x7b;//个位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[ge];//个位-段选
	DLE = 0;
	delay_1ms(5);
}

延时1ms函数:

//延时1ms函数
void delay_1ms(uint z)
{
	uint x,y;
	for(x = z;x > 0;x--)
	{
		for(y =110;y > 0;y--){}
	}

整个项目代码:

#include <reg52.h>
#include <intrins.h>

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

#define uint unsigned int
#define uchar unsigned char
	
sbit WLE = P2^7;//位选
sbit DLE = P2^6;//段选
sbit ADWR = P3^6;//写信号输入
sbit ADRD = P3^7;//读信号输入
sbit LE = P2^5;//led灯使能
//数码管的编码表
uchar code Table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};

void delay_1ms(uint z);
void ADTransform();
void display(uint bai,uint shi,uint ge);

void main()
{
	LE = 0;//关闭led灯使能
	WLE = 1;
	P0 = 0x7f;
	WLE = 0;
	
	while(1)
	{
		ADTransform();
	}
}


//AD转换函数
void ADTransform()
{
	uint i,ADval,bai,shi,ge;
	
	//写入信号
	ADWR = 1;
	_nop_();//延时一个机器周期
	ADWR = 0;//打开写入信号
	_nop_();
	ADWR = 1;//关闭写入信号
	//延时一段时间,待信号全部转换好(此处未用INTR中断标志信号已全部写入)
	for(i = 20;i > 0;i--)
	{
		display(bai,shi,ge);
	}
	
	//读出信号
	P1 = 0xff;//读之前P1全赋1
	ADRD = 1;
	_nop_();//延时一个机器周期
	ADRD = 0;//打开读出信号
	_nop_();
	ADval = P1;//将信号读出
	ADRD = 1;//关闭读出信号
	
	//处理读到的信号
	bai = ADval / 100;//百位
	shi = (ADval % 100) / 10;//十位
	ge = ADval % 10;//个位
	display(bai,shi,ge);
}

//数码管显示函数
void display(uint bai,uint shi,uint ge)
{
	WLE = 1;
	P0 = 0x7e;//百位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[bai];//百位-段选
	DLE = 0;
	delay_1ms(5);
	
	WLE = 1;
	P0 = 0x7d;//十位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[shi];//十位-段选
	DLE = 0;
	delay_1ms(5);
	
	WLE = 1;
	P0 = 0x7b;//个位-位选
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[ge];//个位-段选
	DLE = 0;
	delay_1ms(5);
}

//延时1ms函数
void delay_1ms(uint z)
{
	uint x,y;
	for(x = z;x > 0;x--)
	{
		for(y =110;y > 0;y--){}
	}
}

AD时序图:

ADC0804启动转换时序图:

ADC0804读取数据时序图:

心得/经验记录:

1.在本实验中,会一直随机检测是否有AD转换数据,所以AD的CS片选可以一直打开,即一直给CS置低电平;

2.AD转换的过程是:先启动AD的转换,然后等待一段时间(AD将模拟信号转换成数字信号需要花一点时间),最后读取转换好的数字信号。(ADC0804有INTR标志模拟信号是否转换完成,完成后会触发中断,但本实验用的单片机开发板没有用到该功能,所以就自动延长了一小段时间显示数码管时间用于AD的信号转换);

3.本实验中,读取的数据是从P1口读取,而P1口也是开发板的led灯接口,所以也关闭led灯使能,防止实验过程中led灯亮灭;

4.实验最终的结果,实现了AD的转换,在数码管上也能及时显示出相应的数据数字。但是,当没有拧动电位器时,数码管会在几个相邻的数字间跳动,不能稳定在一个数字上。(不确定这个现象是正常还是不正常?以及是什么原因导致的?——有知道的uu,麻烦评论区告诉俺一下哦,3Q)

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值