题目:
【例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)