1602时钟(郭天祥老师板子配套)

来源:互联网 发布:橱柜拆单软件 编辑:程序博客网 时间:2024/04/29 20:19

根据郭老师1602时钟的学习视频进行的完善,是一个可以显示年月日,时分秒星期的例子。

/*
根据郭老师视频,写的可以调节年月日星期时分秒的例子。
在郭老师的学习板中,s13键用来进行选定按键
s17用来进行加1,s21用来减一。
*/
#include<reg52.h>
#include<string.h>
#include<math.h>

#define uchar unsigned char
#define uint unsigned int


#define DATA P0  //八位并行数据接口


sbit DULA=P2^6; 
sbit WELA=P2^7;  //数码管的位选和段选关闭
sbit RS=P3^5;      
//sbit RW=P3^6;
sbit E=P3^4;
sbit RDD=P3^7;//将此置为0,则矩阵键盘变为独立按键
uchar code table1[]="2012-11-14 SUN";
uchar code table2[]="23:59:55";
uchar code week_table[]={0x53,0x55,0x4e,0x4d,0x4f,0x4e,0x54,0x55,0x45,0x57,0x45,0x44,0x54,0x48,0x55,
0x46,0x52,0x49,0x53,0x41,0x54}; //周日到周六的编码
uchar code month1[]={1,3,5,7,8,10,12};
uchar code month2[]={4,6,9,11};
uint n1;//计算table1长度
uint n2;//计算table2长度
uchar count=0;//定时1秒所用
uchar hour=23,min=59,sec=55;
int year=2012;
uchar year_l=20,year_r=12,month=11,day=14,week=0;
sbit key1=P3^1; //用来选中哪个项目进行加减
sbit key2=P3^2; //用来加1
sbit key3=P3^3; //用来减1
uchar num;
void delay(uint x)
{
uint i;
while(x--){
for(i=0;i<60;i++);
}
}
/*
函数作用:液晶写控制指令函数
输入:空
输出:空
*/
void write_ctrl(uchar ctrl)
{
//RW=0;
RS=0;
E=0;
DATA=ctrl;
delay(5);
E=1;
delay(5);
E=0;
}
/*
函数作用:液晶写数据函数
输入:空
返回值:空
*/
void write_data(uchar da)
{
// RW=0;
RS=1;
E=0;
DATA=da;
delay(5);
E=1;
delay(5);
E=0;

}
/*
函数作用:初始化。包括禁止数码管显示(锁存器控制端置低);液晶初始化设置;
液晶初始化显示设置;定时器初始化
输入:空
返回值:空
*/
void init()
{
uchar i;
DULA=0;
WELA=0;
RDD=0;
E=0;
write_ctrl(0x06);//光标移动
write_ctrl(0x0c);//不显示光标
write_ctrl(0x38);//两行,5*7


n1=strlen(table1);
n2=strlen(table2);
write_ctrl(0x80);
for(i=0;i<n1;i++){
write_data(table1[i]);
delay(1);
}
write_ctrl(0x80+0x40);
for(i=0;i<n2;i++){
write_data(table2[i]);
delay(1);
}
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;//定时50ms
EA=1;
ET0=1;
TR0=1;
}
/*
函数作用:写时分秒函数,即向指定的地址写入时、分或是秒。
输入:第一个参数add是指从哪个地址开始写,第二个参数da指要写的数据
返回值:空
*/
void write_sfm(uchar add,uchar da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_ctrl(0x80+0x40+add);//从0x80+0x40+addr这个地址开始写,即秒的十位
write_data(0x30+shi); //先写十位
write_data(0x30+ge);//再写个位
}
/*
函数作用:写年月日函数,与write_sfm不同的是写入的地址不一样
输入:第一个参数add是指从哪个地方写,第二个参数da指要写的数据
返回值:空。
*/
void write_nyr(uchar add,uchar da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_ctrl(0x80+add);//从0x80+addr这个地址开始写,即十位
write_data(0x30+shi); //先写十位
write_data(0x30+ge);//再写个位
}
/*
函数作用:扫描键盘函数,检查是否有按键按下
输入:空
返回值:空
*/
void keyscan()
{
uchar k=0;
if(key1==0){
num=(num+1)%9;
delay(5);//消抖
if(key1==0){
if(num==1){ //第一次摁,则停在秒
while(key1==0);//松手检测
TR0=0;//不再计时
write_ctrl(0x80+0x40+7);//光标移动指定位置,此处为秒的个位
write_ctrl(0x0f); //光标闪烁

}
if(num==2){//第二次,则停在分
while(key1==0);
TR0=0;
write_ctrl(0x80+0x40+4);
write_ctrl(0x0f);
}
if(num==3){//第三次,停在时
while(key1==0);
TR0=0;
write_ctrl(0x80+0x40+1);
write_ctrl(0x0f);
}
if(num==4){ //停在星期
while(key1==0);
TR0=0;
write_ctrl(0x80+0x0d);
write_ctrl(0x0f);
}
if(num==5){//停在天
while(key1==0);
TR0=0;
write_ctrl(0x80+0x09);
write_ctrl(0x0f);
}
if(num==6){ //停在月
while(key1==0);
TR0=0;
write_ctrl(0x80+0x06);
write_ctrl(0x0f);
}
if(num==7){//停在年,将年分成两部分,十个位和千百位
while(key1==0);
TR0=0;
write_ctrl(0x80+0x03);
write_ctrl(0x0f);
}
if(num==8){//年的千百位
while(key1==0);
TR0=0;
write_ctrl(0x80+0x01);
write_ctrl(0x0f);
}
if(num==0){ //第四次摁,继续计数
while(key1==0);
write_ctrl(0x0c);
TR0=1; //重新计时
}
}
}
//检测key2键是否被按下,即进行加1运算
if(num!=0){ //此处要放到和检测key1的if语句平行的位置
if(num==1){   //秒
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
sec=sec+1;
if(sec==60){
sec=0;
}
write_sfm(6,sec);
write_ctrl(0x80+0x40+7);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==2){ //分
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
min=min+1;
if(min==60){
min=0;
}
write_sfm(3,min);
write_ctrl(0x80+0x40+4);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==3){  //小时
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
hour=hour+1;
if(hour==24){
hour=0;
}
write_sfm(0,hour);
write_ctrl(0x80+0x40+1);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==4){  //星期
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
week=week+1; 
if(week==7){
week=0;
}
write_ctrl(0x80+0x0b);
for(k=0;k<3;k++){
write_data(week_table[week*3+k]); 
} //采用两层循环,这样就可以每次week加1,来显示三个字母。
write_ctrl(0x80+0x0d);
}
}
}
if(num==5){   //天
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
day=day+1;
if(day==32){
day=1;
}
write_nyr(8,day);
write_ctrl(0x80+9);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==6){   //月
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
month=month+1;
if(month==13){
month=1;
}
write_nyr(5,month);
write_ctrl(0x80+6);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==7){ //把年分成了两半
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
year_r=year_r+1;
if(year_r==100){
year_r=0;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==8){
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
year_l=year_l+1;
if(year_l==100){
year_l=0;
}
write_nyr(0,year_l);
write_ctrl(0x80+1);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
}
//减1操作
if(num!=0){ //此处要放到和检测key1的if语句平行的位置
if(num==1){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
sec=sec-1;
if(sec==-1){
sec=59;
}
write_sfm(6,sec);
write_ctrl(0x80+0x40+7);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==2){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
min=min-1;
if(min==-1){
min=59;
}
write_sfm(3,min);
write_ctrl(0x80+0x40+4);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==3){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
hour=hour-1;
if(hour==-1){
hour=23;
}
write_sfm(0,hour);
write_ctrl(0x80+0x40+1);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==4){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
week=week-1;
if(week==-1){
week=6;
}
//week=week%7;
write_ctrl(0x80+0x0b);
for(k=0;k<3;k++){
write_data(week_table[week*3+k]);
}
write_ctrl(0x80+0x0d);
}
}
}
if(num==5){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
day=day-1;
if(day==-1){
day=31;
}
write_nyr(8,day);
write_ctrl(0x80+9);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==6){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
month=month-1;
if(month==-1){
month=12;
}
write_nyr(5,month);
write_ctrl(0x80+6);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==7){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
year_r=year_r-1;
if(year_r==-1){
year_r=99;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
if(num==8){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
year_r=year_r-1;
if(year_r==-1){
year_r=99;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因为写完以后,光标会向右移一个位置
//所以此句把光标左移
}
}
}
}
}
void main()
{
uchar i;
uchar j;
init();
while(1){
keyscan();
if(count==20){
count=0;
sec++;
if(sec==60){
sec=0;
min++;
if(min==60){
min=0;
hour++;
if(hour==24){
hour=0;
day++;
week=(week+1)%7;
write_ctrl(0x80+0x0b);
for(j=0;j<3;j++){
write_data(week_table[week*3+j]);
//write_ctrl(0x06);
}

//闰年2月28天的计算
if(((year%4==0)&&(year%100!=0))||(year%400==0)){
if(month==2){
if(day==29){
day=1;
month++;
}
else {
write_nyr(8,day);
}
write_nyr(8,day);
write_nyr(5,month);
}
}
if(!(((year%4==0)&&(year%100!=0))||(year%400==0))){
if(month==2){
if(day==30){
day=1;
month++;
}
else {
write_nyr(8,day);
}
write_nyr(8,day);
write_nyr(5,month);
}
}
//月份为31天的  


for(i=0;i<7;i++){
if(month==month1[i]){
if(day==32){
day=1;
month++;
if(month==13){
month=1;
year_r++;
year++;
if(year_r==100){
year_r=0;
year_l++;
}
write_nyr(0,year_l);
}
write_nyr(2,year_r);
//break;
}
write_nyr(5,month);
}

}
write_nyr(8,day);
//以下为月份数数是30天的
for(i=0;i<4;i++){
if(month==month1[i]){
if(day==31){
day=1;
month++;
if(month==13){
month=1;
year_r++;
year++;
if(year_r==100){
year_r=0;
year_l++;
}
write_nyr(0,year_l);
}
write_nyr(2,year_r);
//break;
}
write_nyr(5,month);
}

}
write_nyr(8,day);

}
write_sfm(0,hour);//此语句应该放在sec==60,然后清零后面,否则则会出现sec=60的现象
}
write_sfm(3,min);
}
write_sfm(6,sec);
}
}
}
//定时器0
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
}






原创粉丝点击