单片机
返回首页

用普中开发板做的51单片机的智能时钟具有闹钟功能

2020-08-27 来源:51hei

本贴针对学完单片机并且有读懂代码的非新手同学。本人目前放寒假,这个是本人在上个学期的单片机课上要求做的综合实验,现在重新修改了下增加了菜单目前测试毫无问题可以完美使用。有志向做闹钟的同学可以参考一下,原码上由本人写的大量注释可以方便看懂。

使用了LCD1602、DS1302、DS18B20用来测试温度、内部含闹钟系统但本人没有做EEPROM有需要的同学可以自行添加。


单片机源程序如下:

#include

#include

#include

#include

#include

#include


#define normal 0//正常显示时钟界面

#define settime 1//设定时钟界面

#define setalarm 2//设定闹钟界面

#define displayalarm 3//显示闹钟界面

#define normal_12 4//显示十二小时制界面

#define caidan 5


unsigned char system=normal;//我一开始就把界面切换为正常显示时钟界面


extern unsigned char i,k;


extern unsigned int code song[3][300];


unsigned char code *week[8]={'NO ','Mon ','Tue ','Wed ','Thu ','Fri ','Sat ','Sun '};


unsigned char code *clockzifu[4]={'ON ','OFF ','REP ','NRE '};


struct Time timeset={0x18,0x01,0x16,0x14,0x30,0x50,0x03};


//第一个闹钟

//第二个闹钟

//第三个闹钟

//第四个闹钟

//第五个闹钟

struct alarmtime xdata clock[5]={{1,16,14,31,0,1,0,1},{1,8,14,32,3,0,0,0},{1,7,18,49,1,1,1,0},{0,0,0,0,0,0,1,0},{1,25,0,0,0,0,1,2}};


unsigned char alarmnum;//闹钟


unsigned char a;


unsigned char flag=0;


unsigned char xinghao=0;


unsigned char tentoBCD(unsigned char dat)//十进制转换为BCD码函数

{

        unsigned char dat1,dat2;

        dat1=dat/10;

        dat2=dat%10;

        dat2=dat2+dat1*16;

        return dat2;

}


unsigned char BCDtoten(unsigned char dat)//BCD码转为十进制函数

{

        unsigned char dat1,dat2;

        dat1=dat/16;

        dat2=dat%16;

        dat2=dat2+dat1*10;

        return dat2;

}


void DS18B20deal(int temp)//DS18B20数据处理函数 显示温度更新温度         

{

    //先判断温度值是否大于0或小于0等于0

           float tp;//保存的数据可能带小数  

        if(temp<0)//当温度值为负数

          {

                LCD1602_writechar(9,1,0x2D);//ASCII码中的-符号

                temp=temp-1;//因为读取的温度是实际温度的补码,所以减1,再取反求出原码

                temp=~temp;//还原读取的数据

                tp=temp;//保存到变量里面

                temp=tp*0.0625*100+0.5;//强制转换成一个整形的数据.留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就算加上0.5,还是在小数点后面。       

          }

        else//当温度值为正数

          {                       

                LCD1602_writechar(9,1,0x20);//ASCII码中的空格

                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量。如果温度是正的那么,那么正数的原码就是补码它本身

                temp=tp*0.0625*100+0.5;//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点。后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就算加上0.5,还是在小数点后面。       

        }

        LCD1602_writechar(10,1,temp/10000+'0');//温度百位

        LCD1602_writechar(11,1,temp%10000/1000+'0');//温度十位

        LCD1602_writechar(12,1,temp%1000/100+'0');//温度个位

    LCD1602_writechar(13,1,0x2E);//ASCII码小数点

        LCD1602_writechar(14,1,temp%100/10+'0');//小数点后一位

        LCD1602_writechar(15,1,temp%10+'0');//小数点后两位

}


void updatetime()//更新时钟上的时间

