基于51单片机+74LS138译码器+8位共阴数码管时钟设计—按键修改时间

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于51单片机+74LS138译码器+8位共阴数码管时钟设计—按键修改时间相关的知识,希望对你有一定的参考价值。

基于51单片机+74LS138译码器+8位数码管时钟设计—按键修改时间
通过74LS138译码器+8位共阴数码管配合实现时钟设计

为什么强调8位的数码管一定要是共阴的,因为,如果是采用共阳的8数码管是没法实现对数码管的每一个位进行控制的,这是由于74LS138输出特性所决定的。

  • 采用74LS138译码器可以节省4个IO的出来,除了节省IO口还有另外一个重要的原因就是单片机的驱动能力有限,在设计的过程当中,最好是单片机只负责运算和信号处理,驱动的事情交给其他专业的协同芯片来完成,不同芯片都有自己的专攻领地。
    在这里插入图片描述
  • 配合74HC245缓存器来使用效果,至于为什么还需采用外围的芯片驱动,请看上面的信息。
    在这里插入图片描述

程序代码:

#include<reg51.h>

typedef unsigned char uchar;
typedef unsigned int uint;

//按键定义
sbit key_stop = P2^0;
sbit key_star = P2^1;
sbit key_fen = P2^2;
sbit key_shi = P2^3;

//0~9的十六进制数码
//uchar code num[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};  // 0~9 7SegCA共阳数码管
//1100 0000,1001 1111,
unsigned char code num[]  = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
					  //共阴0-F段码,加code是存在rom里面
//秒、分、时标志
uchar miao = 0, fen = 0, shi = 0;  

//秒、分、时高位低位
uchar miao_L, miao_H, fen_L, fen_H, shi_L, shi_H; 

//计数
uint counter = 0;  


void delay(uint x){  //毫秒延时函数
	    unsigned int i=0,j=0;
    for(i=0;i<x;i++)
        for(j=0;j<123;j++);
		;
}//delay

void key_delay(int xms){  //按键延时函数 x ms
	unsigned int i, j;
	for(i=0; i<xms; ++i)
		for(j=0; j<110; ++j)
			;
}//key_delay

void T0_Init(){  //定时器初始化
	
	TMOD = 0x01; 
	TH0 = 0x3c;  
	TL0 = 0xb0;	 
    EA = 1;  //开总中断
	ET0 = 1;     
	TR0 = 1;    
}//T0_Init

void display(){  //显示函数
	
	//P1 = 0x20;  //0010 0000共阳数码管
	//P1 =0xdf;		//1101 1111共阴数码管
	P1=5;		//这是采用74LS138来实现控制的
	P0 = 0x40;	//段选显示-
	delay(2);

//	P1 = 0x04; //位选0000 0100 
//		P1 =0xfb;		//1111 1011
	P1 = 2;
	P0 = 0x40;//段选显示-
	delay(2);

	//P1 = 0x40;  // 1000 0000
	//P1=0X7F;		//0111 1111
	P1 = 7;
	P0 = num[miao_L];  
	delay(2);

//	P1 = 0x80;	// 0100 0000
	//	P1=0XBF;		//1011 1111
	P1 = 6;
	P0 = num[miao_H]; 
	delay(2);

//	P1 = 0x08;	// 0001 0000
//	P1=0XEF;		//1110 1111
	P1 = 4;
	P0 = num[fen_L];  
	delay(2);

//	P1 = 0x10;	// 0000 1000
//	P1=0XF7;		//1111 0111
	P1 = 3;
	P0 = num[fen_H];  
	delay(2);

//	P1 = 0x01;	// 0000 0010	
//	P1=0XFD;	//1111 1101
	P1 = 1;
	P0 = num[shi_L];  
	delay(5);
	
//	P1 = 0x02;	// 0000 0001
//	P1=0XFE;		//1111 1110
	P1 = 0;
	P0 = num[shi_H]; 
	delay(5);

}//display

