Arduino DS1302 时钟模块应用示例(带闹钟功能)

呃,说点什么呢?

没啥好说的,很基础的东西。也是多年前某宝买了来,一直丢在角落里。还能找点儿空闲,就想让它们也动一动。
免得怪我遗忘了它们。

时钟模块用的是 DS1302,蜂鸣器用的是有源蜂鸣器(无源的还要设置频率编个曲儿啥的,我比较懒,喜欢直接一点的,HIGH or LOW)。


就是上面这些东西。

没有加按钮,因为后续打算添加 LCD 显示屏和温湿度传感器,做成一个比较完整的系统。所以 Arduino 的 IO 接口,能省就省了。时间设置以及其他功能,可以通过串口输入命令配置。闹钟是在代码的常量定义里手动修改(图省事啊)。

还有就是,用到的库文件来自网络,作者我他么也不认识。剩下的代码几乎全是我个人完成,没系统地学过 C,所以应该还有很大的提升空间。

线路连接图如下:


运行效果如下:


上代码了啊

ds1302.ino(这个是我写的。。。)

/******************************************************************************
-------------------------1.开发环境:Arduino IDE-----------------------------------
-------------------------------2.作者:starky-----------------------------------------
******************************************************************************/
#include <Arduino.h>
#include "DS1302.h"

#define Buzz_Pin 5                 // 有源蜂鸣器引脚
unsigned char Alarm_Hour=6;          // 闹钟小时设置
unsigned char Alarm_Minute=30;        // 闹钟分钟设置
bool Always=false;                 //是否不间断地输出时间到串口(每隔 1 秒)

void setup()
{
  pinMode(Buzz_Pin,OUTPUT);
  DS1302_Init();
  Serial.begin(9600); 
  Serial.println("Welcome to use!");  
  DS1302_GetTime(&DS1302Buffer);
  Display_RTCC();
  Serial.println("Type \"help\" To Get The Help Information.");
}

//显示时间
void Display_RTCC()
{
  
  if(DS1302Buffer.Year < 10)
  {
    Serial.print("200");
  }
  else
  {
    Serial.print("20");
  }
  Serial.print(DS1302Buffer.Year);
  Serial.print('-');
  Serial.print(DS1302Buffer.Month);
  Serial.print('-');
  Serial.print(DS1302Buffer.Day);

  Serial.print("   ");

  switch(DS1302Buffer.Week)
  {
    case 1:
        Serial.println("Mon");         //显示星期一
        break;
    case 2:
        Serial.println("Tue");         //显示星期二
        break;
    case 3:
        Serial.println("Wed");         //显示星期三
        break;
    case 4:
        Serial.println("Thu");         //显示星期四
        break;
    case 5:
        Serial.println("Fri");         //显示星期五
        break;
    case 6:
        Serial.println("Sat");         //显示星期六
        break;
    case 7:
        Serial.println("Sun");         //显示星期日
        break;
    default : break;            
  }

  Serial.print(DS1302Buffer.Hour);
  Serial.print(':');
  Serial.print(DS1302Buffer.Minute);
  Serial.print(':');
  Serial.println(DS1302Buffer.Second);
}

// 获取串口输入
void Scan_Input()
{
  String comdata=""; 
  while (Serial.available() > 0)  
   {
     comdata += char(Serial.read());
     delay(2);
   }
  if(comdata.length()==20 && comdata.startsWith("set"))
    {
      Set_Time(comdata);
    }
  if(comdata=="show")
  {
    Serial.println("The Time Now Is:");
    Always=false;
    Display_RTCC();
  }

//是否不间断地将时间输出到串口
  if(comdata=="always")
  {
    Always=!Always;
  }

//显示闹钟
  if(comdata=="alarm")
  {
    Serial.print("Alarm Set to ");
    Serial.print(Alarm_Hour); 
    Serial.print(":");
    Serial.println(Alarm_Minute);   
  }
  if(comdata=="help")
  {
    help();
  }
}

//时间设置函数
void Set_Time(String &command)
{
  DS1302_ON_OFF(0);     //关闭振荡
  DS1302Buffer.Year=command.substring(4,6).toInt();
  DS1302Buffer.Month=command.substring(7,9).toInt();
  DS1302Buffer.Day=command.substring(10,12).toInt();
  DS1302Buffer.Week=command.substring(13,14).toInt();
  DS1302Buffer.Hour=command.substring(15,17).toInt();
  DS1302Buffer.Minute=command.substring(18).toInt();
  DS1302_SetTime( DS1302_YEAR , DS1302Buffer.Year );
  DS1302_SetTime( DS1302_MONTH , DS1302Buffer.Month );
  DS1302_SetTime( DS1302_DAY , DS1302Buffer.Day );
  DS1302_SetTime( DS1302_WEEK , DS1302Buffer.Week );
  DS1302_SetTime( DS1302_HOUR , DS1302Buffer.Hour );
  DS1302_SetTime( DS1302_MINUTE , DS1302Buffer.Minute );
  DS1302_ON_OFF(1);
  Always=false;
  Serial.println("Set Done");
  Display_RTCC();   
}

