Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

教程如下:

  • 实现功能:(代码见底部)
  1. 串口和1602 显示实时时间
  2. 串口和按键修改时间
  • 实时时钟:

Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

  • 按键修改时间:一共5个按键,分别修改分钟、小时、天数、月份、年份。  

分钟满60归1,小时进1。小时24进制。 天数按照公历闰平年来计算某年某月是多少进制。如2020年2月是闰二月,一共29天,那这个天数就是29进制。 包括星期几也计算在内。已经验证准确无误。 (只是每次按键都是加一)

Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

  • 串口修改时间:格式如:2019,11,17,12,25,36,5     

                                     年,月,日,时,分,秒,星期

通过Arduino编译器的串口调试器发送。(确保串口发送的日期跟星期几是对应的,按键是在正确对应的情况下计算才会准确)

Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

  • 虚拟 串口安装如下:VSPD串口软件的文件夹里找到vspd ,点击ok,I agree ,next,finish 

Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

  • 打开软件:直接点击okArduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示
  • 然后点击Add Pair:

Arduino MEGA2560 DS1302 实时时钟(protues+程序)使用教程 可用串口、按键修改|串口和1602显示

  • 在Arduino编译器上找到串口调试器,设置波特率(一般是9600)当然只要仿真里的虚拟串口COMPIM跟Arduino是一对,并且波特率一样就行了。
  • 好贴代码:(需要找到对应的库文件才行,懒得的话 直接点我的博客或者链接去下载吧)

#include <FlexiTimer2.h>  
#include <LiquidCrystal.h>

/*
Arduino 连接 DS1302
增加了串口调整时间代码
2019,11,17,11,22,40,5
*/
#include <stdio.h>
#include <string.h>
#include "DS1302.h"

// 初始化针脚
const int rs = 30, en = 31 , d4 = 32, d5 = 33, d6 = 34,d7 = 35;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
/* 接口定义
CE(DS1302 pin5) -> Arduino D5
IO(DS1302 pin6) -> Arduino D6
SCLK(DS1302 pin7) -> Arduino D7
*/
uint8_t CE_PIN   = 24;
uint8_t IO_PIN   = 26;
uint8_t SCLK_PIN = 25;

/* 日期变量缓存 */
char buf[50];
char buflcd1[30],buflcd2[30],buflcd3[30];
char day[10];
/* 串口数据缓存 */
String comdate = "";
int numdate[7] ={0}, j = 0, mark = 0;
/* 创建 DS1302 对象 */
DS1302 rtc (CE_PIN, IO_PIN, SCLK_PIN);


void print_time()
{
    /* 从 DS1302 获取当前时间 */
    Time t = rtc.time();
    /* 将星期从数字转换为名称 */
    memset(day, 0, sizeof(day));
    switch (t.day)
    { case 0: strcpy(day, "Saturday "); break;
      case 1: strcpy(day, "Sunday   "); break;
      case 2: strcpy(day, "Monday   "); break;
      case 3: strcpy(day, "Tuesday  "); break;
      case 4: strcpy(day, "Wednesday"); break;
      case 5: strcpy(day, "Thursday "); break;
      case 6: strcpy(day, "Friday   "); break;
      case 7: strcpy(day, "Saturday "); break; 
    }
    /* 将日期代码格式化凑成buf等待输出 */
    snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d", day, t.yr, t.mon, t.date, t.hr, t.min, t.sec);
    /* 输出日期到串口 */
    Serial.println(buf);
}

int w=0;
void setup()
{   
    Serial.begin(9600);
    rtc.write_protect(false);
    rtc.halt(false);
    attachInterrupt(1,minutes, FALLING);//引脚号是3 分钟加一
    attachInterrupt(5,hours, FALLING);//引脚号是18  小时加一
    attachInterrupt(4,days, FALLING);//引脚号是19  天数加一
    attachInterrupt(3,monthes, FALLING);//引脚号是20 月份加一
    attachInterrupt(2,years, FALLING);//引脚号是21  年份加一
    lcd.begin(16, 2);lcd.setCursor(1, 0);
    lcd.print("17dianziyiban ");//17电子一班
    lcd.setCursor(1, 1);   
    lcd.print(" shichengshi");  //施成师
    delay(1000);
    lcd.clear() ;  
    FlexiTimer2::set(500,1.0/1000,LCD);
    FlexiTimer2::start();  
}
void LCD()

   Time t = rtc.time();                                       //LCD的屏幕会有显示“残留”
   snprintf(buflcd1, sizeof(buflcd1), "%04d  %s",t.yr, day );//为了减少清屏带来的闪烁 
   lcd.setCursor(0, 0);lcd.print(buflcd1);                   //LCD显示字符的排版 比较奇特
   snprintf(buflcd2, sizeof(buflcd2), "%02d-%02d",t.mon ,t.date);
   lcd.setCursor(0, 1);lcd.print(buflcd2); 
   snprintf(buflcd3, sizeof(buflcd3), "%02d:%02d:%02d",  t.hr, t.min, t.sec);
   lcd.setCursor(6, 1);lcd.print(buflcd3);  
}
void minutes()

  Time t = rtc.time();  
  t.min++;if(t.min>60)t.min=1,t.hr++;
  Time p( t.yr, t.mon, t.date, t.hr, t.min,t.sec,t.day);
  rtc.time(p);
 }