void keyscan(){  //按键函数

	if(key_stop == 0){
		key_delay(10);
		if(key_stop == 0){
			EA = 0;  //关总中断,即停止
			while(!key_stop);
		}
	}//key_stop
	
	if(key_star == 0){
		key_delay(10);
		if(key_star == 0){
			EA = 1;  //开总中断
			while(!key_star);
		}
	}//key_star	
	
	if(key_fen == 0){
		key_delay(10);
		if(key_fen == 0){
			fen++;
			while(!key_fen);
		}
	}//key_fen++
	
	if(key_shi == 0){
		key_delay(10);
		if(key_shi == 0){
			shi++;
			while(!key_shi);
		}
	}//key_shi++
}

void main(){

	T0_Init(); 
	
	while(1){

		display();
		keyscan();		
   }

}

void timer0_Init() interrupt 1
{  //中断函数 
	TL0 =(65536-50000)%256;//50ms预装载值
	TH0 =(65536-50000)/256;
	 counter++;
//1秒钟=50ms*20=1000ms,20次计数为1秒钟
	 if(counter == 20){
	 	counter = 0;  
	 	miao++;	//i = 100 

		if(miao == 60){
			miao = 0;  
			fen++;

			if(fen == 60){
				fen = 0;  
				shi++;

				if(shi == 24){
					shi = 0;
					fen = 0;
					miao = 0;
				}
			}
		}

		miao_L = miao%10;  
		miao_H = miao/10; 

		fen_L = fen%10; 
		fen_H = fen/10;  

		shi_L = shi%10;  
		shi_H = shi/10;

	 }
 }//timer0_Init

对位选代码进行封装优化后的代码
//#include<reg51.h>
#include <STC89C5xRC.H>

typedef unsigned char uchar;
typedef unsigned int uint;

//按键定义
sbit key_stop = P2^0;
sbit key_star = P2^1;
sbit key_fen = P2^2;
sbit key_shi = P2^3;

//0~9的十六进制数码
//uchar code num[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};  // 0~9 7SegCA共阳数码管
//1100 0000,1001 1111,
unsigned char code num[]  = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//共阴0-F段码,加code是存在rom里面
//秒、分、时标志
uchar miao = 0, fen = 0, shi = 0;

//秒、分、时高位低位
uchar miao_L, miao_H, fen_L, fen_H, shi_L, shi_H;

//计数
uint counter = 0;

void Nixie(unsigned char Location);
void delay(uint x) { //毫秒延时函数
    unsigned int i=0,j=0;
    for(i=0; i<x; i++)
        for(j=0; j<123; j++);
    ;
}//delay

void key_delay(int xms) { //按键延时函数 x ms
    unsigned int i, j;
    for(i=0; i<xms; ++i)
        for(j=0; j<110; ++j)
            ;
}//key_delay

void T0_Init() { //定时器初始化

    TMOD = 0x01;
    TH0 = 0x3c;
    TL0 = 0xb0;
    EA = 1;  //开总中断
    ET0 = 1;
    TR0 = 1;
}//T0_Init

void display() { //显示函数

    //P1 = 0x20;  //0010 0000共阳数码管
    //P1 =0xdf;		//1101 1111共阴数码管
    //  P1=5;		//这是采用74LS138来实现控制的
    Nixie(5);
    P0 = 0x40;	//段选显示-
    delay(2);

//	P1 = 0x04; //位选0000 0100
//		P1 =0xfb;		//1111 1011
    // P1 = 2;
    Nixie(2);
    P0 = 0x40;//段选显示-
    delay(2);

    //P1 = 0x40;  // 1000 0000
    //P1=0X7F;		//0111 1111
    // P1 = 7;
    Nixie(7);
    P0 = num[miao_L];
    delay(2);

//	P1 = 0x80;	// 0100 0000
    //	P1=0XBF;		//1011 1111
    //  P1 = 6;
    Nixie(6);
    P0 = num[miao_H];
    delay(2);

//	P1 = 0x08;	// 0001 0000
//	P1=0XEF;		//1110 1111
//   P1 = 4;
    Nixie(4);
    P0 = num[fen_L];
    delay(2);

//	P1 = 0x10;	// 0000 1000
//	P1=0XF7;		//1111 0111
//    P1 = 3;
    Nixie(3);
    P0 = num[fen_H];
    delay(2);

//	P1 = 0x01;	// 0000 0010
//	P1=0XFD;	//1111 1101
//    P1 = 1;
    Nixie(1);
    P0 = num[shi_L];
    delay(5);

//	P1 = 0x02;	// 0000 0001
//	P1=0XFE;		//1111 1110
//    P1 = 0;
    Nixie(0);
    P0 = num[shi_H];
    delay(5);

}//display

