打印

为啥数码管显示跳动厉害?这是显示3路AD转换输出的程序..

[复制链接]
1179|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#include <reg52.h>
#include <intrins.h>
#define PCF8591_ADDR         0x90
#define DACOUT_EN                0x40

typedef unsigned char uchar;
typedef unsigned int uint;


uchar code leddata[]={

                0x3F,  //"0"
                0x06,  //"1"
                0x5B,  //"2"
                0x4F,  //"3"
                0x66,  //"4"
                0x6D,  //"5"
                0x7D,  //"6"
                0x07,  //"7"
                0x7F,  //"8"
                0x6F,  //"9"
                0x77,  //"A"
                0x7C,  //"B"
                0x39,  //"C"
                0x5E,  //"D"
                0x79,  //"E"
                0x71,  //"F"
                0x76,  //"H"
                0x38,  //"L"
                0x37,  //"n"
                0x3E,  //"u"
                0x73,  //"P"
                0x5C,  //"o"
                0x40,  //"-"
                0x00,  //熄灭
                0x00  //自定义

                         };


/*位声明*/
sbit SCL = P2^1;
sbit SDA = P2^0;
sbit du = P2^6;
sbit we = P2^7;
sbit AD0_OK = P1^0;
sbit AD1_OK = P1^1;
sbit AD2_OK = P1^2;
sbit AD3_OK = P1^3;
/*延时5us*/
void delay_5us()
{
        _nop_();
}

/*延时1ms*/
void delay(uint z)
{
        uint x,y;
        for(x = z; x > 0; x--)
                for(y = 114; y > 0 ; y--);
}

/**数码显示函数(为0的位不显示)**/
void display_567bit(uchar cc)
{
        uchar ge,shi,bai;

        bai = cc / 100;
        shi = (cc - bai*100) / 10;
        ge = cc % 10 ;

        if(cc > 99 && cc < 999)
        {
                P0 = 0xff;
                we = 1;P0 = 0xdf;//1101 1111
                we = 0;
                du = 1;P0 = leddata[bai];
                du = 0;
                delay(1);
       
                P0 = 0xff;//数码管清零
                we = 1;P0 = 0xbf;
                we = 0;
                du = 1;P0 = leddata[shi];
                du = 0;
                delay(1);       
       
                P0 = 0xff;
                we = 1;P0 = 0x7f;
                we = 0;
                du = 1;P0 = leddata[ge];
                du = 0;
                delay(1);               
        }
        else if(cc > 9 && cc < 99)
        {
                P0 = 0xff;//数码管清零
                we = 1;P0 = 0xbf;
                we = 0;
                du = 1;P0 = leddata[shi];
                du = 0;
                delay(1);       
       
                P0 = 0xff;
                we = 1;P0 = 0x7f;
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(1);
        }
        else
        {
                P0 = 0xff;
                we = 1;P0 = 0x7f;
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(1);
        }
}

/**数码显示函数(为0的位不显示)**/
void display_34bit(uchar cc)
{
        uchar ge,shi,bai;

        bai = cc / 100;
        shi = (cc - bai*100) / 10;
        ge = cc % 10 ;

         if(cc > 9 && cc < 99)
        {
                P0 = 0xff;//数码管清零
                we = 1;P0 = 0xf7;//1111 0111
                we = 0;
                du = 1;P0 = leddata[shi];
                du = 0;
                delay(1);       
       
                P0 = 0xff;
                we = 1;P0 = 0xef;//1110 1111
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(1);
        }
        else
        {
                P0 = 0xff;
                we = 1;P0 = 0xef;//1110 1111
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(1);
        }
}

/**数码显示函数(为0的位不显示)**/
void display_012bit(uchar cc)
{
        uchar ge,shi,bai;

        bai = cc / 100;
        shi = (cc - bai*100) / 10;
        ge = cc % 10 ;

        if(cc > 99 && cc < 999)
        {
                P0 = 0xff;
                we = 1;P0 = 0xfe;//1111 1110
                we = 0;
                du = 1;P0 = leddata[bai];
                du = 0;
                delay(3);
       
                P0 = 0xff;//数码管清零
                we = 1;P0 = 0xfd;//1111 1101
                we = 0;
                du = 1;P0 = leddata[shi];
                du = 0;
                delay(3);
       
                P0 = 0xff;
                we = 1;P0 = 0xfb;//1111 1011
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(1);               
        }
        else if(cc > 9 && cc < 99)
        {
                P0 = 0xff;//数码管清零
                we = 1;P0 = 0xfd;//1111 1101
                we = 0;
                du = 1;P0 = leddata[shi];
                du = 0;
                delay(3);
       
                P0 = 0xff;
                we = 1;P0 = 0xfb;//1111 1011
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(3);
        }
        else
        {
                P0 = 0xff;
                we = 1;P0 = 0xfb;//1111 1011
                we = 0;
                du = 1;P0 = leddata[ge] + 0x80;
                du = 0;
                delay(3);
        }
}

