标题: 基于51单片机和ADC0809的数字电压表设计 [打印本页]

作者: 51hei社区    时间: 2016-1-14 00:06
标题: 基于51单片机和ADC0809的数字电压表设计
  本课题是利用单片机设计一个数字电压表,能够测量0-5V之间的直流电压值,四位数码显示,使用的元器件数目较少。外界电压模拟量输入到A/D转换部分的输入端,通过A/D转换变为数字信号,输送给单片机。然后由单片机给数码管数字信号,控制其发光,从而显示数字。
    注:因为ADC0809的通道选择端口是使用插针,做出电路板后再用导线连起来的,在程序里也少了通道选择的语句,请注意一下。
一.原理图



二.仿真图



三.存储空间定义
(1)70H用于存放A/D转换结果,71H、72H、73H、74H分别存储显示用的三位数据如表所示。

(2)地址30H~39H存放显示在数码管上0~9的数。如表所示。


四.程序


程序可分为数据采集系统、数据转换系统、显示系统,这三部分先独立测试,然后整体调试。
①数据采集系统:因为ADC0809本身并没有内部时钟,需要外部时钟来提供工作的时钟频率。如果利用单片机ALE端脚提供的频率为6MHZ,而ADC0809工作的频率在10KHZ-1MHZ。因此,需要增加含触发器功能的器件,从面增加了系统的复杂程度。后来,最终用软件编程来提供ADC0809工作的时钟频率,从而解决了这个问题。
②显示系统的调试:要显示的数据存放在71H、72H、73H、74H单元中,先在30H~39H分单元中存放0~9的数,运行显示程序,进行查表指令,察看显示的结果是否与存放值一样。在测试的过程中发现小数点没有显示,通过下面几条指令,把小数点显示出来。
MOVC A,@A+DPTR
           CJNER2,#0FEH,NOT_ONE     ;不是左边第一个数码管,则转移
           ORL A,#80H               ;左边第一个数码管显示小数点
NOT_ONE:   MOVP0,A                  ;数码管段选


(1) 汇编语言程序清单
QIAN  EQU  71H
BAI   EQU 72H
SHI   EQU 73H
GEWEI EQU 74H     ;71H-74H存放显示数据,依次为个位、十位、百位、千位
SHUJU EQU 70H         ;地址70H存放采集数据  
ST  BITP3.0            ;START和ALE共用一个端口
OE  BIT P3.6
EOC BIT P3.7
CLK BITP3.3     
ORG  0000H
LJMP  START
ORG 0030H
TAB:  DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
            
START:     
MAIN:      LCALL  TEST              ;数据采集函数
LCALL TURNDATA            ;数据处理函数
           LCALL  DISPLAY           ;显示函数
           LJMP   MAIN


DELAY:         MOV R7,#06H        ;约延时1.5ms
LOOP1:     MOV  R6,#0FFH
LOOP2:     DJNZ R6,LOOP2
           DJNZR7,LOOP1        
       RET


TEST:      CLR  ST
          CLR  OE
           SETB ST
          CLR  ST                  ;ST端口下降沿,开始转换
LOOPCLK:   SETBCLK                 ;由软件来提供ADC0809工作的时钟频率
          CLR  CLK
          JNB EOC,LOOPCLK         ;EOC=1时,退出循环
           SETBOE                  ;转换后数据的传送
          MOV P1,#0FFH            ;P1端口读数据,需先给高电平
          MOV A,P1               
         CLR  OE
          MOV SHUJU,A             ;存储数据到地址70H
      RET


TURNDATA:      
         MOV  A,SHUJU
         MOV  B,#51
         DIV AB                     ;余数在B,相除以后C=0
         MOV  QIAN,A            ;储存千位
           CLR  F0
         MOV A,B                                       
          SUBBA,#1AH           ;A减去26,测试上面AB相除时,余数与26相比较
          MOV F0,C                   ;余数<26,则C=1,不用加5调整
          MOV  A,#10
          MUL  AB
          MOV  B,#51
          DIV  AB
          JB   F0,LP1
         ADD A,#5                   ;若AB相除后B>=26,百位加五
