发新帖我要提问
12
返回列表
打印

关于74HC164驱动数码管显示的问题

[复制链接]
楼主: tomegeo
手机看帖
扫描二维码
随时随地手机跟帖
21
tomegeo|  楼主 | 2008-3-6 11:28 | 只看该作者 回帖奖励 |倒序浏览

谢谢大家的热情帮助呀!

一大早看到大家怎么热情的帮助,心理好舒服呀!
按照大家的分析,就是说如果用164的话,用hotpower大侠说的第一种方法能解决问题,这个我试过效果没那么好,有可能是我对三极管的偏置电阻没有设置好或者程序有问题。
但是,我现在郁闷的是别人不用加三极管,可以做到不会闪呀,呵呵,所以想和大家讨论一下到底是用什么办法来解决这个问题的。

使用特权

评论回复
22
artxun| | 2010-8-29 21:56 | 只看该作者
呵呵,我也遇到这个问题
不过我是当显示有变化时才执行移位送数的,就算是闪也只是一下。不过当要做成小数点闪动时就不行了,因为闪动时要500ms发一次数,这就出现闪了

使用特权

评论回复
23
jiao_yx| | 2010-8-30 10:53 | 只看该作者
发一段我的程序,用595,整篇程序没有延时指令,显示和键盘扫描汇编子程序
;----------------------------------------
;              动态显示子程序   
;----------------------------------------
;动态显示只能一位一位的显示
disp:                jnb        keyscan_f,disp1
;**********************求键值***********************
                setb        p1.0
                mov        a,#00001100b                ;键盘扫描,扫描SET键,输入低电平                       
                call        duan_disp
                jb        p1.0,key_disp1
                jnb        set_f,key_disp0                ;
                mov        key_value,#01h
key_disp0:        setb        set_f                        ;set_f为设置键去抖动标志位
                clr        jia_f
                clr        jian_f
               
                jmp        disp00

key_disp1:        clr        set_f
                mov        a,#00010100b                ;扫描加键
                call        duan_disp               
                jb        p1.0,key_disp2
                jnb        jia_f,key_disp11
                mov        key_value,#02h
key_disp11:        setb        jia_f
                clr        jian_f                ;防止2个键同时按下时的情况
                jmp        disp00

key_disp2:        clr        jia_f
                mov        a,#00011000b
                call        duan_disp               
                jb        p1.0,key_disp3
                jnb        jian_f,key_disp22
                mov        key_value,#03h
key_disp22:        setb        jian_f               
                jmp        disp00

key_disp3:        clr        jian_f               
                mov        key_value,#00h               
                jmp        disp0
               
disp00:                clr        keyno_f                ;有按键时,清没有按键标志位
                mov        cnt_keyno,#00        ;有按键时,键值计数器清零
disp0:                clr        keyscan_f
disp1:                mov        a,cnt_disp        ;先求出显示第几位
                clr        c
                mov        r0,#s11
                jmp        cha00
cha0:                inc        r0
cha00:                rlc        a
                jnc        cha0               
                mov        dptr,#disp_tab        ;查表               
cha1:                mov        a,@r0
                movc        a,@a+dptr
                mov        r0,cnt_disp        ;再次利用r0
                cjne        r0,#00100000b,cha11        ;加13小数点
                jnb        dian13,cha12
                inc        a
                jmp        cha12
cha11:                cjne        r0,#00000100b,cha12        ;加22小数点
                jnb        dian22,cha12
                inc        a

cha12:                cjne        r0,#00000001b,cha2        ;指示灯显示               
                setb        keyscan_f                ;扫描完最后一位数码管后进入键盘扫描

                jnb        flash_f,cha12_1                ;1秒指示灯闪烁一次
                jnb        banmiao_f,cha12_1
                mov        a,#00011100b                ;消隐
                jmp        cha2

cha12_1:        mov        a,#00h
                jnb        led_jiare,cha13                ;点亮加热等灯
                orl        a,#10011100b
cha13:                jnb        led_paifeng,cha14        ;点亮排风灯
                orl        a,#01011100b
cha14:                jnb        led_shoudong,cha2        ;点亮手动灯
                orl        a,#00111100b
       
cha2:                call        duan_disp
                mov        a,cnt_disp

                        jnb        flash_f,cha4
                        jnb        banliang_f,cha4
                        cjne        a,#00010000b,cha3
cha3:                        jc        cha4
                        mov        a,#00h                ;前4位亮度减半,


cha4:                mov        p1,a                ;送位码
                mov        a,cnt_disp
                rr        a                ;这就8位
                mov        cnt_disp,a        ;位码右移一位
                call        dog
disp_end:        ret

duan_disp:        clr        rclk_595        ;把段数据送出
                clr        c
                mov        r0,#8
duan1:                clr        sclk_595
                rrc        a
                mov        a_595,c               
                setb        sclk_595               
                djnz        r0,duan1
                setb        rclk_595
                ret

