Proteus仿真:Arduino单片机多功能数字时钟设计

文章目录

  • 一、功能简介
  • 二、软件设计
  • 三、实验现象
  • 联系作者

  • 一、功能简介

    本项目使用Proteus8仿真Arduino单片机控制器,使用PCF8574、LCD1602液晶、DS1302温度传感器、DS1302时钟、按键、蜂鸣器等。
    主要功能:
    系统运行后,LCD1602显示当前日期时间和温度值,当按下K3键进入日期和时间设置模式,
    每按下K3键1次,则切换不同位置,通过K1和K2键调整数据;按下K4键可保存并返回主界面。
    当按下K4键,进入闹钟设置模式,可通过K4键切换不同位置,通过K1和K2键调整数据;按下
    K3键可保存并返回主界面。当时间到达闹钟时间,开启闹铃,可按下K1键取消闹铃。


    二、软件设计

    /*
    作者:嗨小易(QQ:3443792007)
    
    */
    
    
    //系统数据获取
    void sys_data_get(void)
    {
      while(1)
      {
        //获取温度
        sys_ctrl.temp=ds18b20_read_temperture()*10;
        //获取时间
        ds1302_read_time();
    
        break;
      }
    }
    
    //系统数据显示
    void sys_data_show(void)
    {
      u8 buf[5];
      while(1)
      {
        //正常模式显示
        if(sys_ctrl.mode==0)
        {
          //未进入闹钟设置模式
          if(sys_ctrl.alarm_mode==0)
          {
            //日期时间显示
            lcd1602_show_nums(2,0,gDS1302_TIME[6],2,0x80);//年
            lcd1602_show_nums(5,0,gDS1302_TIME[4],2,0x80);//月
            lcd1602_show_nums(8,0,gDS1302_TIME[3],2,0x80);//日
            lcd1602_show_nums(15,0,gDS1302_TIME[5],1,0x80);//星期
            lcd1602_show_nums(0,1,gDS1302_TIME[2],2,0x80);//时
            lcd1602_show_nums(3,1,gDS1302_TIME[1],2,0x80);//分
            lcd1602_show_nums(6,1,gDS1302_TIME[0],2,0x80);//秒
            //温度显示
            if(sys_ctrl.temp<9999)
            {
              buf[0]=sys_ctrl.temp/100+0x30;
              buf[1]=sys_ctrl.temp%100/10+0x30;
              buf[2]='.';
              buf[3]=sys_ctrl.temp%100%10+0x30;
              buf[4]='\0';
              lcd1602_show_string(11,1,buf);
            }
          }
          //闹钟设置显示
          else
          {
            //闹钟时间显示
            lcd1602_show_nums(6,0,sys_ctrl.alarm_time[0],2,0x80);//时
            lcd1602_show_nums(9,0,sys_ctrl.alarm_time[1],2,0x80);//分
            //闹钟开关状态显示
            if(sys_ctrl.alarm_onoff==0)lcd1602_show_string(4,1,"OFF");
            else lcd1602_show_string(4,1," ON");
    
            //对应位置闪烁
            switch(sys_ctrl.alarm_mode)
            {
              case 1:
                lcd1602_show_string(6,0,"  ");
                delay(50);
                lcd1602_show_nums(6,0,sys_ctrl.alarm_time[0],2,0x80);//时
                break;
              case 2:
                lcd1602_show_string(9,0,"  ");
                delay(50);
                lcd1602_show_nums(9,0,sys_ctrl.alarm_time[1],2,0x80);//分
                break;
              case 3:
                lcd1602_show_string(4,1,"   ");
                delay(50);
                //闹钟开关状态显示
                if(sys_ctrl.alarm_onoff==0)lcd1602_show_string(4,1,"OFF");
                else lcd1602_show_string(4,1," ON");
                break;
            }
          }
        }
        //设置模式显示
        else 
        {
          //设置时间显示
          lcd1602_show_nums(2,0,sys_ctrl.set_time[6],2,0x80);//年
          lcd1602_show_nums(5,0,sys_ctrl.set_time[4],2,0x80);//月
          lcd1602_show_nums(8,0,sys_ctrl.set_time[3],2,0x80);//日
          lcd1602_show_nums(15,0,sys_ctrl.set_time[5],1,0x80);//星期
          lcd1602_show_nums(0,1,sys_ctrl.set_time[2],2,0x80);//时
          lcd1602_show_nums(3,1,sys_ctrl.set_time[1],2,0x80);//分
          lcd1602_show_nums(6,1,sys_ctrl.set_time[0],2,0x80);//秒
    
          //对应位置闪烁
          switch(sys_ctrl.mode)
          {
            case 1:
              lcd1602_show_string(2,0,"  ");
              delay(50);
              lcd1602_show_nums(2,0,sys_ctrl.set_time[6],2,0x80);//年
              break;
            case 2:
              lcd1602_show_string(5,0,"  ");
              delay(50);
              lcd1602_show_nums(5,0,sys_ctrl.set_time[4],2,0x80);//月
              break;
            case 3:
              lcd1602_show_string(8,0,"  ");
              delay(50);
              lcd1602_show_nums(8,0,sys_ctrl.set_time[3],2,0x80);//日
              break;
            case 4:
              lcd1602_show_string(15,0,"  ");
              delay(50);
              lcd1602_show_nums(15,0,sys_ctrl.set_time[5],1,0x80);//星期
              break;
            case 5:
              lcd1602_show_string(0,1,"  ");
              delay(50);
              lcd1602_show_nums(0,1,sys_ctrl.set_time[2],2,0x80);//时
              break;
            case 6:
              lcd1602_show_string(3,1,"  ");
              delay(50);
              lcd1602_show_nums(3,1,sys_ctrl.set_time[1],2,0x80);//分
              break;
            case 7:
              lcd1602_show_string(6,1,"  ");
              delay(50);
              lcd1602_show_nums(6,1,sys_ctrl.set_time[0],2,0x80);//秒
              break;
          }
        }
    
        break;
      }
    }
    
    //系统数据设置
    void sys_data_set(void)
    {
      u8 key=0;
      static u8 oneflag=0;
      static u8 nzoneflag=0;
      u8 i=0;
    
      key=key_scan(0);
      if(key!=0)beep_alarm(100,1000);//提示音
      //设置
      if(key==KEY3_PRESS)
      {
        //未进入闹钟设置
        if(sys_ctrl.alarm_mode==0)
        {
          sys_ctrl.mode++;
          if(sys_ctrl.mode>7)sys_ctrl.mode=1;
          if(oneflag==0)
          {
            oneflag=1;
            //获取当前时间记录
            for(i=0;i<7;i++)sys_ctrl.set_time[i]=gDS1302_TIME[i];
            _sys_parm_set_show();//系统参数设置界面显示      
          }
        } 
        //进入闹钟设置
        else
        {
          sys_ctrl.alarm_mode=0;
          nzoneflag=0;
          sys_open_show();//系统开机界面显示
        }
      }
      //加
      else if(key==KEY1_PRESS)
      {
        //时间修改
        if(sys_ctrl.mode!=0)
        {
          switch(sys_ctrl.mode)
          {
            case 1://年
              sys_ctrl.set_time[6]++;
              if(sys_ctrl.set_time[6]>99)sys_ctrl.set_time[6]=0;
              break;
            case 2://月
              sys_ctrl.set_time[4]++;
              if(sys_ctrl.set_time[4]>12)sys_ctrl.set_time[4]=1;
              break;
            case 3://日
              sys_ctrl.set_time[3]++;
              if(sys_ctrl.set_time[3]>31)sys_ctrl.set_time[3]=1;
              break;
            case 4://星期
              sys_ctrl.set_time[5]++;
              if(sys_ctrl.set_time[5]>7)sys_ctrl.set_time[5]=1;
              break;
            case 5://时
              sys_ctrl.set_time[2]++;
              if(sys_ctrl.set_time[2]>23)sys_ctrl.set_time[2]=0;
              break;
            case 6://分
              sys_ctrl.set_time[1]++;
              if(sys_ctrl.set_time[1]>59)sys_ctrl.set_time[1]=0;
              break;
            case 7://秒
              sys_ctrl.set_time[0]++;
              if(sys_ctrl.set_time[0]>59)sys_ctrl.set_time[0]=0;
              break;
          }
        }
        //闹钟设置
        if(sys_ctrl.alarm_mode!=0)
        {
          switch(sys_ctrl.alarm_mode)
          {
            case 1:
              sys_ctrl.alarm_time[0]++;
              if(sys_ctrl.alarm_time[0]>23)sys_ctrl.alarm_time[0]=0;
              break;
            case 2:
              sys_ctrl.alarm_time[1]++;
              if(sys_ctrl.alarm_time[1]>59)sys_ctrl.alarm_time[1]=0;
              break;
            case 3:
              sys_ctrl.alarm_onoff=!sys_ctrl.alarm_onoff;
              break;
          }
        }
    
        //已闹铃,取消
        if(sys_ctrl.naoling==1)sys_ctrl.naoling=0;
      }
      //减
      else if(key==KEY2_PRESS)
      {
        //时间修改
        if(sys_ctrl.mode!=0)
        {
          switch(sys_ctrl.mode)
          {
            case 1://年
              sys_ctrl.set_time[6]--;
              if(sys_ctrl.set_time[6]<0)sys_ctrl.set_time[6]=99;
              break;
            case 2://月
              sys_ctrl.set_time[4]--;
              if(sys_ctrl.set_time[4]<0)sys_ctrl.set_time[4]=12;
              break;
            case 3://日
              sys_ctrl.set_time[3]--;
              if(sys_ctrl.set_time[3]<0)sys_ctrl.set_time[3]=31;
              break;
            case 4://星期
              sys_ctrl.set_time[5]--;
              if(sys_ctrl.set_time[5]<0)sys_ctrl.set_time[5]=7;
              break;
            case 5://时
              sys_ctrl.set_time[2]--;
              if(sys_ctrl.set_time[2]<0)sys_ctrl.set_time[2]=23;
              break;
            case 6://分
              sys_ctrl.set_time[1]--;
              if(sys_ctrl.set_time[1]<0)sys_ctrl.set_time[1]=59;
              break;
            case 7://秒
              sys_ctrl.set_time[0]--;
              if(sys_ctrl.set_time[0]<0)sys_ctrl.set_time[0]=59;
              break;
          }
        }
        //闹钟设置
        if(sys_ctrl.alarm_mode!=0)
        {
          switch(sys_ctrl.alarm_mode)
          {
            case 1:
              sys_ctrl.alarm_time[0]--;
              if(sys_ctrl.alarm_time[0]<0)sys_ctrl.alarm_time[0]=23;
              break;
            case 2:
              sys_ctrl.alarm_time[1]--;
              if(sys_ctrl.alarm_time[1]<0)sys_ctrl.alarm_time[1]=59;
              break;
            case 3:
              sys_ctrl.alarm_onoff=!sys_ctrl.alarm_onoff;
              break;
          }
        }
      }
      //确定
      else if(key==KEY4_PRESS)
      {
        //时间修改
        if(sys_ctrl.mode!=0)
        {
          sys_ctrl.mode=0;
          oneflag=0;
          ds1302_set_time(sys_ctrl.set_time[6],sys_ctrl.set_time[4],sys_ctrl.set_time[3],sys_ctrl.set_time[2],sys_ctrl.set_time[1],sys_ctrl.set_time[0]);
          sys_open_show();//系统开机界面显示
        }
        //闹钟设置
        else
        {
          sys_ctrl.alarm_mode++;
          if(sys_ctrl.alarm_mode>3)sys_ctrl.alarm_mode=1;
          if(nzoneflag==0)
          {
            nzoneflag=1;
            _sys_alarm_set_show();//闹钟设置界面显示
          }
        }
      }
    }
    
    
    
    

    三、实验现象

    B站演示视频:https://space.bilibili.com/444388619



    联系作者

    视频地址:https://space.bilibili.com/444388619/video
    专注于51单片机、STM32、国产32、DSP、Proteus、arduino、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

    作者:Hai小易

    物联沃分享整理
    物联沃-IOTWORD物联网 » Proteus仿真:Arduino单片机多功能数字时钟设计

    发表回复