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

Posted perseverance52

tags:

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

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

本文基于《51单片机七段数码管显示时钟无按键控制—①—74HC595版》修改实现,添加了按键调整时间

  • 仿真效果图
    在这里插入图片描述

  • 程序代码

#include "reg52.h"
#include "intrins.h"

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

//定义P0口的三个引脚,赋予不同的涵义
sbit SER = P0^1;    //p0.1脚控制串行数据输入
sbit SCK = P0^0;    //串行输入时钟
sbit RCK = P0^2;    //存储寄存器时钟

//按键定义
sbit key_stop = P1^0;
sbit key_star = P1^1;
sbit key_fen = P1^2;
sbit key_shi = P1^3;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
char duanMa[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//选择1-8哪个数码管段
char duanZhi[8]={0,0,0x40,0,0,0x40,0,0};	 	//保存8个数码管的中每个数码管段的数值 0x40:显示横杠

//num1:秒初始值 num2:分初始值 num3:时初始值
u16 miao=55,fen=59,shi=23;
//秒、分、时高位低位
u8 miao_L, miao_H, fen_L, fen_H, shi_L, shi_H; 

static int i = 0; 	//给中断计数使用

//函数声明
void SendTo595(char byteData);
void display();
void keyscan(); //按键函数
void key_delay(int xms);  //按键延时函数 x ms
/***********************************************************
*函数名		:display
*功能		:对传入的时分秒进行处理计算,转化为七段数码管要显示的值
*参数		:num1 秒	num2 分	  num3 时
************************************************************/
void display()
{

	//先发送8位位码,后发送8位段码
	//8位数码管需要发送8次
	char i=0;	//给单片机for循环使用,由于Keil4 把 变量定义放for里会报错,只能放函数体前面

	//分离每个数字的个位和十位/
//	static char shi1,ge1,shi2,ge2,shi3,ge3;
//	shi1=(char)miao/10;
//	ge1=(char)miao%10;

//	shi2=(char)fen/10;
//	ge2=(char)fen%10;

//	shi3=(char)shi/10;
//	ge3=(char)shi%10;
	///=======

	//保存段值/
	duanZhi[7]=smgduan[miao_L];
	duanZhi[6]=smgduan[miao_H];
	duanZhi[3]=smgduan[fen_H];
	duanZhi[4]=smgduan[fen_L];
	duanZhi[1]=smgduan[shi_L];
	duanZhi[0]=smgduan[shi_H];	
	///=======

	i=0;
	for(;i<8;i++)	
	{
		SendTo595(~duanMa[i]); 		//送段码
		SendTo595(duanZhi[i]);		//送位码
		
		/*位移寄存器数据准备完毕,转移到存储寄存器*/
	   RCK = 0;         
	   _nop_();
	   _nop_();
	   RCK = 1; 	   //检测到上升沿,让存储寄存器时钟变为高电平
	}
		
}


/*******************************************************************************
* 函 数 名         : TimerInit
* 函数功能		   : 定时器0初始化
* 参数			   :无
*******************************************************************************/
void TimerInit()
{
	TMOD|=0X01;	//选择为定时器0模式,工作方式1,仅用TR0打开启动。
	TH0=0X3c;	//给定时器赋初值,定时50ms 		3CB0
	TL0=0Xb0;	//0X3CB0的十进制是15536 从15536计数到65536计数50000次 即50000us=50ms	
	ET0=1;		//打开定时器0中断允许
	EA=1;		//打开总中断
	TR0=1;		//打开定时器	

}

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 参数			 :无
*******************************************************************************/	
void main()
{	
	TimerInit();
	
	while(1)
	{	
		display();
		keyscan(); //按键函数
	}	
}


/***********************************************************
*函数名		:SendTo595
*功能		:串行发送8个比特(一个字节)的数据给595,再并行输出
*参数		:byteData 
************************************************************/
void SendTo595(char byteData)
{
   char i=0;
    for(;i<8;i++)
   {
        SER = byteData>>7; 		//取出最高位(第8位)       
        byteData= byteData<<1;  //将第7位移动到最高位    

        SCK = 0;        //变为低电平,为下次准备  ,并延时2个时钟周期 
        _nop_();
        _nop_();

        SCK = 1;         //上升沿,让串行输入时钟变为高电平,
   }  
}


/*******************************************************************************
* 函 数 名         : Timer0()
* 函数功能		   : 定时器0中断函数
* 参数			   :无
*******************************************************************************/		
void Timer0() interrupt 1
{
	TL0 =(65536-50000)%256;//50ms预装载值
	TH0 =(65536-50000)/256;
	 i++;	
	if(i==20)//20个50毫秒即一秒
		{
			i=0;
			miao++;
			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;
		}
	//	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 key_delay(int xms){  //按键延时函数 x ms
	unsigned int i, j;
	for(i=0; i<xms; ++i)
		for(j=0; j<110; ++j)
			;
}//key_delay

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

基于51单片机定时器计数+2片74HC595联级+8位数码管时钟+按键修改时间

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

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

74hc595存储寄存器引脚是否可以悬空?他的原理是否让数据暂停?

单片机芯片之(74HC595/74LS595)

单片机引脚扩展芯片74HC595手工分解实验