单片机——时钟调节

 软件(Keil uVision4 + Proteus 8 Professional + stc-isp-15xx-v6.85p)

图标

 

 

 

 

 

 

“万年历”设计任务书

功能简述

数码管以3秒的间隔交替显示日期和时间,并且时间可以修改。

系统硬件部分主要由单片机最小系统、数码管显示、按键模块、LED显示等模块组成。系统组成框图如图 1 所示:

图 1 系统组成框图

设计任务及要求

一、显示界面

1. 当前日期界面

把考试当日的年、月、日数据显示在数码管上,当前日期(以2023年1月12日为例)界面如图 2 所示

图 2 日期显示图

2

0

2

3

0

1

1

2

2. 当前时间显示界面

把从当前时间的时、分、秒数据显示在数码管上,当前日期(以9时31分30秒为例)界面如图 3 所示:

图 2 时间显示图

0

9

-

3

1

-

3

0

3、设置时间

设置界面分小时设置界面和分钟设置界面,小时设置界面如图4所示,分钟设置界面如图5所示。

图 3 修改小时图

S

1

0

9

图 4 小时设置界面

图 3 修改分钟图

S

2

3

1

二、整分LED显示模块

当时间达到整分时,8个LED灯以0.2秒的间隔时间向左流水2次。

三、按键设置模块

按键模块采用矩阵按键,系统初始时,当前日期、时间每隔3秒轮流显示,当系统显示当前温度界面时,按S2、S3无效,当第1次按下S1时,系统显示设置小时界面,此时按S2,小时增1,按S3小时减1,当第2次按下S1时,系统显示设置分钟界面,此时按S2,分钟增1,按S3分钟减1,当第3次按下S1时,系统回到当前日期、时间显示界面。按键流程如图6所示。

 

 led.c

#include<reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "SEG.h"
#include "key.h"
/*
1.数码管显示
  display_dat,	seg_fresh  P0:s1-s8 P2:a-e
2.字符解析显示码值
  char_to_code,display_code,
3.定时器
  初始化,函数声明 ,写中断函数
4.3s交替显示日期、时间
	变量计数,
5.流水灯
  变量计数,P1:灯,x=0xfe,0.2s ,fun_led() ,调用
6.按键
	P3,key_scan(),	flag_mode, key_old	, key_new
*/
//sbit LED1=0X90;

//变量区
bit change_mode=0;//日期、时间切换
bit is_min=0;//流水标志
bit is_200ms=0;
char led_count=0;//0-16
char led_x=0xfe;
//key 变量
unsigned char flag_mode=0,key_new,key_old=0;

//函数声明
void TR0_init();
void seg_pro();
void fun_led();
void key_pro();

unsigned char display_dat[8]={0XC6,0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82};	 //c0-6
unsigned char display_show[10] ;
char hour=12,minute=59,second=57,month=4,day=18;
int year=2023;

void main()
{
   	unsigned int i; 
    unsigned char key_new,key_old=0;
    sprintf(display_show,"%02d-%02d-%02d",(int)hour,(int)minute,(int)second);
    char_to_code(display_show,display_dat);
	SEG_Fresh(display_dat);	

	TR0_init();
    while(1)
	{
	   key_pro(); //按键
	   seg_pro(); //数码管
	   fun_led(); //led


	}
}

void TR0_init()
{
	TMOD=0X01;
	TH0=0X3C; TL0=0XB0; TR0=1;
	EA=1;ET0=1;
}

void seg_pro()
{
	if(flag_mode==0)
	{
		if(!change_mode)
		{
			sprintf(display_show,"%02d-%02d-%02d",(int)hour,(int)minute,(int)second);
	    	char_to_code(display_show,display_dat);
			SEG_Fresh(display_dat);
		}else
		{
			sprintf(display_show,"%4d%02d%02d",(int)year,(int)month,(int)day);
	    	char_to_code(display_show,display_dat);
			SEG_Fresh(display_dat);
		}
	}else if(flag_mode==1)
	{										 
			sprintf(display_show,"E1    %02d",(int)hour);
	    	char_to_code(display_show,display_dat);
			SEG_Fresh(display_dat);
	}else if(flag_mode==2)
	{
			sprintf(display_show,"E2    %02d",(int)minute);
	    	char_to_code(display_show,display_dat);
			SEG_Fresh(display_dat);
	}
	
}
void fun_led()
{
	 	if(is_200ms) //0.2s
		{
			is_200ms=0;
			if(is_min) //整分
	 		{
			    P1=led_x;
				led_x=_crol_(led_x,1);
				if(++led_count==17)
				{
					led_count=0;
					P1=0xff;
					is_min=0;	
				}
	 		}
			
		}
		 

}
void key_pro()
{
	key_new=key_can();
	switch(key_new ^ key_old & key_new)
	{
		 case 1:
		 	if(++flag_mode==3) 
				flag_mode=0; 
			break;
		case 2:
		 	if(flag_mode==1) 
			{
				if(++hour==24) hour=0;
			}else if(flag_mode==2) 
			{
				if(++minute==60) minute=0;
			}
			break;
		case 3:
		 	if(flag_mode==1) 
			{
				if(--hour==-1) hour=23;
			}else if(flag_mode==2) 
			{
				if(--minute==-1) minute=59;
			}
			break;
	}

	key_old=key_new;
}
void  timer0(  )  interrupt 1
{
	static unsigned char i=0,j=0,times=0;
	TH0=0X3C; TL0=0XB0;
	

	if(++times==20)	   //1s
	{
	     times=0;
		 if(++second==60)
		 {
		 	second=0;
			//is_min
			if(++minute==60)
			{
				minute=0;
				if(++hour==24)
				{
					hour=0;
				}	
			}

		 }
	}
	if(++i==60)
	{
		i=0;//3s
		change_mode=~change_mode;
	}
	if(second==0)//整分
	{
		is_min=1;
	}
    if(++j==4)	 //是0.2s
	{
	 	 j=0;
	  	 is_200ms=1;
	 }

}

 seg.c(数码管刷新函数+字符转数码管显示码函数)

#include<reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "SEG.h"

unsigned char code display_code[]={'E',0x86,'C',0XC6,'0',0xC0,'1',0xF9,'2',0xA4,'3',0xB0,'4',0x99,'5',0x92,'6',0x82,'7',0xF8,'8',0x80,'9',0x90,'-',0xbf,' ',0xff};
void   SEG_Fresh(unsigned char *p)
{
	 static char i=0,x=0xfe;
	 
	 P2=0xff;
	 P0=x;
	 P2=p[i];

	 x=_crol_(x,1);
	 i++;
	 if(i==8) i=0;

}

void char_to_code(unsigned char *p,unsigned char *q)
{
	static unsigned char i,j,k;
	for(i=0,k=0;i<8;i++,k++)
	{
		for(j=0;j<14;j++)
		{
			if(p[i]==display_code[2*j])
			{
				q[k]=display_code[2*j+1];
				break;
			}
		}	
	}
  

}

 key.c(按键扫描函数)

#include<reg51.h>
#include <intrins.h>


unsigned char key_can()
{
   	static char i=0,x=0xfe;
	for(i=0;i<4;i++)
	{
		P3=x;
		if(P3!=x)
		{
			switch(P3)
			{
				case 0x7e: return 1;
				case 0x7d: return 2;
				case 0x7b: return 3;
			}
		}
		x=_crol_(x,1);		  	
	}
	

	return 0x00;
}

 2023.4.18

 

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值