void keyscan() { //按键函数

    if(key_stop == 0) {
        key_delay(10);
        if(key_stop == 0) {
            EA = 0;  //关总中断,即停止
            while(!key_stop);
        }
    }//key_stop

    if(key_star == 0) {
        key_delay(10);
        if(key_star == 0) {
            EA = 1;  //开总中断
            while(!key_star);
        }
    }//key_star

    if(key_fen == 0) {
        key_delay(10);
        if(key_fen == 0) {
            fen++;
            while(!key_fen);
        }
    }//key_fen++

    if(key_shi == 0) {
        key_delay(10);
        if(key_shi == 0) {
            shi++;
            while(!key_shi);
        }
    }//key_shi++
}

void main() {

    T0_Init();

    while(1) {

        display();
        keyscan();
    }

}

void timer0_Init() interrupt 1 { //中断函数

    TL0 =(65536-50000)%256;//50ms预装载值
    TH0 =(65536-50000)/256;
    counter++;
//1秒钟=50ms*20=1000ms,20次计数为1秒钟
    if(counter == 20) {
        counter = 0;
        miao++;	//i = 100

        if(miao == 60) {
            miao = 0;
            fen++;

            if(fen == 60) {
                fen = 0;
                shi++;

                if(shi == 24) {
                    shi = 0;
                    fen = 0;
                    miao = 0;
                }
            }
        }

        miao_L = miao%10;
        miao_H = miao/10;

        fen_L = fen%10;
        fen_H = fen/10;

        shi_L = shi%10;
        shi_H = shi/10;

    }
}//timer0_Init
 
void Nixie(unsigned char Location){
    switch(Location) {
    case 0 ://秒低位,Y0=0
        P10=0x00;
        P11=0x00;
        P12=0x00;
        break;
    case 1 ://时低位,Y1
        P10=0x01;
        P11=0x00;
        P12=0x00;
        break;
    case 2 ://时分间隔位-
        P10=0x00;
        P11=0x01;
        P12=0x00;
        break;
    case 3 ://分高位,Y3
        P10=0x01;
        P11=0x01;
        P12=0x00;
        break;
    case 4 ://分低位,Y4
        P10=0x00;
        P11=0x00;
        P12=0x01;
        break;
    case 5 ://秒分间隔位-
        P10=0x01;
        P11=0x00;
        P12=0x01;
        break;
    case 6 ://秒高位,Y6
        P10=0x00;
        P11=0x01;
        P12=0x01;
        break;
    case 7 ://秒低位,Y7
        P10=0x01;
        P11=0x01;
        P12=0x01;
        break;

    }

}

以上是关于基于51单片机+74LS138译码器+8位共阴数码管时钟设计—按键修改时间的主要内容,如果未能解决你的问题,请参考以下文章

Proteus仿真51单片机利用定时器倒计数(99-0)

51单片机+MACX7219驱动8位共阴数码管显示示例

3.8 51单片机-M74HC138译码器驱动8位数码管

51单片机+DS1302+MAX7219驱动8位共阴数码管显示时间

Arduino UNO+DS1302+74HC595联级+8位共阴数码管时钟+Proteus仿真

51单片机 74LS138译码器流水灯+Proteus仿真