disp_tab:
        db        0FCH,060H,0DAH,0F2H,066H,0B6H,0BEH,0E0H,0FEH,0F6H
;显示                 0    1   2    3    4    5    6    7     8    9
        db        0eeh,3eh,1ah,7ah,9eh,02h;8eh
;显示              A   b   c   d   E   -       
        db        00H,0ffh,02h,1eh,6eh,1ch,62h,0ech;2ah
;显示                消隐 全亮 -  t   H   L  -1  n   
        db        3ah,0ceh,10h,70h,60h,0ah,38h,0fdh
;                o    P   _   J    i   r          u   0.
        db        76h

使用特权

评论回复
24
dong_abc| | 2010-8-30 11:35 | 只看该作者
刚做了这个,传上来
[local]1[/local]

使用特权

评论回复
25
dong_abc| | 2010-8-30 11:39 | 只看该作者
看过温子琪大哥的教程,里面的一个例子
#include <REGX51.H>

#define        HIGH   1
#define        LOW    0
#define SEG_PORT P2    //LEDλѡ

#define        LS164_DATA(x)  {if(x) P0_0=1;else P0_0=0;}
#define        LS164_CLK(x)   {if(x) P0_1=1;else P0_1=0;}

unsigned int TimeCount=0;
unsigned char Time0ISREvent=0;
unsigned char Time1SecEvent=0;
unsigned char SegCurPostition=0;

code unsigned char SegCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0xff};
unsigned char SegBuf[4]={0};
code unsigned char SegPostition[4]={0xf7,0xfb,0xfd,0xfe};

void LS164Send(unsigned char byte)
{
unsigned char i;
for(i=0;i<=7;i++)
   {
    if(byte&(1<<(7-i)))
         {
           LS164_DATA(HIGH);
         }
        else
         {
           LS164_DATA(LOW);
         }
         LS164_CLK(LOW);
         LS164_CLK(HIGH);
   }
}

void SegReFreshDisplayBuf()
{
SegBuf[0]=TimeCount%10;
SegBuf[1]=TimeCount/10%10;
SegBuf[2]=TimeCount/100%10;
SegBuf[3]=TimeCount/1000%10;
}

void SegDisplay()
{
unsigned char SegData;
SEG_PORT|=0x0f;       
SegData=SegCode[SegBuf[SegCurPostition]];
LS164Send(SegData);
SEG_PORT=SegPostition[SegCurPostition];
if(++SegCurPostition>=4)
  {
           SegCurPostition=0;
  }
}

void TimerInit()
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TMOD=0x01;
}

void Timer0Start()
{
TR0=1;
ET0=1;
}

void PortInit()
{
P0=0xff;
}

void main()
{
PortInit();
TimerInit();
Timer0Start();
SegReFreshDisplayBuf();
EA=1;
while(1)
{
    if(Time0ISREvent)
    {
           Time0ISREvent=0;
           if(Time1SecEvent)
           {
                  Time1SecEvent=0;
                  if(++TimeCount>=9999)
                  {
                    TimeCount=0;
                  }
                  SegReFreshDisplayBuf();
           }
           SegDisplay();
    }
}
}

void  Timer0ISR(void) interrupt 1
{
  static unsigned int cnt=0;
  TH0=(65536-5000)/256;
  TL0=(65536-5000)%256;
  Time0ISREvent=1;
  if(++cnt>=200)
  {
     cnt=0;
         Time1SecEvent=1;          
  }
}

使用特权

评论回复
26
善解人意| | 2010-8-30 17:12 | 只看该作者
这个我也做个,是做的电子时钟。我只用了一个74LS164和74LS138点6个数码管,74LS164来接a-g,六个数码管的a-g并在一起,74LS138来点每个数码管的阳极,要加个PNP的管子在来驱动。动态扫描用定时器来的。

使用特权

评论回复
27
linjing| | 2010-8-30 18:59 | 只看该作者
这个没有很好的办法,用164带LED总会有鬼影存在,只能减轻,无法彻底削除!
以前见过别人接电容的,电路具体怎么接没仔细看,效果会好一点点,但也很有限,而且需要接很多电容
个人建议,
1、74164换成74HC595
2、如果单片机的资源还算富裕,用一个74164,加接6个三极管(或者ULN2003A),做成动态显示的
3、用专用的LED显示驱动芯片,如MAX7219。

我一般都是用动态显示,口线占用多点,但软件开销并不大。
据说MAX7219的可靠性不太好,现在有许多兼容的型号,可以找找看。

使用特权

评论回复
28
linjing| | 2010-8-30 19:04 | 只看该作者
26# 善解人意

试试把74138换成74145,可以简化电路,不需要用三极管的
当然前提是亮度不要求很亮,数码管需要换成共阴的

使用特权

评论回复
29
清风明月张| | 2012-4-14 21:32 | 只看该作者
12楼的没写错吧

使用特权

评论回复
30
wanghx70| | 2014-3-25 13:58 | 只看该作者
显示亮度有问题

使用特权

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

本版积分规则