关于使用51单片机io口和lcd与定时器实现电子日历钟

源代码(C语言)

/*******************************仅用lcd与51单片机io口,定时器0来实现电子日历**************************/
#include<reg52.h>
#include<intrins.h>
#include<copy.h>
#define u16 unsigned int
#define u8 unsigned char
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;//写指令 输入:RS=L,RW=L,E=下降沿脉冲,DB0~DB7=指令码 输出:无
sbit LCD1602_RS=P2^6;//写数据 输入:RS=H,RW=L,E=下降沿脉冲,DB0~DB7=数据 输出:无
sbit k1=P3^1;//对应单片机上的4个独立按键    
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
//k1功能键k2加键k3减键
u8 code table[]="  2022-01-01 SUN";
u8 code table1[]="    23:59:55";
u8 code table2[7][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
u8 count,k1num;char shi,fen,miao,ri,yue,nian,shiji;//时分秒日月年世纪-1(世纪这个,估计也活不到那么久)
u8 xingqiji,i;//全局变量星期几,i
void Delay_ms(u16 z)//延时函数大致1ms
{
        u16 x,y;
            for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void LcdWriteCom(uchar com)      //写入命令
{
    LCD1602_E = 0;     //使能
    LCD1602_RS = 0;       //选择发送命令
    LCD1602_RW = 0;       //选择写入
    
    P0 = com;     //放入命令
    Delay_ms(1);        //等待数据稳定

    LCD1602_E = 1;              //写入时序
    Delay_ms(5);      //保持时间
    LCD1602_E = 0;
}
void LcdWrite_data(u8 dat)//写数据
{
        LCD1602_RS=1;        //选择输入数据
        P0=dat;                //接在P0口
        Delay_ms(5);
        LCD1602_E = 1;  //写入时序
        Delay_ms(5);
        LCD1602_E = 0;  
}
void Init()
{        
         u8 i;nian=22;yue=1;ri=1;shi=23;fen=59;miao=55,shiji=20;//初始化要设置参数,也要改初始显示    
         LcdWriteCom(0x38);//显示模式 8位总线 显示2行 5*10
         LcdWriteCom(0x0c);//开光标,光标闪烁 0000 1111  
       //开光标不闪烁0x0e 0000 1110    ;闪烁0x0f
         LcdWriteCom(0x06);//0000 0110 读写一个字符后地址光标加一
         LcdWriteCom(0x01);//清屏
         //LcdWriteCom(0x80+0x10);//设置数据指针起点80H+ 
       //例如如果是0x81则数据从第一行的第二个显示
        for(i=0;i<16;i++)
            {
                    LcdWrite_data(table[i]);
                    Delay_ms(5);
            }
            LcdWriteCom(0x80+0x40);//设置数据指针起点80H+
            for(i=0;i<12;i++)
            {
                    LcdWrite_data(table1[i]);
                    Delay_ms(5);
            }
                TMOD=0x01;//开定时器0
                TH0=0x3c;
                TL0=0xb0;
                ET0=1;
                EA=1;
                TR0=1;
            

//                //设置INT0
//                IT0=1;//跳变沿出发方式(下降沿)
//                EX0=1;//打开INT0的中断允许。    
//            EA=1;//打开总中断    
//本来想用中断来写星期函数,还是算了,没必要

}    
void write_sfm(u8 add,u8 dat)//一个地址位,一个数据位
{
        u8 shi,ge;//十位个位,本来用了个千百位,老报错,也找不到原因,索性不用了
        shi=dat/10;
        ge=dat%10;
        LcdWriteCom(0x80+0x40+add);//从地址位下一位写入,自动移位来写个位数据
        LcdWrite_data(0x30+shi);
        LcdWrite_data(0x30+ge);
    
}
void write_nyr(u8 add,u8 dat)
{
            u8 shi,ge;
        shi=dat/10;
        ge=dat%10;
        LcdWriteCom(0x80+add);
        LcdWrite_data(0x30+shi);
        LcdWrite_data(0x30+ge);
    
}

void keypros()
{
    if(k1==0)          //检测按键K1是否按下
    {    
        Delay_ms(10);   //消除抖动 一般大约10ms
        if(k1==0)     //再次判断功能键是否按下        
                {                        
                    while(!k1);     //检测按键是否松开
                    k1num++;
                    if(k1num==1)
                        {
                            TR0=0;            //关闭定时器
                        LcdWriteCom(0x80+0x40+11);//在秒钟处闪烁
                        LcdWriteCom(0x0f);//显示光标        
                        }
                    if(k1num==2)
                        {
                        LcdWriteCom(0x80+0x40+8);//在分钟处
                        }
                    if(k1num==3)
                        {
                        LcdWriteCom(0x80+0x40+5);    //在小时处        
                        }
                    if(k1num==4)
                        {
                        LcdWriteCom(0x80+15);    //星期
                        }
                    if(k1num==5)
                        {
                        LcdWriteCom(0x80+11);    //日
                        }
                    if(k1num==6)
                        {
                        LcdWriteCom(0x80+8);    //月        
                        }
                    if(k1num==7)
                        {
                        LcdWriteCom(0x80+5);    //年        
                        }
                    if(k1num==8)
                            {
                        LcdWriteCom(0x80+3);//世纪-1
                            }
                    if(k1num==9)
                        {
                            k1num=0;
                            LcdWriteCom(0x0c);//按下光标不再闪烁
                            TR0=1;//打开定时器
                        }
                                                    
                    }                                
                                                            
                }                                        
                                                                if(k1num!=0)
                                            {
                                                                            if(k2==0)          //检测按键K2是否按下
                                                                        {        
                                                                            Delay_ms(10);   //消除抖动 一般大约10ms
                                                                            if(k2==0)     //再次判断按键是否按下                                                                                                                            
                                                                            {
                                                                                    while(!k2);
                                                                                    if(k1num==1)//如果值为1,则对秒操作
                                                                                        {
                                                                                                miao++;
                                                                                                if(miao==60)
                                                                                                    miao=0;
                                                                                                write_sfm(10,miao);
                                                                                                LcdWriteCom(0x80+0x40+10);//写完让光标停在这个位置
                                                                                                
                                                                                        }
                                                                                    if(k1num==2)//值为2,对分操作
                                                                                        {
                                                                                                fen++;
                                                                                                if(fen==60)
                                                                                                    fen=0;
                                                                                                write_sfm(7,fen);
                                                                                                LcdWriteCom(0x80+0x40+7);
                                                                                                
                                                                                        }
                                                                                    if(k1num==3)//值为3,对小时操作
                                                                                        {
                                                                                                shi++;
                                                                                                if(shi==24)
                                                                                                    shi=0;
                                                                                                write_sfm(4,shi);
                                                                                                LcdWriteCom(0x80+0x40+4);
                                                                                                
                                                                                        }    
                                                                                    if(k1num==4)//值为4,对星期操作
                                                                                        {
                                                                                                xingqiji++;//一个礼拜7天,用取余的方式调用switch语句比if语句要少些很多,其实都是复制粘贴
                                                                                                if(xingqiji==8)
                                                                                                    xingqiji=1;
                                                                                                    switch(xingqiji%7)//二维数组来存放字符串,对应用for循环一个个输到对应地址
                                                                                    {
                                                                                            case(0):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[6][i]);
                                                                                            }break;
                                                                                            case(1):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[0][i]);
                                                                                            }break;
                                                                                            case(2):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[1][i]);
                                                                                            }break;
                                                                                            case(3):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[2][i]);
                                                                                            }break;
                                                                                            case(4):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[3][i]);
                                                                                            }break;
                                                                                            case(5):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[4][i]);
                                                                                            }break;        
                                                                                            case(6):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
                                                                                            {
                                                                                                    LcdWrite_data( table2[5][i]);
                                                                                            }break;        
                                                                                    }
                                                                                                LcdWriteCom(0x80+13);
                                                                                                
                                                                                        }    
                                                                                    if(k1num==5)//值为5,对天进行操作
                                                                                    {
                                                                                                        ri++;
                                                                                                    if(ri==32)                                                                                             
                                                                                                        ri=1;                                                                                                                                                                                                                                                                                             
                                                                                            write_nyr(10,ri);
                                                                                            LcdWriteCom(0x80+10);
                                                                                    }
                                                                                    if(k1num==6)//值为6,对月进行操作
                                                                                    {
                                                                                            yue++;
                                                                                            if(yue==13)
                                                                                                yue=1;
                                                                                            write_nyr(7,yue);
                                                                                            LcdWriteCom(0x80+7);
                                                                                    }
                                                                                    if(k1num==7)//值为7,对年进行操作
                                                                                    {
                                                                                            nian++;                                                                                                                                                                                            
                                                                                            if(nian==100)
                                                                                                nian=0;
                                                                                            write_nyr(4,nian);
                                                                                            LcdWriteCom(0x80+4);
                                                                                    }
                                                                                    if(k1num==8)//值为8,对世纪-1进行操作
                                                                                    {
                                                                                                shiji++;
                                                                                                if(shiji==100)
                                                                                                    shiji=0;
                                                                                                write_nyr(2,shiji);
                                                                                                LcdWriteCom(0x80+2);
                                                                                    }
                                                                                }    
                                                                            }
                                                    if(k3==0)          //检测按键K3是否按下
                                            {        
                                                            Delay_ms(10);   //消除抖动 一般大约10ms
                                                            if(k3==0)     //再次判断按键是否按下                                                                                                                            
                                                            {
                                                                    while(!k3);
                                                                    if(k1num==1)
                                                                        {
                                                                                miao--;            //前面定义的这几个都是char型,方便一些,如果用unsigned char的话是255吧
                                                                                if(miao==-1)
                                                                                {    
                                                                                    miao=59;                                                        
                                                                                }                                                                                                        
                                                                                write_sfm(10,miao);
                                                                                LcdWriteCom(0x80+0x40+10);                                                        
                                                                        }
                                                                    if(k1num==2)
                                                                        {
                                                                                fen--;
                                                                                if(fen==-1)
                                                                                {    
                                                                                    fen=59;
                                                                                }
                                                                                    write_sfm(7,fen);
                                                                                LcdWriteCom(0x80+0x40+7);
                                                                                
                                                                        }
                                                                    if(k1num==3)
                                                                        {
                                                                                shi--;
                                                                                if(shi==-1)
                                                                                    shi=23;
                                                                                write_sfm(4,shi);
                                                                                LcdWriteCom(0x80+0x40+4);                                                    
                                                                        }//星期数很小,没有对其设置减功能,后续再添加别的功能
                                                                        if(k1num==5)//值为4,对天进行操作
                                                                                    {
                                                                                                        ri--;
                                                                                                    if(ri==0)                                                                                             
                                                                                                        ri=31;                                                                                                                                                                                                                                                                                             
                                                                                            write_nyr(10,ri);
                                                                                            LcdWriteCom(0x80+10);
                                                                                    }
                                                                                    if(k1num==6)//值为5,对月进行操作
                                                                                    {
                                                                                            yue--;
                                                                                            if(yue==0)
                                                                                                yue=12;
                                                                                            write_nyr(7,yue);
                                                                                            LcdWriteCom(0x80+7);
                                                                                    }
                                                                                    if(k1num==7)//值为6,对年进行操作
                                                                                    {
                                                                                            nian--;                                                                                                                                                                                            
                                                                                            if(nian==0)
                                                                                                nian=99;
                                                                                            write_nyr(4,nian);
                                                                                            LcdWriteCom(0x80+4);
                                                                                    }
                                                                                    if(k1num==8)//值为7,对世纪-1进行操作
                                                                                    {
                                                                                                shiji--;
                                                                                                if(shiji==0)
                                                                                                    shiji=99;
                                                                                                write_nyr(2,shiji);
                                                                                                LcdWriteCom(0x80+2);
                                                                                    }
                                                            }
                                                
                                            }        
                                            
                            }                                                                                                
}
void nyr_pros()//写年月日
{            
                    if(ri==32)//1,3,5,7,8,10,12一个月31天
                            {
                                    if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
                                    {    
                                            ri=1;
                                            yue++;
                                        write_nyr(7,yue);
                                        write_nyr(10,ri);
                                    }    
                                    if(yue==13)
                                    {
                                        yue=1;
                                        nian++;
                                        write_nyr(4,nian);
                                        write_nyr(7,yue);
                                        write_nyr(10,ri);
                                        if(nian==100)
                                        {        
                                                nian=0;                    
                                                shiji++;
                                            write_nyr(4,nian);//这里一定对nian进行刷新,不然会出现100进位变成:0而不是00的情况
                                                write_nyr(2,shiji);
                                        }
                                    }
                            }
                                                                        
                        
                                        if(ri==31)//4,6,9,11一个月30天
                                    {
                                            if(yue==4||yue==6||yue==9||yue==11)
                                            {
                                                    ri=1;
                                                    yue++;
                                                write_nyr(7,yue);
                                                write_nyr(10,ri);
                                            }    
                                    }
                    
                            
                                if((yue==2)&&(nian%4==0))                
                                {
                                            if(ri==30)//闰年2月29天
                                        {
                                            ri=1;
                                            yue++;
                                            write_nyr(7,yue);
                                            write_nyr(10,ri);    
                                        }                    
                                }
                                    else if(ri==29)//非闰年2月28天
                            {
                                        ri=1;
                                        yue++;
                                    write_nyr(7,yue);    
                                    write_nyr(10,ri);
                            }
                            
}