{

        unsigned char time[9];//存储变量

        DS1302_gettime(×et);//读取时间

        time[0]=BCDtoten(timeset.hour)/10+'0';//小时的十位

        time[1]=BCDtoten(timeset.hour)%10+'0';//小时的个位

        time[2]=':';

        time[3]=BCDtoten(timeset.min)/10+'0';//分的十位

        time[4]=BCDtoten(timeset.min)%10+'0';//分的个位

        time[5]=':';

        time[6]=BCDtoten(timeset.sec)/10+'0';//秒的十位

        time[7]=BCDtoten(timeset.sec)%10+'0';//秒的个位

        time[8]='';//字符串结束标志


        LCD1602_writestr(0,1,time);//在LCD上面打印时间

}


void updatetime_12()//更新十二小时制界面的时间

{

        unsigned char time[9];

        DS1302_gettime(×et);//读取时间

        time[0]= BCDtoten(timeset.hour)%12/10+'0';//小时的十位

        time[1]= BCDtoten(timeset.hour)%12%10+'0';//小时的个位

        time[2]=':';

        time[3]= BCDtoten(timeset.min)/10+'0';//分的十位

        time[4]= BCDtoten(timeset.min)%10+'0';//分的个位

        time[5]=':';

        time[6]= BCDtoten(timeset.sec)/10+'0';//秒的十位

        time[7]= BCDtoten(timeset.sec)%10+'0';//秒的个位

        time[8]='';//字符串结束标志                                                                                                                                                                                                               

        LCD1602_writestr(3,1,'TIME:');//打印出TIME的字符串

        LCD1602_writestr(8,1,time);//在第二行第四列显示时间

        if(BCDtoten(timeset.hour)>12)//要是小时大于12时

        {

          LCD1602_writestr(0,1,'PM');//则显示PM

        }

        else//小时不大于12

        {

          LCD1602_writestr(0,1,'AM');//则显示AM

        }  

}


void updatedate()//更新日历

{

        unsigned char date[12];

        date[0]= '2';

        date[1]= '0';

        date[2]= BCDtoten(timeset.year)/10%10+'0';//年的十位

        date[3]= BCDtoten(timeset.year)%10+'0';//年的个位

        date[4]='.';

        date[5]= BCDtoten(timeset.mon)/10+'0';//月的十位

        date[6]= BCDtoten(timeset.mon)%10+'0';//月的个位

        date[7]='.';

        date[8]= BCDtoten(timeset.day)/10+'0';//日的十位

        date[9]= BCDtoten(timeset.day)%10+'0';//日的个位

        date[10]='';

        LCD1602_writestr(0,0,date);//显示年月日

        LCD1602_writestr(11,0,week[timeset.week]);//显示星期

}


void updatealarm()//更新闹钟设定值

{

        unsigned char str0[14];

        unsigned char str1[2];


        str0[0]=alarmnum+'0';

        str0[1]=' ';

        str0[2]=clock[alarmnum].mon/10+'0';//月份十位

        str0[3]=clock[alarmnum].mon%10+'0';//月份个位

        str0[4]='-';

        str0[5]=clock[alarmnum].day/10+'0';//日期十位

        str0[6]=clock[alarmnum].day%10+'0';//日期个位

        str0[7]=' ';

        str0[8]=clock[alarmnum].hour/10+'0';//小时十位

        str0[9]=clock[alarmnum].hour%10+'0';//小时个位

        str0[10]=':';

        str0[11]=clock[alarmnum].min/10+'0';//分钟十位

        str0[12]=clock[alarmnum].min%10+'0';//分钟个位

        str0[13]='';


        LCD1602_writestr(0,1,str0);


        str1[0]=clock[alarmnum].music+'0';//铃声

        str1[1]='';


        LCD1602_writestr(0,0,'U');

        LCD1602_writestr(1,0,str1);//显示铃声

        LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//显示重不重复

        LCD1602_writestr(7,0,week[clock[alarmnum].week]);//显示星期

        LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//显示开关       

}


void anjian4();


void anjian1()

{

  if(system==normal)

  {

    system=caidan;

        xinghao=0;

        LCD1602_clear();

        LCD1602_writechar(0,0,'*');

        LCD1602_writestr(1,0,'12');

        LCD1602_writestr(1,1,'alarm');

        LCD1602_writestr(8,0,'setclock');

        LCD1602_writestr(8,1,'setalarm');

  }

  else if(system==caidan&&xinghao==0)

  {

    system=normal_12;//切换到12小时制

        LCD1602_clear();//清屏

        updatetime_12();//显示12小时制的时间

        updatedate();//显示日期

  }

  else if(system==caidan&&xinghao==1)

  {

    system=displayalarm;//切换到闹钟显示

    LCD1602_clear();//清屏

        updatealarm();//显示闹钟界面

  }

  else if(system==caidan&&xinghao==2)

  {

    system=settime;//进入设置时间界面

        LCD1602_clear();

        updatetime();//刷新时间

    updatedate();//刷新日期

    DS18B20deal(DS18B20readtemp());//DS18B20数据处理函数 同时输出温度

    flag=0;//光标索引设置到秒钟上

    anjian4();//显示光标位置

    LCD1602_openguangbiao();//LCD1602打开光标显示

  }

  else if(system==caidan&&xinghao==3)

  {

    system=setalarm;//进入设置闹钟

        LCD1602_clear();//清屏

        updatealarm();//显示闹钟界面

    flag=0;//光标索引设置到多闹钟选择处上

    anjian4();//显示光标位置

    LCD1602_openguangbiao();//LCD1602打开光标显示

  }

  else if(system==settime)

  {

    system=normal;//切换回正常显示时钟的界面,显示日历时钟、温度。

        DS1302_settime(×et);//把设定时间写入实时时钟

        LCD1602_closeguangbiao();//LCD1602关闭光标显示

    LCD1602_clear();//LCD1602清屏

    updatetime();//刷新时间

        updatedate();//立即刷新日期

        DS18B20deal(DS18B20readtemp());//DS18B20数据处理函数 显示温度

  }

  else if(system==setalarm)

  {

     system=displayalarm;//返回到闹钟显示

         LCD1602_closeguangbiao();//LCD1602关闭光标显示

         LCD1602_clear();//清屏

         updatealarm();//刷新闹钟界面

  }

}


void anjian4()

{

  if(system==caidan)

  {

    system=normal;

        LCD1602_clear();//清屏

        updatetime();//显示时钟时间

        updatedate();//显示日期

        DS18B20deal(DS18B20readtemp());//DS18B20数据处理函数

  }

  else if(system==normal_12)

  {

    system=normal;//返回时钟显示界面

        LCD1602_clear();//清屏

        updatetime();//显示时钟时间

        updatedate();//显示日期

        DS18B20deal(DS18B20readtemp());//DS18B20数据处理函数

  }

  else if(system==displayalarm)

  {

    system=caidan;

        xinghao=1;

        LCD1602_clear();

        LCD1602_writechar(0,1,'*');

        LCD1602_writestr(1,0,'12');

        LCD1602_writestr(1,1,'alarm');

        LCD1602_writestr(8,0,'setclock');

        LCD1602_writestr(8,1,'setalarm');

  }

  else if(system==settime)//当前系统状态位于设置时间时 定义光标的位置

  {

        switch(flag)//保存的设置位

     {

       case 0:LCD1602_setcur(7,1);flag=1;break;//定位于秒钟个位处

       case 1:LCD1602_setcur(4,1);flag=2;break;//定位于分钟处

       case 2:LCD1602_setcur(1,1);flag=3;break;//定位于小时处

       case 3:LCD1602_setcur(11,0);flag=4;break;//定位于星期处

       case 4:LCD1602_setcur(9,0);flag=5;break;//定位于日处

       case 5:LCD1602_setcur(6,0);flag=6;break;//定位于月处

       default:LCD1602_setcur(3,0);flag=0;break;//定位于年处

     }

  }

  else if(system==setalarm)//当前系统状态位于设置闹钟时 定义光标的位置

     {

        switch(flag)//保存的设置位

        {

            case 0:LCD1602_setcur(0,1);flag=1;break;//定位于多闹钟选择处

                        case 1:LCD1602_setcur(3,1);flag=2;break;//定位于闹钟月份处

                        case 2:LCD1602_setcur(6,1);flag=3;break;//定位于闹钟日处

                        case 3:LCD1602_setcur(9,1);flag=4;break;//定位于闹钟分钟处

                        case 4:LCD1602_setcur(12,1);flag=5;break;//定位于闹钟小时处

                        case 5:LCD1602_setcur(1,0);flag=6;break;//定位于闹钟铃声选择处

                        case 6:LCD1602_setcur(3,0);flag=7;break;//定位于闹钟重复与不重复选择处

                        case 7:LCD1602_setcur(7,0);flag=8;break;//定位于闹钟星期选择处

            default:LCD1602_setcur(11,0);flag=0;break;//定位于闹钟开关处

        }

     }

}


