打印

【求助】电压表数码管显示不正常

[复制链接]
3256|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wuwei1029|  楼主 | 2010-1-18 10:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
俺是菜鸟!做一个电压表遇到的问题,我用的AD是AD1674,数码管是4位共阳!
做出来可以比较准确的显示数值,但发现最后一位数值来回在几个数中间闪烁,不能够稳定显示,而且最后一位比其他几位稍亮,不知程序需要怎样修改,困惑了几天了

感谢各位大侠抒发高见!

以下是程序:

#include <reg52.h>
#include <intrins.h>
sbit CE=P3^0;
sbit RC=P3^1;
sbit STS=P3^2;
sbit LE=P3^5;
sbit A0=P3^6;
sbit CS=P3^3;
#define N 0x0fff                   //十二位转换
unsigned long result=0;
unsigned char seg[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char buf[4];

void delay(n)
{
int i;
while(n--)
for(i=0;i<10;i++);
}
void inti()
{
CS=1;            /*初始化AD*/
CE=0;
}
unsigned int ad1674_convert()
{
unsigned int temp=0;
//STS=1;
inti();
CS=0;     /*启动12位AD*/
delay(1);
A0=0;
delay(1);
RC=0;//
delay(1);
CE=1;
delay(1);
//while(STS==1);
{
CE=0;
delay(1);
RC=1;
delay(1);
A0=0;
delay(1);
CE=1;
delay(1);
temp=P0;
temp=P0<<4;
CE=0;
delay(1);
RC=1;
delay(1);
A0=1;
delay(1);
CE=1;
delay(1);
temp+=P0>>4;
}
CE=0;
CS=1;
return temp;
}
void dispute()
{
unsigned long result1;       //用于中途的数据转换
unsigned long vol,vol_c;    //电压显示,与电压的一个进位
result1=result*20000;      //*100*10*10v  扩大一百倍,用来替代两位小数,扩大十倍用来小数点后第三位四舍五入?
                  

          //又乘以20,是最电压
vol=result1/N;             // vol=result/0x0fff*10(v)   
vol_c=vol%10;
if(vol_c>=5)              //四舍五入
vol=vol+10;
vol=vol/10;
buf[0]=vol/1000;
buf[1]=vol/100%10;
buf[2]=vol/10%10;
buf[3]=vol%10;
}
void display()      //显示子程序.
{

int i=0;
unsigned char m;

m=0x7f;
while(1)
{
for(i=0;i<4;i++)
   {
LE=0;
m=_crol_(m,1);     
P2=m;
LE=1;
if(i==1)
P1=seg[buf[i]]-0x80;       //加小数点
else P1=seg[buf[i]];
LE=0;
delay(15);
P1=0xff;         //关显示,进行下一次测试

   }
}  
}


main()
{
while(1)
{
result=ad1674_convert();
dispute();
delay(1);
display();
delay(20);
}
}

相关帖子

沙发
mohanwei| | 2010-1-19 19:34 | 只看该作者
最好在定时器中断里显示。
定义一个显示缓冲区:unsigned char disp_buff[4];
主程序里将数值写入disp_buff[]即可。
定时器中断里:
static unsigned char pos=0;
if(pos==0)
{
      //送数显示第1个数码管
}
else if(pos==1)
{
      //送数显示第2个数码管
}
else if(pos==2)
{
      //送数显示第3个数码管
}
else if(pos==3)
{
      //送数显示第4个数码管
}

pos++;//下一次中断显示下一个数码管
if(pos>=4)
{
     pos=0;
}

只要定时器中断周期设置合理(例如20ms),就能实现自动显示扫描了。显示效果绝对非常稳定。

使用特权

评论回复
板凳
wuwei1029|  楼主 | 2010-1-20 15:12 | 只看该作者
你好! 请问有具体的简单小例子让我看下嘛!

使用特权

评论回复
地板
ljolove| | 2010-1-20 18:14 | 只看该作者
存几个数取个平均最后一位就稳了,要不就降低AD采样速率,也可以稳定数值

使用特权

评论回复
5
wuwei1029|  楼主 | 2010-1-21 08:01 | 只看该作者
4# ljolove

使用特权

评论回复
6
wuwei1029|  楼主 | 2010-1-21 08:02 | 只看该作者
4# ljolove 你好 ,很感谢您的回答!请您看一下我这个程序的AD采样速率应该怎样改呢?

使用特权

评论回复
7
ljolove| | 2010-1-21 10:30 | 只看该作者
#pragma vector=TIMER0_OVF_vect  //timer0 interrupt overflew   1ms
__interrupt void timer0_irq(void)
{
   ADCTimeBase++;
   if(ADCTimeBase==400)//ADC 2.5 CONVERTS PER SEC
   {
        ADCTimeBase=0;
        if(adeoc1)
        {
            adeoc1=0;  
            ADCSRA |=(1<<ADSC);
        }   
    }
   TCNT0=0xf7;
}这个定时器中断,两个变量,一个用来计时,还有一个就是完成的标志,如果时间到,在定时器里判断转换是否完成,如果完成,打开AD进行下一次转换
#pragma vector=ADC_vect   //adc complete interrupt
__interrupt void ADC_Eoc(void)
{
    acc +=ADC&0x3FF;
    dec_int--;
    if(dec_int==0)
    {
        dec_int=256;
        ADCSRA &=0XBF;//stop adc                                
        ADC_Buffer = acc >>4;
        acc=0;
        adoc=1;
        adeoc1=1;
    }
    else
    {
        ADCSRA |= 1<<ADSC;
    }   
}这个是ADC完成中断,在完成中断里面致另外一个标志,在主程序里面插这个标志就OK了,然后读书处理就可以了.我这个是AVR的,你改改就可以用在51上了,而且你的AD应该也接外部中断了吧

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
wuwei1029 + 1 谢谢你
8
wuwei1029|  楼主 | 2010-1-26 13:44 | 只看该作者
7# ljolove
感谢朋友的指导我用了定时器中断降低了AD的转换速率,现在显示情况很稳定
谢谢了!@

使用特权

评论回复
9
ljolove| | 2010-1-26 19:54 | 只看该作者
其实最简单的办法取个平均就OK了,呵呵

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

20

帖子

0

粉丝