//蜂鸣器报警函数
void buzz(int &times)
{
  for(int i=0;i<times;i++){
    digitalWrite(Buzz_Pin,HIGH);
    delay(650);
    digitalWrite(Buzz_Pin,LOW);
    delay(250);
    }
}

//帮助内容
void help()
{
  Serial.println("************************************* HELP *****************************************");
  Serial.println("Edited By Starky");
  Serial.println("Type \"set YY MM DD WEEK HH MM\" To Set The Time!");
  Serial.println("Such As Type \"set 08 08 08 1 12 00\" To Set The Time As 2008-8-8 Monday 12:00");
  Serial.println("Type \"show\" To Display The Time Now!");
  Serial.println("Type \"always\" To Print The Time Every Second!");
  Serial.println("Type \"alarm\" To Check The Current Alarm");
  Serial.println("Welcome To Use!"); 
  Serial.println("************************************* HELP *****************************************");
}

void loop()
{
  Scan_Input();
  DS1302_GetTime(&DS1302Buffer);        //获取当前RTCC值
  if(Always)
  {
    if(Flag_Time_Refresh == 1)
      {
          Flag_Time_Refresh = 0;
          Display_RTCC();
      }
  }
  
  // 闹钟激活
  if(DS1302Buffer.Hour==Alarm_Hour && DS1302Buffer.Minute==Alarm_Minute && DS1302Buffer.Second==0)
  {
    int times=15;        // 报警次数
    buzz(times);
  }
}

以下是库文件内容

DS1302.cpp

/******************************************************************************
----------------1.开发环境:Arduino IDE-----------------------------------------
----------------2.测试使用开发板型号:Arduino UNO R3-------
----------------3.单片机使用晶振:16M------------------------------------------
----------------4.作者:神秘藏宝室---------------------------------------------
******************************************************************************/
#include "DS1302.h"

SYSTEMTIME DS1302Buffer;
bool Flag_Time_Refresh = 1;

//****************************************************
//实时时钟写入一字节(内部函数)
//****************************************************
void DS1302_InputByte(unsigned char dat)    
{ 
    unsigned char i;

    pinMode(DS1302_IO,OUTPUT);

    for(i=0; i<8; i++)
    {
        if((dat & 0x01) == 1)
        {
            DS1302_IO_1;
        }
        else
        {
            DS1302_IO_0;
        }
          
        
        DS1302_CLK_0;               //上升沿写入数据
        
        delayMicroseconds(2);
        
        DS1302_CLK_1;
        
        delayMicroseconds(2);
        dat >>= 1; 
    } 
}

//****************************************************
//实时时钟读取一字节(内部函数)
//****************************************************
unsigned char DS1302_OutputByte(void)   
{ 
    unsigned char i;
    unsigned char dat;
    pinMode(DS1302_IO,INPUT);
    for(i=0; i<8; i++)
    {
        DS1302_CLK_1;                   //下降沿读出数据
        delayMicroseconds(2);
        DS1302_CLK_0;
        delayMicroseconds(2);
        dat >>= 1;                  
        if( digitalRead(DS1302_IO) == HIGH )
            dat |= 0x80;                //最高位置一
        else
            dat &= 0x7F;                //最高位清零       
    } 
    return(dat); 
}

//****************************************************
//ucAddr: DS1302地址, ucData: 要写的数据
//****************************************************
void DS1302_Write(unsigned char ucAddr, unsigned char ucDa) 
{
    DS1302_RST_0;
    delayMicroseconds(2);
    DS1302_CLK_0;
    delayMicroseconds(2);
    DS1302_RST_1;
    delayMicroseconds(2);
    DS1302_InputByte(ucAddr);           // 地址,命令 
    DS1302_InputByte(ucDa);             // 写1Byte数据
    DS1302_CLK_1;
    delayMicroseconds(2);
    DS1302_RST_0;
    delayMicroseconds(2);
}

//****************************************************
//读取DS1302某地址的数据
//****************************************************
unsigned char DS1302_Read(unsigned char ucAddr) 
{
    unsigned char ucData;
    DS1302_RST_0;
    delayMicroseconds(2);
    DS1302_CLK_0;
    delayMicroseconds(2);
    DS1302_RST_1;
    delayMicroseconds(2);
    DS1302_InputByte(ucAddr|0x01);        // 地址,命令 
    ucData = DS1302_OutputByte();         // 读1Byte数据
    DS1302_CLK_1;
    delayMicroseconds(2);
    DS1302_RST_0;
    delayMicroseconds(2);
    return(ucData);
}