//void xingqi()//开始写的if,万物皆可if
//{
//    u8 i,j;
//    
//    j=xingqiji%7;        
//            if(j==1)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[0][i]);
//            }
//        }            
//        if(j==2)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[1][i]);
//            }
//        }            
//        if(j==3)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[2][i]);
//            }
//        }            
//        if(j==4)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[3][i]);
//            }
//        }            
//        if(j==5)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[4][i]);
//            }
//        }            
//        if(j==6)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[5][i]);
//            }
//        }            
//        if(j==0)
//        {
//                LcdWriteCom(0x80+13);
//                for(i=0;i<3;i++)
//            {
//                    LcdWrite_data( table2[6][i]);
//            }
//        }            
//        
//}
void xingqi_pros()//因为不能放进按键里,暂时不放了,因为重复定义,我还没找到问题所在
{            
xingqiji++;
if(xingqiji==8)                
    xingqiji=1;
switch(xingqiji%7)
{
        case(0):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[6][i]);
        }break;
        case(1):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[0][i]);
        }break;
        case(2):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[1][i]);
        }break;
        case(3):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[2][i]);
        }break;
        case(4):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[3][i]);
        }break;
        case(5):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[4][i]);
        }break;        
        case(6):LcdWriteCom(0x80+13);for(i=0;i<3;i++)
        {
                LcdWrite_data( table2[5][i]);
        }break;        
}
                                
}
void main()
{
        
        Init();        
        while(1)
        {                                
                    keypros();                
    }
}
void timer0()interrupt 1
{
        
        TH0=0x3c;
        TL0=0xb0;
        count++;
        if(count==20)
                {
                            count=0;
                            miao++;
                            if(miao==60)
                        {
                                    miao=0;
                                    fen++;
                                    if(fen==60)
                            {
                                            fen=0;
                                            shi++;
                                            if(shi==24)
                                            {
                                                    shi=0;
                                                    ri++;                                                    
                                                    xingqi_pros();
                                                    nyr_pros();
                                                    write_nyr(10,ri);
                                            }
                                            write_sfm(4,shi);
                            }
                                    write_sfm(7,fen);
                        }
                            write_sfm(10,miao);                            
                 }
        
}
//过程很艰辛,结果很有趣

上一篇:lcd之framebuffer应用编程


下一篇:4.11 51单片机-LCD1602显示屏