void zengjia()//增加

{

    if(system==caidan)

        {

          if(xinghao==0)

          {

            LCD1602_clear();

            LCD1602_writechar(0,1,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=1;

          }

          else if(xinghao==1)

          {

                  LCD1602_clear();

            LCD1602_writechar(7,0,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=2;

          }

          else if(xinghao==2)

          {

            LCD1602_clear();

            LCD1602_writechar(7,1,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=3;

          }

          else if(xinghao==3)

          {

            LCD1602_clear();

            LCD1602_writechar(0,0,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=0;

          }

        }

        else if(system==settime)//当设置日历时间的界面时

    {

                switch(flag)//检查光标位置

        {                               

                        case 1: a=BCDtoten(timeset.sec);//把BCD码转为十进制 因为DS1302里时钟程序读写时都是BCD码 转为10进制更好处理

                                        if(a<59)

                                        {

                                          a++;

                                        }  

                                        else

                                        {

                                          a=0;//限制设置秒钟不超过59秒,超过则回到0

                                        }

                                        timeset.sec=tentoBCD(a);//把十进制转为BCD码 因为DS1302时钟程序读写时都是BCD码 将加完的东西重新赋值给sec

                                        LCD1602_writechar(6,1,(timeset.sec>>4)+'0');//秒的十位

                                        LCD1602_writechar(7,1,(timeset.sec&0x0f)+'0');//秒的个位

                                        LCD1602_setcur(7,1);//光标保持原位

                                        break;


                        case 2:        a=BCDtoten(timeset.min);//把BCD码转为十进制

                                        if(a<59)

                                        {

                                          a++;

                                        }  

                                        else

                                        {

                                          a=0;//限制设置分钟不超过59分,超过则回到0

                                        }

                                        timeset.min=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(3,1,(timeset.min>>4)+'0');//分的十位

                                        LCD1602_writechar(4,1,(timeset.min&0x0f)+'0');//分的个位

                                        LCD1602_setcur(4,1);//光标保持原位

                                        break;


                        case 3:        a=BCDtoten(timeset.hour);//把BCD码转为十进制

                                        if(a<23)

                                        {

                                          a++;

                                        }  

                                        else

                                        {

                                          a=0;//限制设置小时不超过23时,超过则回到0

                                        }

                                        timeset.hour=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(0,1,(timeset.hour>>4)+'0');//小时的十位

                                        LCD1602_writechar(1,1,(timeset.hour&0x0f)+'0');//小时的个位

                                        LCD1602_setcur(1,1);//光标保持原位

                                        break;


                        case 4: if(timeset.week<7)//限制不超过星期日,如果超过则回到周一

                                        {

                                          timeset.week++;

                                        }  

                                        else

                                        {

                                          timeset.week=1;//回到星期一

                                        }

                                        LCD1602_writestr(11,0,week[timeset.week]);//

                                        LCD1602_setcur(11,0);//光标保持原位

                                        break;


                        case 5:        a=BCDtoten(timeset.day);//把BCD码转为十进制

                                        if(a<31)

                                        {

                                          a++;

                                        }  

                                        else

                                        {

                                          a=1;//限制设置日期不超过31日,超过则回到1

                                        }

                                        timeset.day=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(8,0,(timeset.day>>4)+'0');//日的十位

                                        LCD1602_writechar(9,0,(timeset.day&0x0f)+'0');//日的个位

                                        LCD1602_setcur(9,0);//光标保持原位

                                        break;


                        case 6:        a=BCDtoten(timeset.mon);//把BCD码转为十进制

                                        if(a<12)

                                        {

                                          a++;

                                        }  

                                        else

                                        {

                                          a=1;//限制设置月份不超过12月,超过则回到1

                                        }

                                        timeset.mon=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(5,0,(timeset.mon>>4)+'0');//月的十位

                                        LCD1602_writechar(6,0,(timeset.mon&0x0f)+'0');//月的个位

                                        LCD1602_setcur(6,0);//光标保持原位

                                        break;


                        case 0:        a=BCDtoten(timeset.year);//把BCD码转为十进制

                                        if(a<99)

                                        {

                                          a++;                                          

                                        }  

                                        else

                                        {

                                          a=0;//限制设置年不超过99年,超过则回到0

                                        }

                                        timeset.year=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(2,0,(timeset.year>>4)+'0');//年的十位

                                        LCD1602_writechar(3,0,(timeset.year&0x0f)+'0');//年的个位

                                        LCD1602_setcur(3,0);//光标保持原位

                                        break;

                }       

        }

        else if(system==setalarm)//当设置闹钟的时候

        {

                switch(flag)//检查光标位置

        {

                        case 1: if(alarmnum<4)//换闹钟

                                {

                                          alarmnum++;

                                }  

                                        else

                                        {

                                          alarmnum=0;

                                        }

                                        updatealarm();//更新闹钟设定值

                                        LCD1602_setcur(0,1);//光标保持原位

                                        break;

                        case 2:        if(clock[alarmnum].mon<12)

                                {

                                          clock[alarmnum].mon++;

                                }  

                                        else

                                        {

                                          clock[alarmnum].mon=1;//限制设置月份不超过12月,超过则回到1

                                        }

                                        LCD1602_writechar(2,1,(clock[alarmnum].mon/10)+'0');//月的十位

                                        LCD1602_writechar(3,1,(clock[alarmnum].mon%10)+'0');//月的个位

                                        LCD1602_setcur(3,1);//光标保持原位

                                        break;

                        case 3:        if(clock[alarmnum].day<31)

                                {

                                          clock[alarmnum].day++;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].day=1;//限制设置日期不超过31日,超过则回到1

                                        }

                                        LCD1602_writechar(5,1,(clock[alarmnum].day/10)+'0');//日的十位

                                        LCD1602_writechar(6,1,(clock[alarmnum].day%10)+'0');//日的个位

                                        LCD1602_setcur(6,1);//光标保持原位

                                        break;

                        case 4:        if(clock[alarmnum].hour<23)

                                {

                                          clock[alarmnum].hour++;

                                        }

                                        else

                                        {

                                          clock[alarmnum].hour=0;//限制设置小时不超过23时,超过则回到0

                                        }                                                                                                                                                                                                                                                                                                                                                                                           

                                        LCD1602_writechar(8,1,(clock[alarmnum].hour/10)+'0');//小时的十位

                                        LCD1602_writechar(9,1,(clock[alarmnum].hour%10)+'0');//小时的个位

                                        LCD1602_setcur(9,1);//光标保持原位

                                        break;

                        case 5: if(clock[alarmnum].min<59)

                                {

                                          clock[alarmnum].min++;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].min=0;//限制设置分钟不超过59分,超过则回到0

                                        }

                                        LCD1602_writechar(11,1,(clock[alarmnum].min/10)+'0');//分钟的十位

                                        LCD1602_writechar(12,1,(clock[alarmnum].min%10)+'0');//分钟的个位

                                        LCD1602_setcur(12,1);//光标保持原位

                                        break;

                                       

                        case 6:        if(clock[alarmnum].music<2)

                                {

                                          clock[alarmnum].music++;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].music=0;

                                        }

                                        LCD1602_writechar(1,0,clock[alarmnum].music+'0');//音乐曲目

                                        LCD1602_setcur(1,0);//光标保持原位

                                        break;

                                                               

                        case 7:        clock[alarmnum].alarmre=~clock[alarmnum].alarmre;//取反

                                        LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//显示闹钟状态

                                        LCD1602_setcur(3,0);//光标保持原位

                                        break;

                        case 8:        if(clock[alarmnum].week<7)

                                        {

                                          clock[alarmnum].week++;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].week=0;//限制不超过星期日,如果超过则回到不设星期

                                        }

                                        LCD1602_writestr(7,0,week[clock[alarmnum].week]);//显示到液晶上;

                                        LCD1602_setcur(7,0);//光标保持原位

                                        break;


                        case 0: clock[alarmnum].alarmon=~clock[alarmnum].alarmon;//取反

                                        LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//显示闹钟状态

                                        LCD1602_setcur(11,0);//光标保持原位

                                        break;               

                }               

        }

}


