制作的模数转换,在硬件和仿真都有一些问题,请求帮助
时间:10-02
整理:3721RD
点击:
在这里先感谢各位的回答。
目的:key1控制ADC0809的通道选择,每次加一,key2负责把转换后的数值相加。
故障描述:(1)在proteus仿真时,第一次按下key1会多出一个莫名的数值,之后正常但通道号错误。
(2)在硬件实验时,第一次按下key1一直显示在"LO"字符。("LO"字符是用于当AD0809还没 有转换完成时显示。)
(3)我初步怀疑是多出来那个值得原因。
代码:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code lednum[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x76,0x79,0x38,0x40}; //0~9,'h','e','l','-'
uchar ADC_data = 0;
uint temp = 0;
uchar wei5, wei4, wei3, wei2, wei1;
uchar channel = 0; //用于标记模数转换的通道值(在这里是IN0和IN1轮换)
uchar a[2] = {0, 0}; //用于存储已转换的数字数据值
uchar ge, shi, bai, qian, wei, t; //用于显示
sbit le = P2^0; //锁存器锁存控制端,用于数码管位选
sbit clk = P2^1; //ADC0809的时钟信号输入端
sbit adda = P3^4; //ADC0809的地址输入端
sbit addb = P3^5;
sbit addc = P3^6;
sbit start_ad = P2^5; //ADC0809启动信号,高脉冲启动
sbit OE = P2^7; //ADC0809读数据控制端
sbit key1 = P3^0; //用于切换转换的通道,每次加一
sbit key2 = P3^1; //用于把转换后的值相加
sbit I = P2^2; //74hc138控制数码管的位码
sbit J = P2^3;
sbit K = P2^4;
sbit EOC = P3^7;
void ADC_TRANC(uchar channel);
void delay_ms(uint ms)
{
uint i;
ms = ms * 120;
for(i=0;i<ms;i++)
{
;
}
}
void delay(uint x) //微秒级延时子程序
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void inital_myself(void) //初始化单片机
{
le = 1; //确保其他芯片不会误动作
P0 = 1;
start_ad = 0;
OE = 0;
key1 = 1;
key2 = 1;
EOC = 0;
}
void T1_Inital(void)
{
TMOD=0x01;
TH1=(65536-200)/256;//求T1高八位数
TL1=(65536-200)%256;//求T1高八位数
EA=1; // 开中断
ET1=1; // 允许T1中断
TR1=1; // 启动T1
}
void display_hello() //显示‘Hello’作为开始
{
uchar i;
for(i=0;i<3;i++)
{
le = 1; //'H'
K = 1;
J = 0;
I = 0;
P0 = lednum[10];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 1;
I = 1;
P0 = lednum[11];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 1;
I = 0;
P0 = lednum[12];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 0;
I = 1;
P0 = lednum[12];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 0;
I = 0;
P0 = lednum[0];
le = 0;
delay_ms(5);
}
}
void display_lo(void) //当AD芯片还没有转换完成是,数码管显示‘LO’
{
le = 1;
K = 0;
J = 0;
I = 1;
P0 = lednum[12];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 0;
I = 0;
P0 = lednum[0];
le = 0;
delay_ms(5);
}
void display()
{
uchar j;
for(j=0;j<25;j++)
{
le = 1; //显示ADC转换后的数据需要6位 格式为“通道号 — 数值”
K = 1;
J = 0;
I = 1;
P0 = lednum[wei];
le = 0;
delay_ms(5);
le = 1;
K = 1;
J = 0;
I = 0;
P0 = lednum[13];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 1;
I = 1;
P0 = lednum[qian];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 1;
I = 0;
P0 = lednum[bai];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 0;
I = 1;
P0 = lednum[shi];
le = 0;
delay_ms(5);
le = 1;
K = 0;
J = 0;
I = 0;
P0 = lednum[ge];
le = 0;
delay_ms(5);
}
}
void key_scan() //键盘扫描程序
{
if(key1 == 0)
{
delay(5);
if(key1 == 0) //消抖
{
while(key1 == 0) //等待按键松开
{
;
}
if(channel == 2) //这本实验中要求只转换IN0和IN1的模拟值,并循环转换次序
{
channel = 0;
}
ADC_TRANC(channel);
channel++;
t = 1;
}
}
else if(key2 == 0)
{
delay(5);
if(key2 == 0)
{
while(key2 == 0)
{
;
}
temp = a[0] + a[1];
ge=temp%10; //个位
shi=temp/10%10;//十位
bai=temp/100%10;//百位
qian=temp/1000;//千位
wei=channel;
}
t = 1;
}
else
t = 0;
}
void ADC_TRANC(uchar channel)
{
OE=0;
start_ad=0;
start_ad=1;
start_ad=0; //START从1->0下降沿开始转换数据
adda=0x01&channel;
addb=0x01&(channel>>1);
addc=0x01&(channel>>2); //选择通道输入模拟量
do{display_lo();}while(!EOC); //当ADC0808转换数据时,EOC=0;转换结束时,EOC=1;在还没有转换完毕时,输出“LO”
OE=1; //允许A/D数据输出,单片机读取数据
ADC_data=P1; //将输出数据P0端采集,将采集数据放到ADC_data中
OE=0; //关闭A/D数据输出
temp=ADC_data*1.00/255*500; //转化为十进制数字量
a[channel] = temp;
ge=temp%10; //个位
shi=temp/10%10;//十位
bai=temp/100%10;//百位
qian=temp/1000;//千位
wei=channel;
}
int main(void)
{
inital_myself();
delay_ms(5);
T1_Inital(); //定时器初始化
while(1)
{
key_scan();
if(t == 1)
display();
else
display_hello(); //没有按键按下则显示“HELLO”
}
return 0;
}
void T1_interrupt(void)interrupt 3 using 0 //ADC芯片的时钟来源
{
TH1=(65536-200)/256; //转换时间为200us(时钟频率为640Hz)
TL1=(65536-200)%256;
clk=~clk; //产生同步时钟信号
}
电路图
我通过单片机的中断作为AD芯片的时钟信号,这样会不会影响程序本身的运行?