//****************************************************
//是否写保护
//****************************************************
void DS1302_SetProtect(unsigned char flag)       
{
    if(flag)
        DS1302_Write(0x8E,0x10);            //保护
    else
        DS1302_Write(0x8E,0x00);            //不保护
} 

//****************************************************
// 设置时间函数
//****************************************************
void DS1302_SetTime(unsigned char Address, unsigned char Value)        
{
    DS1302_SetProtect(0);
    DS1302_Write(Address, ((Value/10)<<4 | (Value%10))); 
}

//****************************************************
//获取实时时间
//****************************************************
void DS1302_GetTime(SYSTEMTIME *Time)
{
    unsigned char ReadValue;
    ReadValue = DS1302_Read(DS1302_SECOND);
    ReadValue = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);            //BCD码转换十进制
    if(ReadValue != DS1302Buffer.Second)                                //跟上一次状态不同,置位刷新标志位
        Flag_Time_Refresh = 1;
    Time->Second = ReadValue;

    ReadValue = DS1302_Read(DS1302_MINUTE);
    Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
    ReadValue = DS1302_Read(DS1302_HOUR);
    Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
    ReadValue = DS1302_Read(DS1302_DAY);
    Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);    
    ReadValue = DS1302_Read(DS1302_WEEK);
    Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
    ReadValue = DS1302_Read(DS1302_MONTH);
    Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
    ReadValue = DS1302_Read(DS1302_YEAR);
    Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);   
}

//****************************************************
//初始化
//****************************************************
void DS1302_Init(void)
{
    unsigned char Second;

    pinMode(DS1302_RST,OUTPUT);
    pinMode(DS1302_IO,OUTPUT);
    pinMode(DS1302_CLK,OUTPUT);

    Second = DS1302_Read(DS1302_SECOND);
    if(Second&0x80)       
        DS1302_SetTime(DS1302_SECOND,Second & 0x7f);    //开启振荡    
}
//****************************************************
//DS1302振荡器停止
//****************************************************
void DS1302_ON_OFF(bool FLAG_ON_OFF)
{
    unsigned char Second;
    Second = DS1302_Read(DS1302_SECOND);
    if(FLAG_ON_OFF == 0)
        DS1302_Write(DS1302_SECOND,Second | 0x80);              //关闭振荡
    else
        DS1302_Write(DS1302_SECOND,Second & 0x7f);              //开启振荡
}

DS1302.h

/******************************************************************************
----------------1.开发环境:Arduino IDE-----------------------------------------
----------------2.测试使用开发板型号:Arduino Leonardo or Arduino UNO R3-------
----------------3.单片机使用晶振:16M------------------------------------------
----------------4.作者:神秘藏宝室---------------------------------------------
******************************************************************************/
#ifndef __DS1302_H__
#define __DS1302_H__

#include <Arduino.h>

//DS1302 IO设置
#define DS1302_RST 2     //实时时钟复位线引脚
#define DS1302_IO 3      //实时时钟数据线引脚
#define DS1302_CLK 4     //实时时钟时钟线引脚


#define DS1302_RST_0 digitalWrite(DS1302_RST,LOW)
#define DS1302_RST_1 digitalWrite(DS1302_RST,HIGH)

#define DS1302_IO_0 digitalWrite(DS1302_IO,LOW)
#define DS1302_IO_1 digitalWrite(DS1302_IO,HIGH)

#define DS1302_CLK_0 digitalWrite(DS1302_CLK,LOW)
#define DS1302_CLK_1 digitalWrite(DS1302_CLK,HIGH)


//宏定义
#define DS1302_SECOND   0x80
#define DS1302_MINUTE   0x82
#define DS1302_HOUR     0x84 
#define DS1302_DAY      0x86
#define DS1302_MONTH    0x88
#define DS1302_WEEK     0x8a
#define DS1302_YEAR     0x8c 


typedef struct __SYSTEMTIME__
{
    unsigned char Second;
    unsigned char Minute;
    unsigned char Hour;
    unsigned char Week;
    unsigned char Day;
    unsigned char Month;
    unsigned char  Year;
}SYSTEMTIME;    //定义的时间类型


//函数或者变量声明
extern void DS1302_InputByte(unsigned char dat);
extern unsigned char DS1302_OutputByte(void) ;
extern void DS1302_Write(unsigned char ucAddr, unsigned char ucDa);
extern unsigned char DS1302_Read(unsigned char ucAddr);
extern void DS1302_SetProtect(unsigned char flag) ;
extern void DS1302_SetTime(unsigned char Address, unsigned char Value);
extern void DS1302_GetTime(SYSTEMTIME *Time);
extern void DS1302_Init(void);
extern void DS1302_ON_OFF(bool FLAG_ON_OFF);


extern SYSTEMTIME DS1302Buffer;
extern bool Flag_Time_Refresh;

#endif

三个文件放一起上传就好了。至于都是些什么东西,你看看代码就知道了。
那么多,实在懒得说。(又何况我也不太懂?)

All Done!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容