void jianxiao()//S4按键功能函数,数据减

{

        if(system==caidan)

        {

          if(xinghao==0)

          {

            LCD1602_clear();

            LCD1602_writechar(7,1,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=3;

          }

          else if(xinghao==3)

          {

                  LCD1602_clear();

            LCD1602_writechar(7,0,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=2;

          }

          else if(xinghao==2)

          {

            LCD1602_clear();

            LCD1602_writechar(0,1,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=1;

          }

          else if(xinghao==1)

          {

            LCD1602_clear();

            LCD1602_writechar(0,0,'*');

            LCD1602_writestr(1,0,'12');

            LCD1602_writestr(1,1,'alarm');

            LCD1602_writestr(8,0,'setclock');

            LCD1602_writestr(8,1,'setalarm');

                xinghao=0;

          }

        }

        else if(system==settime)//设置日期/时间

    {

                switch(flag)//检查光标位置

        {                               

                        case 1:        a=BCDtoten(timeset.sec);//把BCD码转为十进制

                                        if(a!=0)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=59;//限制设置秒钟不为0时减1,为0时回到59

                                        }

                                        timeset.sec=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(6,1,(timeset.sec>>4)+'0');//秒的十位

                                        LCD1602_writechar(7,1,(timeset.sec&0x0f)+'0');//秒的个位

                                        LCD1602_setcur(7,1);//光标保持原位

                                        break;


                        case 2:        a=BCDtoten(timeset.min);//把BCD码转为十进制

                                        if(a!=0)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=59;//限制设置分钟不为0时减1,为0时回到59

                                        }

                                        timeset.min=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(3,1,(timeset.min>>4)+'0');//分的十位

                                        LCD1602_writechar(4,1,(timeset.min&0x0f)+'0');//分的个位

                                        LCD1602_setcur(4,1);//光标保持原位

                                        break;


                        case 3:        a=BCDtoten(timeset.hour);//把BCD码转为十进制

                                        if(a!=0)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=23;//限制设置小时不为0时减1,为0时回到23

                                        }

                                        timeset.hour=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(0,1,(timeset.hour>>4)+'0');//小时的十位

                                        LCD1602_writechar(1,1,(timeset.hour&0x0f)+'0');//小时的个位

                                        LCD1602_setcur(1,1);//光标保持原位

                                        break;


                        case 4: //如果为当前为星期一时,回到星期天

                                        if(timeset.week!=1)

                                        {

                                          timeset.week--;

                                        }  

                                        else

                                        {

                                          timeset.week=7;

                                        }

                                        LCD1602_writestr(11,0,week[timeset.week]);//显示到液晶上;

                                        LCD1602_setcur(11,0);//光标保持原位

                                        break;


                        case 5:        a=BCDtoten(timeset.day);//把BCD码转为十进制

                                        if(a!=1)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=31;

                                        }//限制设置日期不为1时减1,为0时回到31

                                        timeset.day=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(8,0,(timeset.day>>4)+'0');//日期的十位

                                        LCD1602_writechar(9,0,(timeset.day&0x0f)+'0');//日期的个位

                                        LCD1602_setcur(9,0);//光标保持原位

                                        break;


                        case 6:        a=BCDtoten(timeset.mon);//把BCD码转为十进制

                                        if(a!=1)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=12;//限制设置月份不为1时减1,为0时回到12

                                        }

                                        timeset.mon=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(5,0,(timeset.mon>>4)+'0');//月份的十位

                                        LCD1602_writechar(6,0,(timeset.mon&0x0f)+'0');//月份的个位

                                        LCD1602_setcur(6,0);//光标保持原位

                                        break;


                        case 0:        a=BCDtoten(timeset.year);//把BCD码转为十进制

                                        if(a!=0)

                                        {

                                          a--;

                                        }  

                                        else

                                        {

                                          a=99;//限制设置年不为0时减1,为0时回到99

                                        }

                                        timeset.year=tentoBCD(a);//把十进制转为BCD码

                                        LCD1602_writechar(2,0,(timeset.year>>4)+'0');//年的十位

                                        LCD1602_writechar(3,0,(timeset.year&0x0f)+'0');//年的个位

                                        LCD1602_setcur(3,0);//光标保持原位

                                        break;

                }               

        }

        else if(system==setalarm)//设置闹钟

        {

                switch(flag)//检查光标位置

        {

                        case 1: if(alarmnum!=0)//换闹钟

                                {

                                          alarmnum--;

                                        }

                                        else

                                        {

                                          alarmnum=4;

                                        }

                                        updatealarm();//刷新闹钟界面

                                        LCD1602_setcur(0,1);//光标保持原位

                                        break;

                        case 2:        if(clock[alarmnum].mon!=1)

                                {

                                          clock[alarmnum].mon--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].mon=12;//限制设置月份不超过12月,超过则回到1

                                        }

                                        LCD1602_writechar(2,1,(clock[alarmnum].mon/10)+'0');//月份十位

                                        LCD1602_writechar(3,1,(clock[alarmnum].mon%10)+'0');//月份个位

                                        LCD1602_setcur(3,1);//光标保持原位

                                        break;

                        case 3:        if(clock[alarmnum].day!=1)

                                {

                                          clock[alarmnum].day--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].day=31;//限制设置日期不超过31日,超过则回到1

                                        }

                                        LCD1602_writechar(5,1,(clock[alarmnum].day/10)+'0');//日期十位

                                        LCD1602_writechar(6,1,(clock[alarmnum].day%10)+'0');//日期个位

                                        LCD1602_setcur(6,1);//光标保持原位

                                        break;

                        case 4:        if(clock[alarmnum].hour!=0)

                                {

                                          clock[alarmnum].hour--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].hour=23;//限制设置小时不超过23时,超过则回到0

                                        }                                                                                                                                                                                                                                                                                                                                                                                           

                                        LCD1602_writechar(8,1,(clock[alarmnum].hour/10)+'0');//小时十位

                                        LCD1602_writechar(9,1,(clock[alarmnum].hour%10)+'0');//小时个位

                                        LCD1602_setcur(9,1);//光标保持原位

                                        break;

                        case 5: if(clock[alarmnum].min!=0)

                                {

                                          clock[alarmnum].min--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].min=59;//限制设置分钟不超过59分,超过则回到0

                                        }

                                        LCD1602_writechar(11,1,(clock[alarmnum].min/10)+'0');//分钟十位

                                        LCD1602_writechar(12,1,(clock[alarmnum].min%10)+'0');//分钟个位

                                        LCD1602_setcur(12,1);//光标保持原位

                                        break;

                                       

                        case 6:        if(clock[alarmnum].music!=0)

                                {

                                          clock[alarmnum].music--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].music=2;

                                        }

                                        LCD1602_writechar(1,0,clock[alarmnum].music+'0');

                                        LCD1602_setcur(1,0);//光标保持原位

                                        break;

                                                               

                        case 7:        clock[alarmnum].alarmre=~clock[alarmnum].alarmre;

                                        LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//显示闹钟状态

                                        LCD1602_setcur(3,0);//光标保持原位

                                        break;

                        case 8:        if (clock[alarmnum].week!=0)

                                        {

                                          clock[alarmnum].week--;

                                        }  

                                        else

                                        {

                                          clock[alarmnum].week=7;

                                        }

                                        LCD1602_writestr(7,0,week[clock[alarmnum].week]);//显示到液晶上;

                                        LCD1602_setcur(7,0);//光标保持原位

                                        break;


                        case 0: clock[alarmnum].alarmon=~clock[alarmnum].alarmon;

                                        LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//显示闹钟状态

                                        LCD1602_setcur(11,0);//光标保持原位

                                        break;

                }               

        }

}


