单片机自制时钟(年月日星期时分秒显示、按键校准)

单片机自制时钟(可实现年月日星期时分秒显示、按键校准)

单片机自制时钟

/*RS->p1.0;RW->p1.1;EN->p2.5;A->VCC;K->GND*/
/*K1->P3.4;K2->p3.5;K3->p3.6			  */
/*晶振11.0592M							  */
/*Edited by Feng						  */
/*2021/8/8								  */
/*功能:可显示年、月、日、时分秒、星期	  */
#include<reg52.h>
#include<intrins.h>
sbit EN = P2^5;
sbit RS = P1^0;
sbit RW = P1^1;
sbit SET_TIME_BIT_KEY = P3^4;
sbit INC_BIT_NUM_KEY = P3^5;
sbit END_CHANGE_TIME = P3^6;
#define DataPort P0
#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

bit ending;
int year;
unsigned char count,second,minute,hour,date,month,week,display_time[14];
unsigned char character[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
unsigned char double_dot[8]={0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00};
unsigned char week_group[7][3]={{'S','u','n'},{'M','o','n'},{'T','u','e'},{'W','e','d'},{'T','h','u'},{'F','r','i'},{'S','a','t'}};
unsigned char days_num_this_month[12]={31,28,31,30,31,30,31,31,30,31,30,31};

/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
	 DelayUs2x(245);
 }
}
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
 while(LCD_Check_Busy()); //忙则等待
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
 while(LCD_Check_Busy()); //忙则等待
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
 if (y == 0) 
 	{     
 	LCD_Write_Com(0x80 + x);     
 	}    
 else 
 	{     
 	LCD_Write_Com(0xC0 + x);     
 	}        
 LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_Init(void) 
 {
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }

void TIMER0init(void)
{
	TMOD = 0x01;
    TH0 = 0x4C;
    TL0 = 0x00;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void TIMER0process(void)   interrupt 1 
{
	void time_transfer(void);
	TH0=0x4C;
	TL0=0x00;
	count--;
	time_transfer();
}

void time_transfer(void)
{
	if(count==0)
	{
	 	count=20;
		second++;
	}
	if(second==60)
	{
	 	second=0;
		minute++;
	}
	if(minute==60)
	{
		minute=0;
		hour++;
	}
	if(hour==24)
	{
		hour=0;
		date++;
		week++;
	}
	if(date==1+days_num_this_month[month-1])
	{
		date=1;
		month++;	
	}
	if(week==7)
	{
		week=0;
	}
	if(month==13)
	{
		month=1;
		year++;
		if(year%4==0)
			days_num_this_month[1]=29;
		else
			days_num_this_month[1]=28;
	}
	display_time[0]=year/1000;
	display_time[1]=(year%1000)/100;
	display_time[2]=((year%1000)%100)/10;
	display_time[3]=(((year%1000)%100)%10);

	display_time[4]=month/10;
	display_time[5]=month%10;

	display_time[6]=date/10;
	display_time[7]=date%10;

	display_time[8]=hour/10;
	display_time[9]=hour%10;

	display_time[10]=minute/10;
	display_time[11]=minute%10;

	display_time[12]=second/10;
	display_time[13]=second%10;
}

void set_init_time(void)
{
	year=2021;
	month=8;
	date=8;
	hour=12;
	minute=0;
	second=0;
	week=0;
	
	if(year%4==0)
	{
		days_num_this_month[1]=29;
	}
	display_time[0]=year/1000;
	display_time[1]=(year%1000)/100;
	display_time[2]=((year%1000)%100)/10;
	display_time[3]=(((year%1000)%100)%10);

	display_time[4]=month/10;
	display_time[5]=month%10;

	display_time[6]=date/10;
	display_time[7]=date%10;

	display_time[8]=hour/10;
	display_time[9]=hour%10;

	display_time[10]=minute/10;
	display_time[11]=minute%10;

	display_time[12]=second/10;
	display_time[13]=second%10;	
}

void LCD_display(void)
{
	LCD_Write_Char(1,0,character[display_time[0]]);
	LCD_Write_Char(2,0,character[display_time[1]]);
	LCD_Write_Char(3,0,character[display_time[2]]);
	LCD_Write_Char(4,0,character[display_time[3]]);

	LCD_Write_Char(6,0,character[display_time[4]]);
	LCD_Write_Char(7,0,character[display_time[5]]);

	LCD_Write_Char(9,0,character[display_time[6]]);
	LCD_Write_Char(10,0,character[display_time[7]]);

	LCD_Write_Char(4,1,character[display_time[8]]);
	LCD_Write_Char(5,1,character[display_time[9]]);
	LCD_Write_Char(7,1,character[display_time[10]]);
	LCD_Write_Char(8,1,character[display_time[11]]);
	LCD_Write_Char(10,1,character[display_time[12]]);
	LCD_Write_Char(11,1,character[display_time[13]]);
	
	LCD_Write_Char(12,0,week_group[week][0]);
	LCD_Write_Char(13,0,week_group[week][1]);
	LCD_Write_Char(14,0,week_group[week][2]);	
}

void write_diy_character(void)
{
	  unsigned char index;
	  LCD_Write_Com(0x40);
	  for(index=0;index<8;index++)
	  {
	  	LCD_Write_Data(double_dot[index]);
	  }
	  
      LCD_Write_Com(0xC6);  //显示地址
      LCD_Write_Data(0x00); //向DDRAM写入
	  LCD_Write_Com(0xC9);  //显示地址
      LCD_Write_Data(0x00); //向DDRAM写入

	  LCD_Write_Char(5,0,0xB0);
	  LCD_Write_Char(8,0,0xB0);
}

void delay500ms(void)   //误差 -0.000000000068us
{
    unsigned char a,b,c;
    for(c=98;c>0;c--)
        for(b=127;b>0;b--)
            for(a=17;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}

void dislpay_bit_flicker(unsigned bit_num)
{
	unsigned char corresponding_line,corresponding_row=0;
	switch(bit_num)
	{
		case 0:corresponding_line=1;break;
		case 1:corresponding_line=2;break;
		case 2:corresponding_line=3;break;
		case 3:corresponding_line=4;break;
		case 4:corresponding_line=6;break;
		case 5:corresponding_line=7;break;
		case 6:corresponding_line=9;break;
		case 7:corresponding_line=10;break;
		case 8:corresponding_line=4;break;
		case 9:corresponding_line=5;break;
		case 10:corresponding_line=7;break;
		case 11:corresponding_line=8;break;
		case 12:corresponding_line=10;break;
		case 13:corresponding_line=11;
	}
	if(bit_num>=8)
		corresponding_row=1;

	while(SET_TIME_BIT_KEY)
	{
		LCD_Write_Char(corresponding_line,corresponding_row,character[display_time[bit_num]]);
		delay500ms();
		LCD_Write_Char(corresponding_line,corresponding_row,0x5F);
		delay500ms();
		if(INC_BIT_NUM_KEY==0)
		{
			display_time[bit_num]++;
			if(display_time[bit_num]>9)
				display_time[bit_num]=0;
		}
		if(END_CHANGE_TIME==0)
			{
				ending=1;break;
			}			
	}
	LCD_Write_Char(corresponding_line,corresponding_row,character[display_time[bit_num]]);
}

void work_from_new_time(void)
{
	unsigned char old_date=date;
	year=display_time[0]*1000+display_time[1]*100+display_time[2]*10+display_time[3];
	month=display_time[4]*10+display_time[5];
	date=display_time[6]*10+display_time[7];
	week=(week+date-old_date)%7;
	hour=display_time[8]*10+display_time[9];
	minute=display_time[10]*10+display_time[11];
	second=display_time[12]*10+display_time[13];	
}

void change_time(void)
{
	unsigned char key_press_count=0;
	while((key_press_count<14)&&(ending==0))
	{
		dislpay_bit_flicker(key_press_count);
		delay500ms();
		delay500ms();
		key_press_count++;	
	}

	work_from_new_time();
}


void main(void)
{
	LCD_Init();//初始化LCD
	write_diy_character();
	set_init_time();//设置初始时间
	LCD_display();
	change_time();

	TIMER0init();//初始化计时器0
	while(1)
	{	
		LCD_display();
	}
}
  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值