呃,说点什么呢?
没啥好说的,很基础的东西。也是多年前某宝买了来,一直丢在角落里。还能找点儿空闲,就想让它们也动一动。
免得怪我遗忘了它们。
时钟模块用的是 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 ×)
{
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
三个文件放一起上传就好了。至于都是些什么东西,你看看代码就知道了。
那么多,实在懒得说。(又何况我也不太懂?)