[应用方案] 节约N76E003的引脚,使用两片74HC595级联驱动4位8段数码管

[复制链接]
596|15
 楼主 | 2018-11-13 14:19 | 显示全部楼层 |阅读模式
本帖最后由 cry1109 于 2018-11-13 16:21 编辑

N76E003只有20个引脚,驱动4位8段数码管时为了节约引脚,可以使用两片74HC595(8位3态移位寄存/锁存输出的芯片)驱动数码管,采用动态扫描方式。

两片74HC595的级联以及与数码管的连接电路图。

74HC595和N76E003的连接电路图。

74HC595时序图。
74HC595的具体使用方法百度之。我只说一下重要的部分:第一片595用于位选,第二片595用于段选,两片级联时先写段码再写位码,一个8位的数据是串行一位一位的写入595中,这样将段码写入第一片595后再写接着写位码时,单片机每写一位位码,则第一片中的锁存的段码就通过QH'引脚串行一位一位的移入到下一片595中,8位位码写完毕后第一片的595中的段码全部移入到第二片595中,此时第一片595锁存着一个8位的位码而第二片595锁存着段码,段码位码都写完毕后给RCK引脚一个上升沿,两片595同时并行输出锁存的8位数据,达到串行并出的效果。同样3片级联、4片级联...,依次类推。段码位码的写入顺序根据实际电路修改,我的电路是用于片选的595和单片机相连,所以先写段码后写位码。代码有很详细的注释,仅供参考。


/*********************************
*********************************/
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"


#define TH0_INIT        50000
#define TL0_INIT         50000


sbit DAT=P1^0;
sbit RCK=P1^1;
sbit SCK=P1^2;
sbit key=P1^3;

unsigned char code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};                // 共阳极数码管 0 1 2 3 4 5 6 7 8 9
unsigned char code wei[]={0x01,0x02,0x04,0x08};                                               //共4位
unsigned char  update[]={0x00,0x01,0x02,0x03};                                                //更新数据缓存

UINT8 u8TH0_Tmp,u8TL0_Tmp;
unsigned char tcount;
int num;


/*******************************
向74HC595写入数据
*******************************/
void write595(unsigned char Data)
{
        unsigned char i;
        for(i=0;i<8;i++)        //循环8次,刚好移完8位
        {
                SCK= 0;                                        //先将移位寄存器控制引脚置为低   
                _nop_();
                DAT=Data&0x80;        
                /*******************************************
                 if((Data & 0x80)== 0x80)     写入数据的另一种方式
                 DAT=1;
                 else
                 DAT=0;
                ******************************************/
               
                Data<<=1;                   //将数据的次高位移到最高位
                SCK=1;                                   //再将移位寄存器控制引脚置为高,产生一个上升沿,写入一位数据
        }
}

void out595(void)
{
        RCK=0;     //先将RCK引脚置为低
        _nop_();
        RCK=1;     //再将RCK引脚置为高,产生移一个上升沿,上升沿时移位寄存器的数据进入数据存储寄存器,显示数据
}


void main(void)
{

        unsigned int i;
        
        P10_Quasi_Mode;
        P11_Quasi_Mode;
        P12_Quasi_Mode;
        P13_Quasi_Mode;
        P14_PushPull_Mode;
        
        TIMER0_MODE1_ENABLE;
        
        //clr_T0M;
/*******************************
定时器初始化设置(参考官方代码)
*******************************/        
        u8TH0_Tmp = (65536-TL0_INIT)/256;
        u8TL0_Tmp = (65536-TL0_INIT)%256;   

        TH0 = u8TH0_Tmp;
        TL0 = u8TL0_Tmp;
        
        set_TR0;                //TR0=1打开定时器0
        set_EA;                  //EA=1使能全局中断                  
        
        
/*******************************
                           按键处理程序
*******************************/        
        while(1)
        {
                unsigned int a;
        
                if(key==0)
                {        
                        Timer0_Delay1ms(10);                // 按键消抖
                        if(key==0)
                        {
                                a++;
                                if(a==2)
                                {a=0;}
                        }
                        while(key==0);        
                }
                switch(a)
                {
                        case 0:P14=0;clr_ET0;break;
                        case 1:P14=1;set_ET0;break;
                }
               
                update[0]=num/1000;                             // 千位
                update[1]=num/100%10;                        // 百位
                update[2]=num/10%10;                         // 十位
                update[3]=num%10;                              // 个位
               
                for(i=0;i<4;i++)                 //4位数码管循环4次,依次写入每位数据并显示
                {
                        write595(duan[update]);     //先写段码
                        write595(wei);                                             //再写位码
                        out595();                                                                                   //显示锁存数据
                        Timer0_Delay1ms(4);                                                 //每位数码管显示延时4ms以内
                }        
        }
}


/*******************************
定时器0中断处理
*******************************/
void Timer0_ISR (void) interrupt 1 //interrupt address is 0x000B
{
  TH0 = u8TH0_Tmp;
  TL0 = u8TL0_Tmp;
        
        tcount++;                                                                        
        if(tcount==10)                                //调整计时速度(需要显示的数据更新速度)
        {
                tcount=0;
                num++;
                if(num>9999)
                {num=0;}
        }               
}














本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2018-11-13 16:15 | 显示全部楼层
为何不直接用N76E003的SPI驱动595,简单,速度也快!
| 2018-11-13 16:39 | 显示全部楼层
也可以用一片7219驱动8个数码管。
| 2018-11-13 17:52 | 显示全部楼层
两片595都用上了,不如用专用的显示芯片,2-3个引脚,按键都有了,还不用动态扫描
| 2018-11-13 21:29 | 显示全部楼层
看来大家都有丰富的经验了
| 2018-11-15 20:42 | 显示全部楼层
这个方法好,另外这个芯片很便宜。
| 2018-11-16 22:30 | 显示全部楼层
只要能实现自己的功能就是好。
| 2018-11-19 23:22 | 显示全部楼层
多谢分享啊,这个方法好。
| 2018-11-20 00:16 | 显示全部楼层
本帖最后由 tuoxieshu 于 2018-11-20 00:30 编辑

595是好东西,以前我也写过文章介绍过。当时还画了一个动态图帮助大家理解原理。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评论

tuoxieshu 2018-11-21 00:40 回复TA
@cry1109 :哈哈 
cry1109 2018-11-20 08:11 回复TA
说不定我在使用595时就参考过你的帖子,哈哈哈 
| 2018-11-20 10:35 | 显示全部楼层
用TM1620或其他专门LED驱动IC更好。。
| 2019-1-27 11:47 | 显示全部楼层
实现自己的功能就是好
| 2019-1-27 23:14 | 显示全部楼层
还有个方法上管脚多的系列。003是低管脚系列的。
| 2019-1-27 23:14 | 显示全部楼层
另外就是用LED驱动芯片。也不贵。
| 2019-2-1 22:34 | 显示全部楼层
LED驱动芯片在便宜也比595贵
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表