/*I2C初始化*/
void I2C_init()
{
        SCL = 1;
        _nop_();
        SDA = 1;
        _nop_();
}

/*I2C起始信号*/
void I2C_start()        //I2C起始信号
{
        SDA = 1;
        _nop_();        //小延时 让总线稳定
        SCL = 1;
        delay_5us();
        SDA = 0;
        delay_5us();
}

/*I2C终止信号*/
void I2C_stop()                //I2C终止信号
{
        SDA = 0;
        _nop_();        //小延时 让总线稳定
        SCL = 1;
        delay_5us();
        SDA = 1;
        delay_5us();
}

/*主机发送应答*/
void master_answer(bit i)                //主机发送应答信号,以回复从机是否应答
{
         SCL = 0;        //拉低时钟总线SLC,允许数据总线SDA上的数据变化
         _nop_();        //稳定总线
         if(i)
         {
                 SDA = 0;//发送应答
         }
         else
         {
                 SDA =1;//发送非应答
         }
         _nop_();
         SCL = 1;        //拉高时钟总线,以让从机读走主机的应答信号
         delay_5us();        //按照I2C时序,必须延时4us
         //此时从机已经读完应答信号
         SCL = 0;        //时钟拉低,占用总线继续通信,
         _nop_();
         SDA = 1;        //数据总线拉高,释放数据总线,交由从机控制
         _nop_();
}

/*测试从机应答*/
bit test_answer()        //测试从机的应答
{
        SCL = 1;        //只有时钟总线为1 ,才能接受应答信号
        delay_5us();//I2C时序要求,必须延时4us
        if(SDA)
        {
                SCL = 0;        //拉低,以让SDA可变
                _nop_();
                I2C_stop();
                return(0);         //返回非应答
        }
        else
        {
                SCL = 0;        //拉低,以让SDA可变
                _nop_();
                return(1);         //返回非应答
        }
         SCL = 0;        //时钟拉低,占用总线继续通信,
         _nop_();
         SDA = 1;        //数据总线拉高,释放数据总线,交由从机控制
         _nop_();
}

/*发送一个字节*/
void I2C_send_byte(uchar byte)
{
        uchar i;
        for(i = 0; i < 8 ;i++)
        {
                SCL = 0;
                _nop_();
                if(byte & 0x80)                //1000 0000
                {
                        SDA = 1;
                        _nop_();
                }
                else
                {
                        SDA = 0;
                        _nop_();
                }
                SCL = 1;
                _nop_();
                byte <<= 1;                 //byte = byte << 1;
         }
         SCL = 0;        //时钟拉低,占用总线继续通信
         _nop_();
         SDA = 1;        //数据总线拉高,释放数据总线
         _nop_();
}

/*读一个字节*/
uchar I2C_read_byte()
{
        uchar i,dat;
        SCL = 0;
        _nop_();
        SDA = 1;
        _nop_();

        for(i = 0; i < 8 ;i++)
        {
                SCL = 1;        //SCL置高以使SDA保持,才可以读数据
                _nop_();
                if(SDA)
                {
                        dat = dat | 0x01;
                }
                else
                {
                        dat = dat & 0xfe;
                }

                _nop_();
                SCL = 0;
                _nop_();

                if(i < 7)
                {
                        dat = dat << 1;
                }
         }
         return (dat);
         SCL = 0;        //时钟拉低,占用总线继续通信
         _nop_();
         SDA = 1;        //数据总线拉高,释放数据总线
         _nop_();
}