void alarmset()//闹钟函数

{

        unsigned char i;

        for(i=0;i<5;i++)//扫描闹钟

        {

            //0就是重复 1不重复

                if(clock[i].alarmre)//不重复时

                {

                          if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.mon)==clock[i].mon)&&(BCDtoten(timeset.day)==clock[i].day)&&(BCDtoten(timeset.sec))==0)//检查闹钟的时间和日期是否跟目前的时钟时间日期匹配

                    {

                              //0为打开 1为关闭

                          if(!clock[i].alarmon)//检查闹钟是否打开

                                                {

                                                  LCD1602_clear();//清屏

                                                  LCD1602_writestr(0,0,'Alarm');

                                                  LCD1602_writechar(6,0,i+'0');

                                                  LCD1602_writestr(8,0,'ring!');

                                                  LCD1602_writestr(0,1,'Please press!');

                                                  playmusic(clock[i].music);//播放铃声

                                                  LCD1602_clear();//清屏

                                                }

                    }

                }

                else//如果重复

                {

                        if(clock[i].week)//有设置星期 则是每一个特定星期重复

                        {

                                if(clock[i].week==timeset.week)//看闹钟设置的星期是否为现在的星期

                                {

                                        if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.sec))==0)//检查闹钟的时间是否跟目前的时钟时间匹配

                                    {

                                          if(!clock[i].alarmon)//检查闹钟是否打开

                                                {

                                                  LCD1602_clear();//清屏

                                                  LCD1602_writestr(0,0,'Alarm');

                                                  LCD1602_writechar(6,0,i+'0');

                                                  LCD1602_writestr(8,0,'ring!');

                                                   LCD1602_writestr(0,1,'Please press!');

                                                  playmusic(clock[i].music);//播放音乐

                                                  LCD1602_clear();//清屏

                                                }

                                    }

                                       

                                }       

                       

                        }

                        else//没有设置星期且在重复的情况下 则为每天都响

                        {

                                        if((BCDtoten(timeset.hour)==clock[i].hour)&&(BCDtoten(timeset.min)==clock[i].min)&&(BCDtoten(timeset.sec))==0)//检查闹钟的时间是否跟目前的时钟时间匹配

                                    {

                                        if (!clock[i].alarmon)//检查闹钟是否打开

                                                {

                                                  LCD1602_clear();//清屏

                                                  LCD1602_writestr(0,0,'Alarm');

                                                  LCD1602_writechar(6,0,i+'0');

                                                  LCD1602_writestr(8,0,'ring!');

                                                  LCD1602_writestr(0,1,'Please press!');

                                                  playmusic(clock[i].music);//播放音乐

                                                  LCD1602_clear();//清屏

                                                }

                                    }                               

                        }       

                }

        }          

}



