📄 my_clock.c
字号:
#define uchar unsigned char //宏定义字符型变量(无符号字符类型)
#define uint unsigned int //宏定义整型变量
#include "reg52.h" //定义89E58RD特殊功能寄存器
#include "intrins.h" //调用空操作延时函数_nop_()
sbit BELLING =P0^0; //闹钟信号引脚
sbit RS = P3^5; //数据/命令选择端引脚
sbit RW = P3^6; //读/写选择端引脚
sbit E = P3^7; //能使信号引脚
sbit ESC = P1^0; //退出键
sbit EN = P1^1; //确定键
sbit UP = P1^2; //右移键
sbit DOWN = P1^3; //左移
#define DPORT P2 //定义特殊功能寄存器端口
const uchar NoDisp=0; //无显示
const uchar NoCur=1; //有显示无光标
const uchar CurNoFlash=2; //有光标但不闪烁
const uchar CurFlash=3; //有光标且闪烁
void LcdPos(uchar,uchar); //确定光标位置
void LcdWd(uchar); //写字符
void LcdWc(uchar); //送控制字(检测忙信号)
void LcdWcn(uchar ); //送控制字子程序(不检测忙信号)
void mDelay(uchar ); //延时,毫秒数由j决定
void WaitIdle(); //正常读写操作之前检测LCD控制器状态
uchar getkey();
//在指定的行与列显示指定的字符,xpos:行,ypos:列,c:待显示字符
void WriteChar(uchar c,uchar xPos,uchar yPos) //定义WriteChar函数
{ LcdPos(xPos,yPos);
LcdWd(c);
}
void WriteString(uchar *s,uchar xPos,uchar yPos) //定义WriteString函数
{ uchar i;
if(*s==0) //遇到字符串结束
return;
for(i=0;;i++)
{
if(*(s+i)==0)
break;
WriteChar(*(s+i),xPos,yPos);
xPos++;
if(xPos>=15) //如果XPOS中的值未到15(可显示的最多位)
break;
}
}
void SetCur(uchar Para) //定义光标函数
{ mDelay(2); //延时
switch(Para)
{ case 0:
{ LcdWc(0x08); //关显示
break;
}
case 1:
{ LcdWc(0x0c); //开显示但无光标
break;
}
case 2:
{ LcdWc(0x0e); //开显示有光标但不闪烁
break;
}
case 3:
{ LcdWc(0x0f); //开显示有光标且闪烁
break;
}
default:
break;
}
}
void ClrLcd() //定义清屏函数
{ LcdWc(0x01);
}
// 正常读写操作之前检测LCD控制器状态
void WaitIdle() //测试LCD忙碌状态标志函数
{ uchar tmp;
DPORT=0xff; //检测LCD忙标志,若忙则输出为1,否则为0
RS=0;
RW=1;
E=1;
_nop_();
for(;;)
{
E=1; //忙时则等待
_nop_();
_nop_();
tmp=DPORT;
tmp&=0x80;
if( tmp==0)
break;
E=0;
}
E=0; //E=0,执行语句
}
void LcdWd(uchar c) //写字符子程序
{ WaitIdle();
RS=1;
RW=0;
DPORT=c; //将待写数据送到数据端口
E=1; //忙时则等待
_nop_();
_nop_();
E=0;
}
void LcdWc(uchar c) //送控制字子程序(检测忙信号?
{ WaitIdle(); //调用WaitIdle函数
LcdWcn(c); //调用LcdWcn函数
}
void LcdWcn(uchar c) //送控制字子程序(不检测忙信号)
{ RS=0;
RW=0;
DPORT=c; //将待写数据送到数据端口
E=1; //忙时则等待
_nop_();
_nop_();
E=0;
}
void LcdPos(uchar xPos,uchar yPos) //设置第(xPos,yPos)个字符的DDRAM地址
{ unsigned char tmp;
xPos&=0x0f; //x位置范围是0~15,因为显示15列
yPos&=0x01; //y位置范围是0~1,因为显示2行
if(yPos==0) //显示第一行
tmp=xPos;
else
tmp=xPos+0x40; //显示第二行
tmp|=0x80;
LcdWc(tmp);
}
void RstLcd() //复位LCD控制器
{ mDelay(15); //如果使用12M或以下晶振,此数值不必改,如用24M晶振,须用30
LcdWc(0x38); //显示模式设置
LcdWc(0x08); //显示关闭
LcdWc(0x01); //显示清屏
LcdWc(0x06); //显示光标移动位置
LcdWc(0x0c); //显示开及光标设置
}
void mDelay(uchar j) //延时,毫秒数由j决定
{ uint i=0;
for(;j>0;j--)
{ for(i=0;i<124;i++)
{;}
}
}
//============================
struct strtime //时、分、秒声明函数
{
uchar hour;
uchar min;
uchar sec;
}time;
struct strdate //年、月、日声明函数
{
uchar year;
uchar month;
uchar day;
}date;
struct strbell //(闹钟)时分声明函数
{
uchar hour;
uchar min;
};
struct strbell idata belltime[34]; //设置响铃次数,可以响铃34次
bit bellfla;
uchar week,reflash;
uchar buf[8];
code uchar monthday[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; //月标志
uchar code weekday[7][4]={{"SUN"},{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"}}; //星期标志
uchar code weekmon[13]={0,0,3,3,6,1,4,6,2,5,0,3,5};
uchar code ID[]={"3105009720"}; //学号标志
uchar code menu[4][16]={ //菜单设置
{"1. SET TIME"},
{"2. SET DATE"},
{"3. SET ALARM"},
{"4. CANCEL ALARM"},
};
save() //保存语句
{
ClrLcd(); //清屏幕
WriteString("Saved !",4,0); //写入"Saved !"
WriteString("Any Key Esc..",2,1); //写入"Any Key Esc.."
getkey();
}
menudis(uchar num) //执行菜单命令
{
ClrLcd();
WriteString("Select Menu",3,0);
WriteString(&menu[num][0],0,1);
}
//======================================
settime() //设置时间
{
uchar key,cru=0,max=2,xPOS=3;
buf[6]='s'-48;
ClrLcd();
LcdPos(4,0);
WriteString("Input Time",4,0);
buf[0]=time.hour/10; //设置时高位
buf[1]=time.hour%10; //设置时底位
buf[2]=time.min/10; //设置分高位
buf[3]=time.min%10; //设置分底位
buf[4]=time.sec/10; //设置秒高位
buf[5]=time.sec%10; //设置秒底位
//=============显示位置
LcdPos(3,1);
LcdWd(buf[0]+48);
LcdPos(4,1);
LcdWd(buf[1]+48);
LcdPos(5,1);
LcdWd(':');
LcdWd(buf[2]+48);
LcdWd(buf[3]+48);
LcdPos(8,1);
LcdWd(':');
LcdWd(buf[4]+48);
LcdWd(buf[5]+48);
LcdPos(3,1);
SetCur(CurNoFlash);
while(key=getkey()) //时、分、秒加一
{
switch(key)
{
case 0: {;};break;
case 1:
{
if(cru==6)
{
time.hour=buf[0]*10+buf[1];
time.min=buf[2]*10+buf[3];
time.sec=buf[4]*10+buf[5];
save();
ClrLcd();
SetCur(NoCur);
return;
}
if((++buf[cru])>max)
{
buf[cru]=0;
}
LcdPos(xPOS,1);
LcdWd(buf[cru]+48);
LcdPos(xPOS,1);
}
break;
case 2: {
if(++cru>6) cru=0;
switch(cru)
{
case 0: {max=2;xPOS=3;};break;
case 1: {
xPOS=4;
if(buf[0]==2) max=4;
else max=9;
};break;
case 2: {max=5;xPOS=6;};break;
case 3: {max=9;xPOS=7;};break;
case 4: {max=5;xPOS=9;};break;
case 5: {max=9;xPOS=10;};break;
case 6: {max=9;xPOS=11;};break;
}
LcdPos(xPOS,1);
LcdWd(buf[cru]+48);
//xPOS--;
LcdPos(xPOS,1);
}break;
case 3: {
if(cru==0)
{cru=6;xPOS=11;}
else cru--;
switch(cru)
{
case 0: {max=2;xPOS=3;};break;
case 1: {
xPOS=4;
if(buf[0]==2) max=4;
else max=9;
};break;
case 2: {max=5;xPOS=6;};break;
case 3: {max=9;xPOS=7;};break;
case 4: {max=5;xPOS=9;};break;
case 5: {max=9;xPOS=10;};break;
}
LcdPos(xPOS,1);
LcdWd(buf[cru]+48);
//xPOS--;
LcdPos(xPOS,1);
}
break;
}
}
ClrLcd();
SetCur(NoCur);
}
//==========BELL==========设置闹钟
bellreflash(uchar num)
{
buf[0]=num/10;
buf[1]=num%10;
buf[2]=(belltime[num].hour&0x7f)/10; //设置时高位
buf[3]=(belltime[num].hour&0x7f)%10; //设置时傅孜?buf[4]=belltime[num].min/10; //设置分高位
buf[5]=belltime[num].min%10; //设置分底位
if(belltime[num].hour>100) buf[6]=1;
else buf[6]=0;
buf[7]='s'-48;
LcdPos(2,1); //显示位置
LcdWd(buf[0]+48);
LcdWd(buf[1]+48);
LcdWd('#');
LcdWd(buf[2]+48);
LcdWd(buf[3]+48);
LcdWd(':');
LcdWd(buf[4]+48);
LcdWd(buf[5]+48);
LcdWd(' ');
LcdWd(buf[6]+48);
}
//===========BELL=============
setbell()
{
uchar key,num=0,cru,max=3,xp=2;
ClrLcd();
SetCur(CurNoFlash);
WriteString("Set Alamr Time",1,0); //写入响铃时间
bellreflash(num);
LcdPos(2,1);
while(key=getkey())
{
if(key==1)
{
if(cru==7)
{
if(num<34) //响铃次数
{
belltime[num].hour=buf[2]*10+buf[3];
belltime[num].min=buf[4]*10+buf[5];
if(buf[6]) belltime[num].hour|=0x80; //响铃时间到
ClrLcd();
WriteString("Bell ",0,0);
LcdWd(buf[0]+48);
LcdWd(buf[1]+48);
WriteString(" Saved!",9,0);
WriteString("Esc ? Esc key...",0,1);
buf[0]=num/10;
buf[1]=num%10;
if(getkey()==0) //清屏幕,直接退出
{
ClrLcd();
SetCur(NoCur);
return;
}
else //清屏幕,重设响铃时间
{
ClrLcd();
WriteString("Set Alamr Time",1,0);
if(++num>33) num=0;
bellreflash(num);
cru=0;
xp=2;
max=3;
}
}
}
else
{
if(++buf[cru]>max)
{
buf[cru]=0; //可以确定闹钟时间
}
if(cru==0 || cru==1)
{
num=buf[0]*10+buf[1];
bellreflash(num);
}
else
LcdWd(buf[cru]+48);
}
}
else if(key==2)
{
if((++cru)>7)
cru=0;
switch (cru)
{
case 0:{max=3;xp=2;} break;
case 1:{max=9;xp=3;if(buf[0]==3) max=2;} break;
case 2:{max=2;xp=5;} break;
case 3:{max=9;xp=6;if(buf[2]==2) max=3;} break;
case 4:{max=5;xp=8;} break;
case 5:{max=9;xp=9;} break;
case 6:{max=1;xp=11;} break;
case 7:{xp=12;LcdPos(xp,1);LcdWd('s');} break;
}
}
else if(key==3)
{
if(cru==0) cru=7;
else cru--;
switch (cru)
{
case 0:{max=3;xp=2;} break;
case 1:{max=9;xp=3;} break;
case 2:{max=5;xp=5;} break;
case 3:{max=9;xp=6;} break;
case 4:{max=5;xp=8;} break;
case 5:{max=9;xp=9;} break;
case 6:{max=1;xp=11;} break;
case 7:{xp=12; LcdPos(xp,1);LcdWd('s');} break;
}
}
else break;
LcdPos(xp,1);
}
SetCur(NoCur);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -