zoukankan      html  css  js  c++  java
  • 用51单片机做一个电子钟

        学了一个多月51了,终于整了个电子钟出来,个人感觉还是比较有趣的。
        需要注意的是我用的是普中的板子,板子类型不同,io口的功能可能会有所差异。然后我这个k1开关和k2开关是接反了的,原本k1应该是接P3^0,k2接P3^1的,结果我一测试才知道k1接到了P3^1,k2接到P3^0了,不过这不要紧,用sbit定义位变量时注意换一下就可以了。然后大概讲讲功能,用8个数码管显示目前时间和闹铃时间,然后用4个独立按键对目前时间和闹铃时间进行调整(k2是加,k3是减 ,k4是用来停止闹铃的),第一次按k1是对目前时间秒数调整,第2次按k1是对目前时间分钟数调整,第三次按k1是对目前时间小时数调整,第4次按k1是对闹铃秒数调整,第5次按k1是对闹铃时间分钟数调整,第6次按k1是对闹铃秒数调整,第7次按k1是调整完毕,进去非调整状态即实时显示目前时间(不过有点差异,时间走的快了一点)。主要用到了数码管动态显示,独立按键,定时器中断这些。

    代码如下:
    #include<reg52.h>
    typedef unsigned int u16;
    typedef unsigned char u8;
    sbit led=P2^0;
    sbit lsa=P2^2;
    sbit lsb=P2^3;
    sbit lsc=P2^4;
    sbit beep=P1^5;
    sbit k1=P3^1;
    sbit k2=P3^0;
    sbit k3=P3^2;
    sbit k4=P3^3;
    sbit dian=P0^7;
    
    u8 keyvalue,alarmexist=0;
    u8 smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x00};//段选码,分别对应0到无
    u16 cnt=0,i=0,j=0,flag=0,time[]={0,0,0,0,0,0,0,0};//只用数码管0,1 3,4 6,7
    u16 alarm[]={0,0,0,0,0,0,1,0};
    u16*p;
    
    
    void delay(u16 mmp);
    void t0andt1init();
    void addproct(int x);						    
    void addproca(int x);
    void reduceproct(int x);
    void reduceproca(int x);
    void keyscan();
    void jia();
    void jian();
    
    void main()
    {
      	led=0;
        t0andt1init();
    	P0=0x00;
    	while(1)
    	{   
    	    
    		if(time[0]==alarm[0]&&time[1]==alarm[1]&&time[3]==alarm[3]&&time[4]==alarm[4]&&time[6]==alarm[6]&&time[7]==alarm[7])//满足条件 蜂鸣器以一定的时间间隔响,只到K4按键并松开,此时数码管任然正常显示当前时间
    		{   
    			alarmexist=0;
    			while(k4)
    			{
    				beep=~beep;
    				delay(25);
    				beep=~beep;
    				delay(25);
    			}
    		}
    		keyscan();
    	}
    }
    void delay(u16 mmp)
    {
    	while(mmp--);
    }
    void t0andt1init()
    {
    	TMOD=0x11;
    	TH0=0xfc;
    	TL0=0x67;//赋定时器初始值,定时1ms
    	TH1=0xfc;
    	TL1=0x67;
    	TR0=1;//T0定时器开始定时
    	EA=1;
    	ET0=1;
    	ET1=1;	
    }
    void addproct(int x)	  //对非调整状态和调整状态的加1处理(仅用于对当前时间)
    {
    	if(x==0||x==3||x==6)
    		if(time[x]==10)
    		{
    			time[x]=0;
    			time[x+1]=time[x+1]+1;
    			addproct(x+1);
    		}
       
       	if(x==1||x==4)
       		if(time[x]==6)
    		{
    			time[x]=0;
    			time[x+2]=time[x+2]+1;
    			addproct(x+2);
    		}
    	if(time[6]==4&&time[7]==2)
    		time[6]=time[7]=0;		
    }
    void addproca(int x)	  //对调整状态的加1处理(仅用于对闹钟时间)
    {
    	if(x==0||x==3||x==6)
    		if(alarm[x]==10)
    		{
    			alarm[x]=0;
    			alarm[x+1]=alarm[x+1]+1;
    			addproca(x+1);
    		}
       
       	if(x==1||x==4)
       		if(alarm[x]==6)
    		{
    			alarm[x]=0;
    			alarm[x+2]=alarm[x+2]+1;
    			addproca(x+2);
    		}
    	if(alarm[6]==4&&alarm[7]==2)
    		alarm[6]=alarm[7]=0;		
    }
    void reduceproct(int x) // 对调整状态的减1处理(仅用于对当前时间)
    {
    	if(time[0]==0&&time[1]==0&&time[3]==0&&time[4]==0&&time[6]==0&&time[7]==0)
    	{
    		time[0]=time[3]=9;
    		time[1]=time[4]=5;
    		time[6]=3;
    		time[7]=2;
    		return ;
    	}
    	if(x==0||x==3||x==6)
    	{
    		if(time[x]>=1)
    			time[x]=time[x]-1;
    		else
    		{   
    			if(time[7]==0&&x==6)
    			{
    				time[6]=3;
    				time[7]=2;
    			}
    			else
    			{
    				time[x]=9;
    				reduceproct(x+1);	
    			}
    		}
    		
    	}
    	else
    	{
    		if(time[x]>=1)
    			time[x]=time[x]-1;
    		else
    		{
    			time[x]=5;
    			if(x!=7)
    				reduceproct(x+2);
    			else
    				time[x]=1;
    		}
    	}
    	
    }
    void reduceproca(int x) // 对调整状态的减1处理(仅用于对闹钟时间)
    {
    	if(alarm[0]==0&&alarm[1]==0&&alarm[3]==0&&alarm[4]==0&&alarm[6]==0&&alarm[7]==0)
    	{
    		alarm[0]=alarm[3]=9;
    		alarm[1]=alarm[4]=5;
    		alarm[6]=3;
    		alarm[7]=2;
    		return ;
    	}
    	if(x==0||x==3||x==6)
    	{
    		if(alarm[x]>=1)
    			alarm[x]=alarm[x]-1;
    		else
    		{   
    			if(alarm[7]==0&&x==6)
    			{
    				alarm[6]=3;
    				alarm[7]=2;
    			}
    			else
    			{
    				alarm[x]=9;
    				reduceproca(x+1);	
    			}
    		}
    		
    	}
    	else
    	{
    		if(alarm[x]>=1)
    			alarm[x]=alarm[x]-1;
    		else
    		{
    			alarm[x]=5;
    			if(x!=7)
    				reduceproca(x+2);
    			else
    				alarm[x]=1;
    		}
    	}
    	
    }
    void keyscan()
    {   
    	flag=0;
    	keyvalue=0;
        if(k1==0)
    	{   
    	    TR0=0;//不在显示当前时间
    		TR1=1;
    	    delay(1000);
    		if(k1==0)
    		{   
    			while(!k1) ;
    			delay(1000);
    			led=~led;
    		    keyvalue++;
    		}
    		else
    			return ;
    		
    		while(keyvalue!=7)
    		{
    			if(k1==0)
    			{   
    			    delay(1000);
    				if(k1==0)
    				{
    					while(!k1) ;
    					led=~led;
    		            keyvalue++;
    					if(keyvalue==4)
    						flag=1;
    				} 
    				
    			}	
    			if(k2==0)
    			{
    				delay(1000);
    				if(k2==0)
    				{
    					while(!k2) ;
    				 	led=~led;
    					jia();
    				}
    			}
    			if(k3==0)
    			{
    				delay(1000);
    				if(k3==0)
    				{
    					while(!k3) ;
    				    led=~led;
    					jian();
    				}
    			}	
    		}
    		TR0=1;
    		TR1=0;
    		if(((alarm[6]+alarm[7]*10)*60+alarm[3]+alarm[4]*10)>((time[6]+time[7]*10)*60+time[3]+time[4]*10))//判断闹钟时间是否大于当前时间,
    			alarmexist=1;
    		else
    			alarmexist=0;
    		
    		
    	}
    }			
    void jia()
    {
    	switch(keyvalue)
    	{
    		case 1:time[0]=time[0]+1;addproct(0);break;
    		case 2:time[3]=time[3]+1;addproct(3);break;
    		case 3:time[6]=time[6]+1;addproct(6);break;
    		case 4:alarm[0]=alarm[0]+1;addproca(0);break;
    		case 5:alarm[3]=alarm[3]+1;addproca(3);break;
    		case 6:alarm[6]=alarm[6]+1;addproca(6);break;
    		
    
    	}
    }
    void jian()
    {
    	switch(keyvalue)
    	{
    		case 1:reduceproct(0);break;
    		case 2:reduceproct(3);break;
    		case 3:reduceproct(6);break;
    		case 4:reduceproca(0);break;
    		case 5:reduceproca(3);break;
    		case 6:reduceproca(6);break;
    		
    
    	}
    	
    }
    void Timer0() interrupt 1//非调整时,执行的中断服务程序
    {
    	TH0=0xfc;
    	TL0=0x67;//赋定时器初始值,定时1ms
    	cnt++;
    	if(1000==cnt)
    	{   
    		cnt=0;
    		time[0]=time[0]+1;
    		addproct(0);
    	}
    	P0=0X00;
    	switch(i)
    	{	
    	    case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[time[0]];dian=(alarmexist==1)?1:0;i++;break;
    		case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[time[1]];i++;i++;break;
    		case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[time[3]];i++;break;
    		case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[time[4]];i++;i++;break;
    		case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[time[6]];i++;break;
    		case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[time[7]];i=0;break;
    	}
    }
    void Timer1() interrupt 3	//调整时,执行的中断服务程序  ,flag=0显示正在调整的time,为1显示正在调整的alarm
    {
        
    	TH1=0xfc;
    	TL1=0x67;//赋定时器初始值,定时1ms
        if(flag==0)
    		p=time;
    	else
    		p=alarm;
    	P0=0X00;
    	switch(j)
    	{	
    	    case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[p[0]];j++;break;
    		case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[p[1]];j++;j++;break;
    		case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[p[3]];j++;break;
    		case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[p[4]];j++;j++;break;
    		case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[p[6]];j++;break;
    		case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[p[7]];j=0;break;
    	}
    }
    

  • 相关阅读:
    由AbstractQueuedSynchronizer和ReentrantLock来看模版方法模式
    Java并发编程-CAS
    Java并发编程-volatile
    Java并发编程-synchronized
    学习几个协议
    邻接矩阵存储简单路径(1070)
    输出利用先序遍历创建的二叉树的层次遍历序列(0980)
    中缀表达式转换为后缀表达式(1042)
    特定字符序列的判断(1028)
    舞伴问题(1027)
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755113.html
Copyright © 2011-2022 走看看