void hours()

  Time t = rtc.time();  
  t.hr++;
  if(t.hr>24)
  {t.hr=1;t.day++;t.date++;
   t.day=t.day%7;
  }Time p( t.yr, t.mon, t.date, t.hr, t.min,t.sec,t.day);
  rtc.time(p);
 }
void days()

  Time t = rtc.time();  
  t.date++;  
   switch(t.mon)
     {case 1: if(t.date>31)t.date=1,t.mon++;break;
     case 2: if(t.date>28)t.date=1,t.mon++;break;
     case 3: if(t.date>31)t.date=1,t.mon++;break;
     case 4: if(t.date>30)t.date=1,t.mon++;break;
     case 5: if(t.date>31)t.date=1,t.mon++;break;
     case 6: if(t.date>30)t.date=1,t.mon++;break;
     case 7: if(t.date>31)t.date=1,t.mon++;break;
     case 8: if(t.date>31)t.date=1,t.mon++;break;
     case 9: if(t.date>30)t.date=1,t.mon++;break;
     case 10: if(t.date>31)t.date=1,t.mon++;break;
     case 11: if(t.date>30)t.date=1,t.mon++;break;
     case 12: if(t.date>31)t.date=1,t.mon++;break;
     }
  t.day++;t.day=t.day%7;
  Time p( t.yr, t.mon, t.date, t.hr, t.min,t.sec,t.day);
  rtc.time(p);
 }
void monthes()

  Time t = rtc.time();  
  t.mon++; if(t.mon>12)t.mon=1,t.yr++;
  switch(t.mon)
     {case 1: t.day+=3;t.day=t.day%7;break;
     case 2: t.day+=3;t.day=t.day%7;break;
     case 3:   if(t.yr%4==0)t.day+=1;else t.day+=0;t.day=t.day%7;break;
     case 4:   t.day+=3;t.day=t.day%7;break;
     case 5:   t.day+=2;t.day=t.day%7;break;
     case 6:   t.day+=3;t.day=t.day%7;break;
     case 7:  t.day+=2;t.day=t.day%7;break;
     case 8:  t.day+=3;t.day=t.day%7; break;
     case 9:   t.day+=3;t.day=t.day%7;break;
     case 10:  t.day+=2;t.day=t.day%7;break;
     case 11:   t.day+=3;t.day=t.day%7;break;
     case 12: t.day+=2;t.day=t.day%7;break;
     }
  Time p( t.yr, t.mon, t.date, t.hr, t.min,t.sec,t.day);
  rtc.time(p);
 }
 void years()

  Time t = rtc.time();  
  t.yr++; 
  switch((t.yr-1)%4)
  {case 0:if(t.mon<3)t.day+=2;else t.day+=1;break;
  default: t.day+=1;
  }
  Time p( t.yr, t.mon, t.date, t.hr, t.min,t.sec,t.day);
  rtc.time(p);
 }
 
void loop()
{
   /* 当串口有数据的时候,将数据拼接到变量comdate */
    while (Serial.available() > 0)
    {
        comdate += char(Serial.read());
        delay(2);
        mark = 1;
    }
    /* 以逗号分隔分解comdate的字符串,分解结果变成转换成数字到numdate[]数组 */
    if(mark == 1)
    {
        //Serial.print("You inputed : ");
        //Serial.println(comdate);
        for(int i = 0; i < comdate.length() ; i++)
        {
            if(comdate[i] == ',' || comdate[i] == 0x10 || comdate[i] == 0x13)
            {
                j++;
            }
            else
            {
                numdate[j] = numdate[j] * 10 + (comdate[i] - '0');
            }
        }
        /* 将转换好的numdate凑成时间格式,写入DS1302 */
        Time t(numdate[0], numdate[1], numdate[2], numdate[3], numdate[4], numdate[5], numdate[6]);
        rtc.time(t);
        mark = 0;j=0;
        /* 清空 comdate 变量,以便等待下一次输入 */
        comdate = String("");
        /* 清空 numdate */
        for(int i = 0; i < 7 ; i++) numdate[i]=0;
    }
   
    /* 打印当前时间 */
    print_time();
    delay(1000);
}