仿真不准正常 |
xuanshao 发表于 2018-11-7 22:12 建议还是用带ADC的单片机采集AD吧 |
不要在AD0808之类的过时芯片上浪费时间了,0808占用IO口超多,还需提供时钟,并且只有8位.现在的单片机基本都集成了ADC功能,分辨率也完爆0808,要求不高的话,模拟电压量直接接到IO剩下的工作就是敲键盘而已.寄存器设置参考手册上的例程即可,非常简单.可以说0808已经没有任何使用价值,这完全是教材跟不上时代的原因.(没记错的话0808的价钱还比片上集成12位ADC的51价格还贵)个人觉得学51最好的教材就是参考手册 |
楼主,我的也遇到相同问题能加下你,问下么 |
cjm82 发表于 2018-9-28 09:56 我今天用12系列的做出来了,也采到了电压。谢谢你们了。 |
FJ2018 发表于 2018-9-27 16:54 一般应用直接接带有ADC功能的IO口,设置相关寄存器就行,怎么设置手册里有详细的介绍,12系列ADC是10位的,最新的8系列IO口是12位的.QFP64封装的有单独的ADC电源和参考电压引脚,适合接基准源精度较高的场合.相关电路手册里也有,下图是从手册里截的,最常用的接法 |
QQ图片20180928094823.png (42.8 KB, 下载次数: 60)
有时候不要光想着软件问题,有可能是硬件问题呢?之前我弄了一个搞了半天,结果是硬件的问题,你查一下基准电压,还有电阻的阻值啊!这些有偏差也会导致电压不准的! |
cjm82 发表于 2018-9-27 11:01 我想请问下,用STC12系列的单片机是不是采集电压直接连IO口就可以了,不用其他外围电路了吧。你有类似的电路么 |
看来,直接用89C52直接产生不了AD芯片需要的时钟信号(500-640KHZ),实物上没有产生clk这个时钟信号。 |
yk910127 发表于 2018-9-27 10:19 好的,我试试,谢谢了 |
8位重载模式,定时计数器高8位和低8位应该值相等才对. 并且不需要在中断函数里面对TH0 TL0进行设置. void Init_T0() //12M晶振12分频 { TMOD |=0x02; TH0 = 0x9c; TL0 = 0x9c; ET0 = 1; TR0 = 1; EA = 1; } 中断服务函数 void Timer0_ISR () interrupt 1 { CLK = ~CLK; } 如果没有示波器,你可以接个LED到CLK口,然后用中断写个1秒闪一次的程序看看LED会不会闪就知道了,如果闪,把频率改高就行. 用AD直接用12系列以上的51现在新出的芯片片上都集成了12位的ADC,只需要1个IO口作为模拟输入口就行,ADC0809这种过时的芯片,除了在过时的书上面,实际运用中根本不会用到. |
看下ADC0809这个芯片手册提供的时序,然后看看你程序是不是一致,如果大致没问题,可以尝试微调下延时的时间,如有需求可以加Q:1327360970 |
有没人给我看看,是不是AD芯片时钟信号给的不对?下面是程序 #include <reg52.h> //52系列单片机头文件 #include <intrins.h> #include "math.h" #define uchar unsigned char #define uint unsigned int sbit st=P2^2; //定义AD的WR端口 sbit oe=P2^3; //定义AD的RD端口 sbit eoc=P2^0; sbit ale=P2^1; sbit lcden=P2^6; //液晶使能端 sbit lcdrs=P2^4; //液晶数据命令选择端 sbit ADDA=P2^5; //定义A、B、C三条地址线 sbit ADDB=P3^6; sbit ADDC=P3^7; sbit CLK=P2^7; //定义时钟端口 uint a,num; float OPA,OPB,AD; uchar code table41[]="WELCOME!"; /********* 延迟函数 **********/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } /************ 2002写命令 **************/ void write_com(uchar com) { lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } /************ 2002写数据 *************/ void write_data(uchar date) { lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; } /**************** 液晶初始化 *********************/ void init() { lcden=0; write_com(0x38);//设置2002显示,5X7点阵,8位数据接口 write_com(0x0c);//设置开显示,不显示光标 write_com(0x06);//写一个字符后地址指针加1 write_com(0x01);//显示清零,数据指针清零 } /******************** 显示程序 ****************************/ void display(uint x,uint qian,uint bai,uint shi,uint ge) { write_com(0x80+x); write_data(0x30+qian); write_data('.'); write_data(0x30+bai); write_data(0x30+shi); write_data(0x30+ge); } /******************** 定时中断初始化,为了产生AD芯片需要的时钟信号 *********************/ void init_time0() { TMOD = 0x02; TH0=(65536-100)/256; TL0=(65536-100)%256; IE = 0x82; TR0 = 1; } /******************** A通道OPA光电压采集 ***********************/ void OPA_1() { ADDA=1; //选择通道1 ADDB=0; ADDC=0; oe=0; //关闭输出允许位 st=0; st=1; st=0; //以上三句,开ADC0809 delay(1); //延迟1ms while(!eoc);//等待转化结束 P1=0xff; oe=1; //开启输出允许位 a=P1; //将转化出的数字存放至a a=a*19.53125; // a=a*5/256*1000 OPA=a*0.001; } /******************** 主函数: *******************/ void main() { uint a1,a2,a3,a4; init_time0(); init(); write_com(0x80+0x07); for(num=0;num<8;num++) { write_data(table41[num]); delay(150); } delay(1000); while(1) { OPA_1();//A路光电压采集 a1=a/1000; a2=a/100%10; a3=a/10%10; a4=a%10; display(0x48,a1,a2,a3,a4); } } void Timer0_INT() interrupt 1 //用定时中断产生ADC芯片时钟信号 { TH0=(65536-100)/256; TL0=(65536-100)%256; CLK = ~CLK; } |
小猫猫爱吃鱼 发表于 2018-9-26 21:21 我用是0.2ms中断一次产生时钟的,给你看看程序对不对 #include <reg52.h> //52系列单片机头文件 #include <intrins.h> #include "math.h" #define uchar unsigned char #define uint unsigned int sbit st=P2^2; //定义AD的WR端口 sbit oe=P2^3; //定义AD的RD端口 sbit eoc=P2^0; sbit ale=P2^1; sbit lcden=P2^6; //液晶使能端 sbit lcdrs=P2^4; //液晶数据命令选择端 sbit ADDA=P2^5; //定义A、B、C三条地址线 sbit ADDB=P3^6; sbit ADDC=P3^7; sbit CLK=P2^7; //定义时钟端口 uint a,num; float OPA,OPB,AD; uchar code table41[]="WELCOME!"; /********* 延迟函数 **********/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } /************ 2002写命令 **************/ void write_com(uchar com) { lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } /************ 2002写数据 *************/ void write_data(uchar date) { lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; } /**************** 液晶初始化 *********************/ void init() { lcden=0; write_com(0x38);//设置2002显示,5X7点阵,8位数据接口 write_com(0x0c);//设置开显示,不显示光标 write_com(0x06);//写一个字符后地址指针加1 write_com(0x01);//显示清零,数据指针清零 } /******************** 显示程序 ****************************/ void display(uint x,uint qian,uint bai,uint shi,uint ge) { write_com(0x80+x); write_data(0x30+qian); write_data('.'); write_data(0x30+bai); write_data(0x30+shi); write_data(0x30+ge); } /******************** 定时中断初始化,为了产生AD芯片需要的时钟信号 *********************/ void init_time0() { TMOD = 0x02; TH0=(65536-200)/256; TL0=(65536-200)%256; IE = 0x82; TR0 = 1; } /******************** A通道OPA光电压采集 ***********************/ void OPA_1() { ADDA=1; //选择通道1 ADDB=0; ADDC=0; oe=0; //关闭输出允许位 st=0; st=1; st=0; //以上三句,开ADC0809 delay(1); //延迟1ms while(!eoc);//等待转化结束 P1=0xff; oe=1; //开启输出允许位 a=P1; //将转化出的数字存放至a a=a*19.53125; // a=a*5/256*1000 OPA=a*0.001; } /******************** 主函数: *******************/ void main() { uint a1,a2,a3,a4; init_time0(); init(); write_com(0x80+0x07); for(num=0;num<8;num++) { write_data(table41[num]); delay(150); } delay(1000); while(1) { OPA_1();//A路光电压采集 a1=a/1000; a2=a/100%10; a3=a/10%10; a4=a%10; display(0x48,a1,a2,a3,a4); } } void Timer0_INT() interrupt 1 //用定时中断产生ADC芯片时钟信号 { TH0=(65536-200)/256; TL0=(65536-200)%256; CLK = !CLK; } |