/*DAC发送数据*/
bit DAC_OUT(uchar dat)
{
        bit ACK_flag;
        I2C_start();
        I2C_send_byte(PCF8591_ADDR + 0);
        if(test_answer() == 0)
        {
                ACK_flag = 1;
        }       
        I2C_send_byte(DACOUT_EN);        //DA输出使能
        if(test_answer() == 0)
        {
                ACK_flag = 1;       
        }
        I2C_send_byte(dat);
        if(test_answer() == 0)
        {
                ACK_flag = 1;       
        }
        I2C_stop();
        delay(5);
        if(ACK_flag == 1)
        {
                return 0;
        }
        else
                return 1;
}

/*读AD数据*/
uchar ADC_Read(uchar CON)
{
        uchar DAC_Value;

        bit ACK_flag;
        I2C_start();
        I2C_send_byte(PCF8591_ADDR + 0);
        if(test_answer() == 0)
        {
                ACK_flag = 1;       
        }
        I2C_send_byte(CON);
        if(test_answer() == 0)
        {
                ACK_flag = 1;                          
        }
        master_answer(0);
        I2C_start();
        I2C_send_byte(PCF8591_ADDR + 1);
        if(test_answer() == 0)
        {
                ACK_flag = 1;       
        }
        DAC_Value = I2C_read_byte();        //将读出的数据赋给 全局变量 DAC_Value
        master_answer(0);  
        I2C_stop();
    delay(2);
        if(ACK_flag == 1)
        {
                return 0;
        }
        else
        return DAC_Value;
}

void main()
{
        I2C_init();
        while(1)
        {
                if( DAC_OUT(ADC_Read(0x00)) )                        AD0_OK = 0;                else                AD0_OK = 1;
                display_012bit(ADC_Read(0x00));
                  
                if( DAC_OUT(ADC_Read(0x01)) )                        AD1_OK = 0;                else                AD1_OK = 1;
                display_34bit(ADC_Read(0x01));
                  
                if( DAC_OUT(ADC_Read(0x02)) )                        AD2_OK = 0;                else                AD2_OK = 1;
                display_567bit(ADC_Read(0x02));
                                                                            
                if( DAC_OUT(ADC_Read(0x03)) )                        AD3_OK = 0;                else                AD3_OK = 1;
        }
}


相关帖子

沙发
ayb_ice| | 2015-11-13 21:40 | 只看该作者
定时中断显示才有实时保障

使用特权

评论回复
板凳
努力总会发光i|  楼主 | 2015-11-15 16:23 | 只看该作者
ayb_ice 发表于 2015-11-13 21:40
定时中断显示才有实时保障

是的。我改成中断服务程序里显示了,3us刷新一次。

使用特权

评论回复
地板
ayb_ice| | 2015-11-15 16:55 | 只看该作者
努力总会发光i 发表于 2015-11-15 16:23
是的。我改成中断服务程序里显示了,3us刷新一次。

1到10个毫秒差不多,

使用特权

评论回复
5
NE5532| | 2015-11-15 20:18 | 只看该作者
楼主查一下人眼的视觉暂留时间是多少?你这个us级的,是给黄金圣斗士看的。

使用特权

评论回复
6
努力总会发光i|  楼主 | 2015-11-16 11:55 | 只看该作者
ayb_ice 发表于 2015-11-15 16:55
1到10个毫秒差不多,

ms级的行不通啊,闪烁得厉害,只能用us

使用特权

评论回复
7
ayb_ice| | 2015-11-16 13:30 | 只看该作者
努力总会发光i 发表于 2015-11-16 11:55
ms级的行不通啊,闪烁得厉害,只能用us

那就是你程序有问题

使用特权

评论回复
8
NE5532| | 2015-11-16 14:07 | 只看该作者
先把扫描的原理查清楚,不要说mS的不行,是你自己写的不对。

使用特权

评论回复
9
努力总会发光i|  楼主 | 2015-11-16 18:59 | 只看该作者
NE5532 发表于 2015-11-16 14:07
先把扫描的原理查清楚,不要说mS的不行,是你自己写的不对。

那您能发个您的数显程序,我参考参考

使用特权

评论回复
10
NE5532| | 2015-11-16 21:04 | 只看该作者
两次扫描间隔不能大于20mS,在此基础上,每个管子尽量延长点亮时间,可增加亮度。你调一下试试。

使用特权

评论回复
11
zgy8864| | 2015-11-16 22:06 | 只看该作者
2ms 扫描一次就够了。3uS一次太快了,单片机会跑不过来。

使用特权

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

本版积分规则

1

主题

5

帖子

0

粉丝