void dingshiqi0()

{

        TMOD|=0x01;

        TH0=0;

        TL0=0;

        TR0=0;

        ET0=1;

        PT0=1;

        EA=1;

}


void dingshiqi1()

{

        TMOD|=0x10;

        EA=1;

        ET1=1;

        TR1=1;

        TH1=0xED;

        TL1=0xFE;

}


void timer0() interrupt 1

{       

    TH0=song[k][i]/256;

        TL0=song[k][i]%256;

        beep=~beep;


}


void timer1() interrupt 3

{

    TH1=0xED;

        TL1=0xFE;

        key_scan();               

}


void main()

{

        dingshiqi0();//定时器0初始化

        dingshiqi1();//定时器1初始化

        LCD1602_init();//LCD1602初始化

        DS1302_init();//DS1302初始化

        while(1)

        {

                key_driver();

                alarmset();//闹钟设定函数

                if(system==normal)//当状态为正常显示时间时

                {

                   updatetime();//刷新时间

                   updatedate();//刷新日期

                   DS18B20deal(DS18B20readtemp());//DS18B20数据处理函数 同时输出温度

                }

                else if(system==normal_12)//当状态为显示12小时制

                {

                   updatetime_12();//刷新时间

                   updatedate();//刷新日期

                }

        }

}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 带有短路保护系统的5V直流稳压电源电路图

    相关电子头条文章