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

文章目录


一、功能简介

本项目使用Proteus8仿真Arduino单片机控制器,使用PCF8574、LCD1602液晶、DS1302温度传感器、DS1302时钟、按键、蜂鸣器等。

主要功能:

系统运行后,LCD1602显示当前日期时间和温度值,当按下K3键进入日期和时间设置模式,

每按下K3键1次,则切换不同位置,通过K1和K2键调整数据;按下K4键可保存并返回主界面。

当按下K4键,进入闹钟设置模式,可通过K4键切换不同位置,通过K1和K2键调整数据;按下

K3键可保存并返回主界面。当时间到达闹钟时间,开启闹铃,可按下K1键取消闹铃。


二、软件设计

c 复制代码
/*
作者:嗨小易(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设计,视频分享,技术交流。

相关推荐
菠萝咕噜肉i12 分钟前
超详细:Redis分布式锁
数据库·redis·分布式·缓存·分布式锁
长风清留扬15 分钟前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理
OpsEye28 分钟前
MySQL 8.0.40版本自动升级异常的预警提示
数据库·mysql·数据库升级
Ljw...28 分钟前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
远歌已逝3 小时前
维护在线重做日志(二)
数据库·oracle
qq_433099405 小时前
Ubuntu20.04从零安装IsaacSim/IsaacLab
数据库
Dlwyz5 小时前
redis-击穿、穿透、雪崩
数据库·redis·缓存
网易独家音乐人Mike Zhou6 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
工业甲酰苯胺7 小时前
Redis性能优化的18招
数据库·redis·性能优化
没书读了8 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring