lcd_time.c

来自「实现MSC-51系统的液晶时间显示的源程序,请大家学习!」· C语言 代码 · 共 388 行

C
388
字号
/**************************************
			LCD time    
		
**************************************/
#include<reg51.h>
#include<intrins.h>
#include"General.h"


#define TT 1				//条件编译标志,TT=0时方便调试

/* 1602控制引脚定义 */
sfr  lcd_data = 0xA0;		//P2为数据口
sbit lcd_rs   = P3^0;		//寄存器选择位
sbit lcd_rw   = P3^1;		//LCD读写选择位
sbit lcd_en   = P3^2;		//LCD操作使能位

/* 外键控制定义 */
sbit key_con = P1^0;		//时间设置键
sbit key_inc = P1^1;		//加1键
sbit key_dec = P1^2;		//减1键

/* 全局变量定义 */
bit flash_flag=0;				//闪烁标志
uchar time_ram[8]={0,0,':',0,0,':',0,0};	//时间显示缓冲区,存放拆分时间值
uchar week_ram[3];			//3位星期显示缓冲区
uchar time[4];				//时,分,秒,半秒
uchar weekday=0;			//星期变量
uchar con_value;			//设置键的状态值 0:非设置,1:设置分钟,2:设置时钟
uchar code time_table[] = "0123456789:";	//字形库
uchar code week_table[][4]={ "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
uchar code mover[] = "Magic 418";
uchar code table[][17] ={ "                ",
					 	  "Welcome To UFO's",
						  "   Magic World  ",
						  "This is a clock ",
						  "that can be set.",
						  "Left -> increase",
						  "Right-> decrease"
						};	
uchar code heart[] ={ 0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f, 	//心形图案
                 	  0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
                 	  0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
                 	  0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
                 	  0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
                 	  0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
                 	  0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
                 	  0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00
					};


/* 宏定义 */
#define BUSY 0x80				//LCD忙标志
#define LCDRS_0 lcd_rs=0		//RS: 0命令寄存器,1数据寄存器
#define LCDRW_0 lcd_rw=0		//RW:0写入,1读出
#define LCDEN_0 lcd_en=0		//EN:由高到低,则LCD执行命令
#define LCDRS_1 lcd_rs=1
#define LCDRW_1 lcd_rw=1
#define LCDEN_1 lcd_en=1
#define DELAY  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

/***************************************************************************
***************************************************************************/
/* LCD写命令函数 */
void WriteCommand(uchar com)		
{
 LCDRS_0;	
 DELAY;
 LCDRW_0;
 DELAY;
 lcd_data=com;
 DELAY;
 LCDEN_1;
 DELAY;
 LCDEN_0;
 DELAY;
}

/* LCD写数据函数 */
void WriteData(uchar dat)			
{
 LCDRS_1;	
 DELAY;
 LCDRW_0;
 DELAY;
 lcd_data=dat;
 DELAY;
 LCDEN_1;
 DELAY;
 LCDEN_0;
 DELAY;
}

/* LCD定位函数 */
void LocateXY(uchar x, uchar y)		//X为列序(0~15),Y为行序(0~1)
{
 if(y)
	x+=0xC0;
 else
	x+=0x80;
 WriteCommand(x);
}

/* 显示字符函数 */
void WriteChar(uchar x,uchar y,uchar dat)	//X Y为显示坐标	
{
 LocateXY(x,y);
 WriteData(dat);
}

/* 显示字符串函数 */
void WriteStr(uchar x,uchar y,uchar *str)
{
 uchar i,len=0;
 while(str[len]!='\0')
	{len++;}			//求取字符串长度
 for(i=0;i<len;i++)
 {
 	WriteChar(x++,y,str[i]);
	if(x>15)
	{
		x=0;
		y=1;
	}
 }
}
 

/* LCD初始化 */
void LcdInit(void)	
{
 uchar i,j,k=0,temp=0x40;
 WriteCommand(0x38);	//设置8位格式:2行,5x7
 WriteCommand(0x01);	//清除DDRAM
 delay50ms(1);
 WriteCommand(0x06);	//设定输入方式:增量字符不动
 WriteCommand(0x0C);	//整体显示,关光标,不闪烁
#if TT
 for(i=8;i>0;i--)		//将心形写入CGRAM
 {
 	for(j=8;j>0;j--)
	{
	 	WriteCommand(temp++);
		WriteData(heart[k++]);
	}
 }

 WriteStr(0,0,table[1]);	//显示前言
 WriteStr(0,1,table[2]);
 delay50ms(40);
 WriteStr(0,0,table[3]);
 WriteStr(0,1,table[4]);
 delay50ms(40);
 WriteStr(0,0,table[5]);
 WriteStr(0,1,table[6]);
 delay50ms(40);

 for(j=0;j<13;j++)		//心形自左至右移动一轮
 {
	WriteStr(0,0,table[0]);	//清第一行
	WriteStr(0,1,table[0]); //清第二行
	for(i=0;i<4;i++)		//显示心形
	{
		WriteChar(j+i,0,i);
	 	WriteChar(j+i,1,i+4);
	}
	delay50ms(6);
 }

 WriteStr(0,0,table[0]);
 WriteStr(0,1,table[0]);
 delay50ms(10);
#endif
}

/* 时钟初始化 */
void TimerInit (void)
{
 TMOD=0x11;
 TH0=0x00;				
 TL0=0x00;
 TH1=0x3c;
 TL1=0xb0;
 TR0=1;
 IE=0x8a;
}

/* 时间值调整函数 */
void AdjustTime (void)
{
 if(time[2]>59)		//秒向分进
 {
	time[2]=0;
	time[1]++;
 }
 if(time[1]>59)	//分向时进
 {
	time[1]=0;
	time[0]++;
 }
 if(time[0]>23)
	time[0]=0;
 time_ram[0]=time[0]/10;
 time_ram[1]=time[0]%10;
 time_ram[2]=10;
 time_ram[3]=time[1]/10;
 time_ram[4]=time[1]%10;
 time_ram[5]=10;
 time_ram[6]=time[2]/10;
 time_ram[7]=time[2]%10;
}


/* 时间设定函数 */
void SetTime(uchar sel)	//sel为选择是设定时钟还是分钟
{

 if(!key_inc)
 {
 	delay1ms(10);
	while(!key_inc);
	if(sel)
		time[1]++;
	else
		time[0]++;
	AdjustTime();
 }
 if(!key_dec)
 {
 	delay1ms(10);
	while(!key_dec);
	if(sel)
	{
		time[1]--;
		if(time[1]>59)
			time[1]=59;
	}
	else
	{
		time[0]--;	
		if(time[0]>23)
			time[0]=23;
	}
	AdjustTime();
 }
}

/* 星期设定函数 */
void SetWeek (void)
{
 if(!key_inc)
 {
 	delay1ms(10);
	while(!key_inc);
	weekday++;
	if(weekday>6)
		weekday=0;
 }
 if(!key_dec)
 {
 	delay1ms(10);
	while(!key_dec);
	weekday--;
	if(weekday>6)
		weekday=6;
 }
}


/* 显示函数 */
void Display (void)
{
 uchar i,*p=time_ram;
 static uchar j;		//j为移动字符的显示位置
 if(time[3]>1)			//1秒到则显示第二行滚动字符
 {
 	time[3]=0;
	time[2]++;
	AdjustTime();
	WriteStr(0,1,table[0]);		//清第二行
	if(!con_value)
	{
		j++;
		if(j>15)
			j=0;
	}
	WriteStr(j,1,mover);
 }
 if(flash_flag)			//闪烁?
	switch(con_value)
	{
		case 1: 
				for(i=0;i<8&&i!=1;i++)
 					WriteChar(i+2,0,time_table[time_ram[i]]);
				WriteChar(3,0,0xff);
				break;
		case 2: 
				for(i=0;i<8&&i!=4;i++)
 					WriteChar(i+2,0,time_table[time_ram[i]]);
				WriteChar(6,0,0xff);
				break;
		case 3: WriteChar(14,0,0xff);
	}
 else
 {
	for(i=0;i<8;i++)		//显示时间
 		WriteChar(i+2,0,time_table[time_ram[i]]);
	WriteStr(12,0,week_table[weekday]);	//显示星期
 }
}

/* 按键检测 */
void keyscan (void)
{
LP: _nop_();
 if(!key_con)
 {	
 	delay50ms(2);
	while(!key_con);
	con_value++;
	if(con_value>3)
	{
		con_value=0;
		TR1=0;
	}
 }
 if(con_value)
 	TR1=1;
 else
 {
 	TR1=0;
	flash_flag=0;
 }
 switch(con_value)
 {
	case 1: SetTime(0); Display(); break;		//设定时钟
	case 2: SetTime(1); Display(); break;		//设定分钟
	case 3: SetWeek();	Display();  			//设定星期
 }
 if(con_value) goto LP;
}


/******************************************************************************
				主函数
******************************************************************************/
main()
{
// delay50ms(80);			//等待电源稳定
 delay50ms(20);
 LcdInit();
 TimerInit();
 while(1)
 {
	Display();
	keyscan();
 }
} 

/***********************************************************************
				中断子程序
***********************************************************************/
void T0_int (void) interrupt 1 using 1	//T0为50ms的时钟定时
{
    static uchar counter;
    TH0=0x3c;
    TL0=0xb0; 
    counter++;
    if(counter==10)		//计满0.5S
   	{
   		counter=0;
		time[3]++;		
	}
}

void T1_int (void) interrupt 3			//T1为闪烁定时
{
	static uchar counter;
    TH0=0x3c;
    TL0=0xb0;
    counter++;
    if(counter==8)		//计满0.4S
   	{
		counter=0;
		flash_flag=~flash_flag;
   	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?