在proteus上仿真没有问题,实物做出来后经adc0832转换出来的后在lcd1602上显示的电压只有0和5v,没有其余的中间值。
将adc0832选择的通道接到电源时显示5v,而若是在电源上并联两个电阻,然后将选择的通道接到它们中间的位置时lcd就显示0v,尝试其他方法后发现只要选择通道输入的电压只要小于5v,lcd1602就全部显示0是怎么回事啊
程序:
#include<reg52.h>
#include<1602.h>
#include<intrins.h>
#include<ADC0832.h>
sbit SK = P2^2;
uchar V[]=" L";
uchar code VT[] = "Gasoline:";
uchar code TH[] = "It's too full";
uchar code TL[] = "It's too little";
uchar code OK[] = "Just be right";
//蜂鸣器报警//
void Beep(uchar t)
{
uchar i,j;
for(i=0;i<200;i++)
{
SK=~SK;
for(j=0;j<t;j++);
}
SK=1;
}
//AD转换//
void AD_Init()
{
CS=1;
CLK=0;
DI=1;
}
unsigned char A_D()
{
unsigned ad_result1=0;
unsigned ad_result2;
unsigned char i;
CS=0;
CLK=0;
DI=1;
delay(10);
CLK=1;//第一个时钟脉冲,启动AD转换
delay(10);
CLK=0;
//选通道 DI输入1 0 选择单通道1
DI=1;
delay(10);
CLK=1;
delay(10);
CLK=0;
DI=1;
delay(10);
CLK=1;
delay(10);
CLK=0;
DO=1;
for(i=0;i<8;i++)
{
CLK=1;
delay(10);
CLK=0;
ad_result1=ad_result1<<1;
if(DO==1)
ad_result1=ad_result1| 0x01;
}
for(i=0;i<8;i++)
{
ad_result2=ad_result2>>1;
if(DO==1)
ad_result2=ad_result2| 0x80;
CLK=1;
delay(10);
CLK=0;
}
CLK=1;
CS=1;
DI=1;
return (ad_result1==ad_result2)?ad_result1:0;
}
//主函数//
void main()
{
uint d;
uchar i=0;
init();
delay(10);
LCD_POS(0x01);
dis_date(VT);
while(1)
{
d=A_D()*500.0/255;
V[1]=d/100+'0';
V[2]=d/10%10+'0';
LCD_POS(10);
dis_date(V);
if(A_D()>229)
{
LCD_POS(0x40);
dis_date(TH);
for(i=0;i<5;i++)
{
Beep(90);
Beep(120);
}
}
else if(V[1]<0x31)
{
LCD_POS(0x40);
dis_date(TL);
for(i=0;i<5;i++)
{
Beep(90);
Beep(120);
}
}
else
{
LCD_POS(0x40);
dis_date(OK);
}
}
}
//ADC0832子程序
#ifndef _ADC0832_H_
#define _ADC0832_H_
#include<reg52.h>
sbit CS = P1^0;
sbit CLK = P1^1;
sbit DI = P1^2;
sbit DO = P1^2;
unsigned char A_D();
#endif
//LCD显示子程序//
#ifndef _1602_h_
#define _1602_h_
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^0;
sbit EN=P2^1;
//延时程序//
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
//写指令操作//
void write_com(uchar com)
{
RS=0;
P0=com;
delay(5);
EN=1;
delay(5);
EN=0;
}
//写数据操作//
void write_date(uchar date)
{
RS=1;
P0=date;
delay(5);
EN=1;
delay(5);
EN=0;
}
//预设初始地址//
void LCD_POS(uchar pos)
{
write_com(pos|0x80);
}
//LCD初始化//
void init()
{
EN=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
//写入数组数据//
void dis_date(uchar*p)
{
while((*p)!='\0')
{
write_date(*p);
p++;
}
}
#endif
原理图:
能不能把你的原理图和测试方法示意图也传一下
你把DI和DO删掉一个吧,然后统一用DI或者DO试试,参考
https://blog.csdn.net/lgzisme/article/details/106058628
void main()
{
uint d;
uchar i=0;
init();
d的长度不合适,后面计算可能会溢出,改成long看看
for(i=0;i<8;i++)
{
CLK=1;
delay(10);
CLK=0;
ad_result1=ad_result1<<1;
if(DO==1)
ad_result1=ad_result1| 0x01;
}
for(i=0;i<8;i++)
{
ad_result2=ad_result2>>1;
if(DO==1)
ad_result2=ad_result2| 0x80;
CLK=1;
delay(10);
CLK=0;
}
CLK=1;
CS=1;
DI=1;
return (ad_result1==ad_result2)?ad_result1:0;
}
为什么这里要读两次然后判断是否一致?
作为单通道模拟信号输入时ADC0832的输入电压是0—5V且8位分辨率时的电压精度为19.53mV,即(5/256)V。如果作为由IN+与IN-输入的输入时,可是将电压值设定在某一个较大范围之内,从而提高转换的宽度。但值得注意的是,在进行IN+与IN-的输入时,如果IN-的电压大于IN+的电压则转换后的数据结果始终为00H。