3974|4

4

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

ADC0809数字电压表显示问题 [复制链接]

设计图如下,
由于硬件已经实现,无法更改,还望大神多多帮忙。
源代码如下
//---------------------------------------
// AD0809 by maomaochong
// Date: 2011/8/31
// Time: 15:54
// Function: ADDA-ADDC connect to P2.0-P2.2 to choose AD channel
//---------------------------------------

#include "reg51.h"

sbit ST_ALE=P3^0;                //START and ALE both connect to P3.0
sbit EOC=P3^1;                        //EOC connect to P3.1                                       
sbit OE=P3^2;                        //OE conect to P3.2
sbit CLK=P3^3;                        //CLK connect to P3.3
unsigned char CHANNEL;        //AD channel variable
unsigned char LED[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//common cathode LED code
unsigned char CHECK[4]={0xFE,0xFD,0xFB,0xF7};        //choose LED channel

void delay(unsigned char time)
{
        unsigned char i,j;
        for(i=time;i>0;i--)
                for(j=250;j>0;j--)
                ;
}

void display()
{
        unsigned long temp;
        unsigned char DATA,digit[4];
        unsigned int k,l;
        DATA=P1;                                        //save AD data
        temp=DATA;                                        //the temporary variable
    temp=temp*1000/51;                        //AD formula:D=A*5/255
        digit[0]=temp/1000;                        //the thousands place
        digit[1]=temp%1000/100;                   //the hundreds place
        digit[2]=temp%1000%100/10;         //the tens place
        digit[3]=temp%1000%100%10;        //the ones place
        DATA=P2;                                          //save P2
        for(k=0;k<1000;k++)
        {
        /*        lighten each LED and equal the below for loop
                P1=LED[digit[0]]+0x80;
                P2_4=0;
                P2_4=1;
                P1=LED[digit[1]];
                P2_5=0;
                P2_5=1;
                P1=LED[digit[2]];
                P2_6=0;
                P2_6=1;
                P1=LED[digit[3]];
                P2_7=0;
                P2_7=1;
        */
                for(l=0;l<4;l++)
                {
                        P2=P2|0x0F;                        //avoid LED residual
                        P0=LED[digit[l]]+0x80*(l==0);        //LED code
                        P2=DATA&CHECK[l];        //choose LED channel
                }
        }
        P2=DATA;                                        //restore P2       
}

void main()
{

        ST_ALE=0;                        //START and ALE default
        OE=0;                                //OE default
        TMOD=0x02;                        //T0 operate in mode 2
       
        EA=1;                                //all interrupt enable
        ET0=1;                                //T0 interrupt enable
        TR0=1;                                //T0 run
        while(1)
        {
               
                ST_ALE=1;                //lock the AD channel address
                ST_ALE=0;                //AD run
                while(EOC==0);        //wait until AD over
                OE=1;                        //enable to transmit AD data
                display();                //view the AD result and diaplay LED
               
       
               
        }       
}

void T1_TIME() interrupt 1 using 0
{
        CLK=~CLK;                        //CLK 500 kHz
}

问题:滑动变阻器显示的电压和数码管显示的电压数值不等,不知道具体问题是哪里,还望大神多多指教。新生小白一只,刚刚接触单片机,还望多多指教!
此帖出自51单片机论坛

最新回复

我把我这两天写的ADC0809程序拷给你,你看一下吧,我的原因是ADC0809芯片的时钟频率达不到,以致ADC0809不能工作,显示用的LCD1602液晶显示屏做的,不过差别不大。    #include  #include                     //宏定义,包含头文件lcd1602.h   #include   #include   sbit adress_A=P1^2;                //需要接,还有VCC和VREF+,还有adress_B和adress_C;   sbit ALE=P3^6;                   //   sbit start=P3^5;                  //   sbit clk=P1^7;                  //   sbit EOC=P3^7;                  //   sbit OE=P1^6;                          //   sbit D0=P2^0;                         //   sbit D1=P2^1;                         //   sbit D2=P2^2;                         //   sbit D3=P2^3;                         //   sbit D4=P2^4;                         //   sbit D5=P2^5;                        //   sbit D6=P2^6;                        //   sbit D7=P2^7;                        // // sbit jidianqi=P3^0;   sbit K2=P3^2;     int flag=4,i=0;   void Delay(unsigned int c);   void h(float temp);   void Delay(unsigned int c)   {           while(c--);   } void timer0init()         {       TMOD=0x01;                TH0=(65536-1)/256;           TL0=(65536-1)%256;        EA=1;          ET0=1;           TR0=1;         clk=0;         } void main() {               unsigned int temp_data=0;     float a;     int U=0;         timer0init();     LCD_init();     IT0=1;         EX0=1;         EA=1;         while(1)     {                                ALE=0;start=0;                         _nop_();_nop_();_nop_();                         adress_A=0;                         Delay(10);                         ALE=1;                         start=0; _nop_();_nop_();_nop_();                                start=1;                         _nop_();_nop_();_nop_();                         start=0;                                                   //        while(!EOC);                         P2=0xff;                         OE=1;                         Delay(13);                         temp_data=P2;                         ALE=0;                                                OE=0;                   a=(float)(temp_data*5/4095.0);                            h(a);                                                       //显示部分传值函数                    Delay(10);  //延时等待芯片反应         }   }   void h(float temp) {     unsigned char str[9];         unsigned char a[]="Recent Voltage";                unsigned char b[]="Recent Electry "; //        sprintf(str,"%.3f",temp); //        LCD_dsp_string(0,0,str);           //lcd1602第一行显示 //        LCD_dsp_string(1,0,"SUCCESSFUL");  //lcd1602第二行显示           if(flag==4)         {         sprintf(str,"%.3f",temp);             LCD_dsp_string(0,0,"guoliu baohu");                 LCD_dsp_string(4,1," ");                                 //空格消除由于档位切换,字符长度不同导致的显示问题                 LCD_dsp_string(11,1,"V");         }            if(flag==0)         {                sprintf(str,"%.3f",temp);                 LCD_dsp_string(0,0,"0V--5V Voltage");           //lcd1602第一行显示            LCD_dsp_string(11,1,"V");  //lcd1602第二行显示            LCD_dsp_string(4,1," ");             LCD_dsp_string(10,1," ");             LCD_dsp_string(12,1,"   ");           }    if(flag==1)         {             sprintf(str,"%.3f",temp);                 LCD_dsp_string(4,1,"-");             LCD_dsp_string(11,1,"V");             LCD_dsp_string(0,0,"-5V-0V Voltage");                 LCD_dsp_string(10,1," ");                 LCD_dsp_string(12,1,"   ");         }    if(flag==2)         {             temp=temp*1000/200;             sprintf(str,"%.3f",temp);             LCD_dsp_string(11,1,"mA");             LCD_dsp_string(0,0,b);                 LCD_dsp_string(4,1," ");                 LCD_dsp_string(13,1,"   ");         }       if(flag==3)         {             temp=temp*3;                 LCD_dsp_string(0,0,"9V-12V Voltage");             sprintf(str,"%.3f",temp);            LCD_dsp_string(11,1,"V");         LCD_dsp_string(4,1," ");         LCD_dsp_string(10,1," ");         LCD_dsp_string(12,1,"  ");         }                                   LCD_dsp_string(5,1,str); }   void timer0() interrupt 1 {             TH0=(65536-1)/256;                     TL0=(65536-1)%256;                   clk=~clk; } void  counter(void) interrupt 0                    //外部中断 {    EX0=0;                                                   //关闭中断,防止在执行中断过程中又进入中断         i++;    if(i==1)       flag=0;                                         //zhengchang dianya         if(i==2)             flag=1;                                         //fu dianya         if(i==3)            flag=2;                                 //dianliu          if(i==4)          {                flag=3;                                //9-12V dianya                 i=0;                 }    Delay(60);                                          //时间延迟,消除按键抖动    EX0=1;                                                  //kai zhongduan } LCD1602.c文件 //adc0809+最小系统+LCD1602液晶显示屏 #include                //宏定义,包含头文件lcd1602.h #include #define  LCDIO  P0                           //定义数据端口 sbit LCD1602_RS = P1^5;                   //数据命令选择接口 sbit LCD1602_RW = P1^3;                   //读写选择接口 sbit LCD1602_EN = P1^4;                   //使能信号接口 /** * @brief LCD1602初始化函数 * * @param 无 * @return 无 * @note */   void Delay(unsigned int c); void LCD_init(void) {         LCD_write_command(0x01);         //清屏         LCD_write_command(0x38);         //设置16*2显示,5*7点阵,8位数据接口模式         LCD_write_command(0x38);         //设置16*2显示,5*7点阵,8位数据接口模式         LCD_write_command(0x0C);         //打开LCD显示 ,不显示光标,光标不闪烁         LCD_write_command(0x06);         //设置LCD第一个显示的地址         LCD_write_command(0x01);     //清屏 } /** * @brief 写指令函数 * * @param command:写入的指令 * @return * @note */ void LCD_write_command(unsigned char command) {         LCDIO = command;                        //指令         LCD1602_RS = 0;                                //输入指令         LCD1602_RW = 0;                                //向LCD写入指令         LCD1602_EN = 1;         LCD1602_EN = 0;                                //使能信号1->0时(下降沿)执行指令         Delay(10);                                //延时 } /** * @brief 写数据函数 * * @param dat:写入的数据 * @return 无 * @note */ void LCD_write_dat(unsigned char dat) {         LCDIO = dat;                                //写入的数据         LCD1602_RS = 1;                                //输入数据         LCD1602_RW = 0;                                //向LCD写入数据         LCD1602_EN = 1;                                        LCD1602_EN = 0;                                //使能信号1->0时(下降沿)执行指令 Delay(1);                                //延时                         } /** * @brief 显示位置函数 * * @param  x:行显示地址(取值范围0-1),y:列显示地址(取值范围0-15) * @return * @note    */ void LCD_set_xy(unsigned char x,unsigned char y) {         unsigned char address;           //定义地址码         if(y==0)                                   //要显示第一行         {                 address = 0x00 + x;           //地址码+0x80         }         else                                           //要显示第二行         {                 address = 0x40 + x;           //地址码+0xC0         }         LCD_write_command(address|0x80);//写入地址码 } /** * @brief 显示一个字符函数 * * @param  x:行显示地址(取值范围0-1),y:列显示地址(取值范围0-15),dat:显示的字符 * @return * @note    */ //void LCD_dsp_char(unsigned char x,unsigned char y,unsigned char dat) //{ //        LCD_set_xy(x,y);                   //设置显示位置 //        LCD_write_dat(dat);                   //在设置的位置写入一个字符 //} /** * @brief 显示字符串函数 * * @param  X:行显示地址(取值范围0-1),Y:列显示地址(取值范围0-15),*s:要显示的字符串 * @return * @note    */ void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s) {         LCD_set_xy(X,Y);                  //设置显示位置         while(*s)                                  //检测字符串结束标志         {                 LCD_write_dat(*s);          //写入当前字符                 s++;                                  //指向下一个字符         } } LCD1602.h文件 #ifndef __LCD1602_H__ #define __LCD1602_H__ void LCD_init(void);//初始化函数声明 void LCD_write_command(unsigned char command);   //写入指令函数声明 void LCD_write_dat(unsigned char dat);           //写入数据函数声明 void LCD_set_xy(unsigned char x,unsigned char y);//设置显示位置函数声明 //void LCD_dsp_char(unsigned char x,unsigned char y,unsigned char dat);//显示一个字符函数声明 void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//显示字符串函数声明 #endif   详情 回复 发表于 2016-7-23 21:02
点赞 关注
 

回复
举报

4

帖子

0

TA的资源

一粒金砂(中级)

推荐
 

回复 沙发 jishuaihu 的帖子

老大,我这个显示直接出问题的不行啊,你看,我模拟的时候发现的,滑动变阻器为1.0V时,数码管显示2.372V,2.0V-2.450V,3.0V-2.549V,4.0V-2.627V,5.0v-2.725V,数字之间没有什么关系啊,这是怎么回事啊?
此帖出自51单片机论坛
 
 
 

回复

3404

帖子

6

TA的资源

裸片初长成(初级)

沙发
 
没有校准部分,自己加一个校准函数就行了,所谓的校准其实就是算一个系数。计算的时候再乘上这个系数就可以了,当然你也可以自己算一下这个系数,然后乘到你计算完的电压值后再显示就可以了。做AD采集一般都需要一个系数的,一个是信号处理部分不可以能和计算的完全一直,在一个AD转换过程中都会产生误差的。
比如变阻器显示的电压是1V,数码管显示的是1.25V,那么你在显示之前乘以0.8就可以了!
此帖出自51单片机论坛

点评

老大,我这个显示直接出问题的不行啊,你看,我模拟的时候发现的,滑动变阻器为1.0V时,数码管显示2.372V,2.0V-2.450V,3.0V-2.549V,4.0V-2.627V,5.0v-2.725V,数字之间没有什么关系啊,这是怎么回事啊?  详情 回复 发表于 2013-4-20 10:33
 
 
 

回复

3404

帖子

6

TA的资源

裸片初长成(初级)

4
 
那可能是程序或者设计有问题吧,我没有用过0809,不太懂,附件里面是一个前辈做的protues的好多仿真及代码。其中有一个电流检测用的ADC0808,和0809操作基本一直,你参考一下吧。这个压缩包是我以前在论坛里下载的,谨向前辈致谢! 单片机 PROTUES仿真实例大全(附带原理图)免费下载.RAR (1.5 MB, 下载次数: 72)
此帖出自51单片机论坛
 
 
 

回复

19

帖子

1

TA的资源

一粒金砂(中级)

5
 
我把我这两天写的ADC0809程序拷给你,你看一下吧,我的原因是ADC0809芯片的时钟频率达不到,以致ADC0809不能工作,显示用的LCD1602液晶显示屏做的,不过差别不大。
   #include  #include                     //宏定义,包含头文件lcd1602.h
  #include
  #include

  sbit adress_A=P1^2;                //需要接,还有VCC和VREF+,还有adress_B和adress_C;
  sbit ALE=P3^6;                   //
  sbit start=P3^5;                  //
  sbit clk=P1^7;                  //
  sbit EOC=P3^7;                  //
  sbit OE=P1^6;                          //
  sbit D0=P2^0;                         //
  sbit D1=P2^1;                         //
  sbit D2=P2^2;                         //
  sbit D3=P2^3;                         //
  sbit D4=P2^4;                         //
  sbit D5=P2^5;                        //
  sbit D6=P2^6;                        //
  sbit D7=P2^7;                        //

// sbit jidianqi=P3^0;
  sbit K2=P3^2;

    int flag=4,i=0;


  void Delay(unsigned int c);
  void h(float temp);

  void Delay(unsigned int c)
  {
          while(c--);
  }
void timer0init()        
{  
    TMOD=0x01;           
    TH0=(65536-1)/256;      
    TL0=(65536-1)%256;   
    EA=1;     
    ET0=1;      
    TR0=1;
        clk=0;        
}

void main()
{          
    unsigned int temp_data=0;
    float a;
    int U=0;
        timer0init();
    LCD_init();
    IT0=1;
        EX0=1;
        EA=1;
        while(1)
    {       
                        ALE=0;start=0;
                        _nop_();_nop_();_nop_();
                        adress_A=0;
                        Delay(10);
                        ALE=1;
                        start=0; _nop_();_nop_();_nop_();       
                        start=1;
                        _nop_();_nop_();_nop_();
                        start=0;                                  
                //        while(!EOC);
                        P2=0xff;
                        OE=1;
                        Delay(13);
                        temp_data=P2;
                        ALE=0;                       
                        OE=0;
                  a=(float)(temp_data*5/4095.0);         
                  h(a);                                                       //显示部分传值函数
                   Delay(10);  //延时等待芯片反应
        }

  }
  void h(float temp)
{
    unsigned char str[9];
        unsigned char a[]="Recent Voltage";       
        unsigned char b[]="Recent Electry ";
//        sprintf(str,"%.3f",temp);
//        LCD_dsp_string(0,0,str);           //lcd1602第一行显示
//        LCD_dsp_string(1,0,"SUCCESSFUL");  //lcd1602第二行显示
          if(flag==4)
        {
        sprintf(str,"%.3f",temp);
            LCD_dsp_string(0,0,"guoliu baohu");
                LCD_dsp_string(4,1," ");                                 //空格消除由于档位切换,字符长度不同导致的显示问题
                LCD_dsp_string(11,1,"V");
        }   

        if(flag==0)
        {       
        sprintf(str,"%.3f",temp);
                LCD_dsp_string(0,0,"0V--5V Voltage");           //lcd1602第一行显示
           LCD_dsp_string(11,1,"V");  //lcd1602第二行显示
           LCD_dsp_string(4,1," ");
            LCD_dsp_string(10,1," ");
            LCD_dsp_string(12,1,"   ");
          }
   if(flag==1)
        {
            sprintf(str,"%.3f",temp);
                LCD_dsp_string(4,1,"-");
            LCD_dsp_string(11,1,"V");
            LCD_dsp_string(0,0,"-5V-0V Voltage");
                LCD_dsp_string(10,1," ");
                LCD_dsp_string(12,1,"   ");
        }
   if(flag==2)
        {
            temp=temp*1000/200;
            sprintf(str,"%.3f",temp);
            LCD_dsp_string(11,1,"mA");
            LCD_dsp_string(0,0,b);
                LCD_dsp_string(4,1," ");
                LCD_dsp_string(13,1,"   ");
        }   
   if(flag==3)
        {

            temp=temp*3;
                LCD_dsp_string(0,0,"9V-12V Voltage");
            sprintf(str,"%.3f",temp);
           LCD_dsp_string(11,1,"V");
        LCD_dsp_string(4,1," ");
        LCD_dsp_string(10,1," ");
        LCD_dsp_string(12,1,"  ");
        }                          
        LCD_dsp_string(5,1,str);
}
  void timer0() interrupt 1
{
            TH0=(65536-1)/256;        
            TL0=(65536-1)%256;  
                clk=~clk;
}

void  counter(void) interrupt 0                    //外部中断
{
   EX0=0;                                                   //关闭中断,防止在执行中断过程中又进入中断
        i++;
   if(i==1)
      flag=0;                                         //zhengchang dianya
        if(i==2)
            flag=1;                                         //fu dianya
        if(i==3)
           flag=2;                                 //dianliu
         if(i==4)
         {   
            flag=3;                                //9-12V dianya
                i=0;
                }

   Delay(60);                                          //时间延迟,消除按键抖动
   EX0=1;                                                  //kai zhongduan
}

LCD1602.c文件
//adc0809+最小系统+LCD1602液晶显示屏
#include                //宏定义,包含头文件lcd1602.h
#include
#define  LCDIO  P0                           //定义数据端口
sbit LCD1602_RS = P1^5;                   //数据命令选择接口
sbit LCD1602_RW = P1^3;                   //读写选择接口
sbit LCD1602_EN = P1^4;                   //使能信号接口

/**
* @brief LCD1602初始化函数
*
* @param 无
* @return 无
* @note
*/
  void Delay(unsigned int c);
void LCD_init(void)
{
        LCD_write_command(0x01);         //清屏
        LCD_write_command(0x38);         //设置16*2显示,5*7点阵,8位数据接口模式
        LCD_write_command(0x38);         //设置16*2显示,5*7点阵,8位数据接口模式
        LCD_write_command(0x0C);         //打开LCD显示 ,不显示光标,光标不闪烁
        LCD_write_command(0x06);         //设置LCD第一个显示的地址
        LCD_write_command(0x01);     //清屏
}

/**
* @brief 写指令函数
*
* @param command:写入的指令
* @return
* @note
*/
void LCD_write_command(unsigned char command)
{
        LCDIO = command;                        //指令
        LCD1602_RS = 0;                                //输入指令
        LCD1602_RW = 0;                                //向LCD写入指令
        LCD1602_EN = 1;
        LCD1602_EN = 0;                                //使能信号1->0时(下降沿)执行指令
        Delay(10);                                //延时
}

/**
* @brief 写数据函数
*
* @param dat:写入的数据
* @return 无
* @note
*/
void LCD_write_dat(unsigned char dat)
{
        LCDIO = dat;                                //写入的数据
        LCD1602_RS = 1;                                //输入数据
        LCD1602_RW = 0;                                //向LCD写入数据
        LCD1602_EN = 1;                               
        LCD1602_EN = 0;                                //使能信号1->0时(下降沿)执行指令
Delay(1);                                //延时
                       
}

/**
* @brief 显示位置函数
*
* @param  x:行显示地址(取值范围0-1),y:列显示地址(取值范围0-15)
* @return
* @note   
*/
void LCD_set_xy(unsigned char x,unsigned char y)
{
        unsigned char address;           //定义地址码
        if(y==0)                                   //要显示第一行
        {
                address = 0x00 + x;           //地址码+0x80
        }
        else                                           //要显示第二行
        {
                address = 0x40 + x;           //地址码+0xC0
        }
        LCD_write_command(address|0x80);//写入地址码
}
/**
* @brief 显示一个字符函数
*
* @param  x:行显示地址(取值范围0-1),y:列显示地址(取值范围0-15),dat:显示的字符
* @return
* @note   
*/
//void LCD_dsp_char(unsigned char x,unsigned char y,unsigned char dat)
//{
//        LCD_set_xy(x,y);                   //设置显示位置
//        LCD_write_dat(dat);                   //在设置的位置写入一个字符
//}

/**
* @brief 显示字符串函数
*
* @param  X:行显示地址(取值范围0-1),Y:列显示地址(取值范围0-15),*s:要显示的字符串
* @return
* @note   
*/
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
{
        LCD_set_xy(X,Y);                  //设置显示位置
        while(*s)                                  //检测字符串结束标志
        {
                LCD_write_dat(*s);          //写入当前字符
                s++;                                  //指向下一个字符
        }
}

LCD1602.h文件
#ifndef __LCD1602_H__
#define __LCD1602_H__


void LCD_init(void);//初始化函数声明
void LCD_write_command(unsigned char command);   //写入指令函数声明
void LCD_write_dat(unsigned char dat);           //写入数据函数声明
void LCD_set_xy(unsigned char x,unsigned char y);//设置显示位置函数声明
//void LCD_dsp_char(unsigned char x,unsigned char y,unsigned char dat);//显示一个字符函数声明
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//显示字符串函数声明

#endif

IMG_20160721_161029.jpg (2.41 MB, 下载次数: 0)

IMG_20160721_161029.jpg
此帖出自51单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表