LP1:      MOV BAI,A                  ;储存百位
CLR  F0
           MOV A,B
           SUBBA,#1AH      
          MOV  F0,C
          MOV  A,#10
          MUL  AB
          MOV  B,#51
          DIV  AB
          JB F0,LP2                  ;F0=1时,转移            
          ADD A,#5                   ;若AB相除后B>=26,十位加五
LP2:       MOV SHI,A                  ;储存十位
          CLR  F0
          MOV  A,B
           SUBBA,#1AH
          MOV  F0,C
          MOV  A,#10
          MUL  AB
          MOV  B,#51
          DIV  AB
          JB F0,LP3                  ;F0=1时,转移            
          ADD A,#5                   ;若AB相除后B>=26,个位加五  
LP3:       MOV GEWEI,A                ;储存个位
      RET


DISPLAY:      
MOV  R1,#4               ;循环四次   
          MOV   R2,#0FEH
          MOV  R0,#71H             ;存放显示初始地址
XIANSHI:      
MOV DPTR,#TAB  
           MOVA,@R0
           MOVCA,@A+DPTR
           CJNER2,#0FEH,NOT_ONE     ;不是左边第一个数码管,则转移
          ORL A,#80H               ;左边第一个数码管显示小数点
NOT_ONE:   MOVP0,A                  ;数码管段选
           MOVP2,R2                 ;数码管位选
           LCALLDELAY               ;延时
          MOV   A,R2
          RL   A                  ;循环左移
          MOV   R2,A
           INCR0                   ;选取下一个地址
          DJNZ  R1,XIANSHI
      RET
END   

(2) C语言程序清单
#include<reg51.h>
sbit CLK=P3^3;
sbit OE=P3^6;
sbit ST=P3^0;
sbit EOC=P3^7;
unsigned int dianya;
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};


void delay(unsigned int z)
{
   while(z--);
}


void ADC_0809()
{
    unsignedchar temp=2;
    ST=0;
    OE=0;
    ST=1;
   ST=0;  
   CLK=1;
   CLK=0;
   CLK=1;
   CLK=0;
   while(!EOC)
   {  
       CLK=1;
       CLK=0;
    }
    OE=1;
   P1=0xff;                       //读取P1端口数据
   temp=P1;
   dianya=(unsigned int)temp*19.53;
    OE=0;
}


void Vpp_Show()
{
    unsignedchar qian,bai,shi,ge;
   qian=dianya/1000;
   bai=dianya00/100;
   shi=dianya0/10;
   ge=dianya;
   P2=0xfe;
   P0=table[qian]|0x80;                 //显示小数点
   delay(50);
   P2=0xfd;
   P0=table[bai];
   delay(50);
   P2=0xfb;
   P0=table[shi];
   delay(50);
   P2=0xf7;
   P0=table[ge];
}
void main()
{
   while(1)
    {
      ADC_0809();
      Vpp_Show();

    }
}

                                                                    (技术部)


作者: jky19951    时间: 2016-1-14 21:31
楼主好人能发下仿真图吗?急需,,,,,在线等,忙着交作业
作者: 小白菜123776    时间: 2016-9-29 08:04
楼主能给我发下仿真图吗
作者: 小小号    时间: 2017-5-19 21:40
楼主,好奇问下,你的ADC0809clock端,没有方波电压,怎么能工作呢
作者: 疯狂阿拉敏    时间: 2017-5-25 22:32
学习中。。。简单且实用的东西
作者: dengy    时间: 2017-12-21 22:01
楼主,问一下如何改成数字电流表和扩大或缩小电流表的量程
作者: qq691741876    时间: 2018-5-1 21:57
out和p1接反了吧

作者: SF丶    时间: 2018-5-15 15:16
楼主能给我发下仿真图吗
作者: free594    时间: 2018-5-16 13:12
学习学习
作者: 思凡    时间: 2018-5-29 20:06
谢谢楼主,学习中

作者: afdsfsda    时间: 2019-5-21 15:35
小白一个
请问,为什么要乘19.53呢?

作者: 无一物惹尘    时间: 2020-6-24 20:43
仿真结果不对呢, 我按照楼主的仿真电路图连接的,程序也是一样的,楼主有空可以解答吗?




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1