本帖最后由 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;}
}
}
|