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 + -
显示快捷键?