转自:@小五义
常常听到老妈在做饭时说“开锅分钟后叫我一下”,为何不做个定时器,来提醒老妈呢?结合前面学习的知识,再加上时间模块,我决定自己做一个。
一、本次实验所需器材
1、Arduino UNO板
2、1602LCD 屏幕
3、DS1302实时时钟模块:DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和 字节静态RAM ,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过 AM/PM 指示决定采用 或 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RST 复位(2)I/O 数据线(3)SCLK串行时钟。
DS1302主要性能指标
★ 实时时钟具有能计算 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力
★ 位暂存数据存储RAM
★ 串行 I/O 口方式使得管脚数量最少
★ 宽范围工作电压.5V
★ 工作电流 2.0V 时,小于300nA
★ 读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式
★ 8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配
★ 简单 3 线接口
★ 与 TTL 兼容Vcc=5V
★ 可选工业级温度范围- +
★ 双电源管用于主电源和备份电源供应
接线方法(以本实验程序为例)
VCC→+5V/3.3V
GND→GND
CLK→5
DAT→3
RST→2
4、按钮开关一个:按钮开关在连接时,需要接一个1KΩ电阻做为下拉电阻。具体关于按钮的使用可参考(
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=)
5、蜂鸣器一个
6、电阻:1KΩ电阻、10KΩ电阻
二、硬件连接方法
DS1602 的连接主要采用四位连接法。端口为,,9,8,7,6。DS1302 的连接方法上面已给出,另外按钮开关、蜂鸣器等的连接具体见下图。
三、程序代码
具体代码如下:
// DS1302: RST pin -> Arduino Digital 2
// DAT pin -> Arduino Digital 3
// CLK pin -> Arduino Digital 5
#include
#include
LiquidCrystal lcd(, , 9, 8, 7, 6);
DS1302 rtc(2, 3, 5);
int j=0;//记录定时设定分钟数
int time=0;//remine the last time
int button=;//口控制按钮
boolean onoff= LOW; //记录按钮状态
boolean timefix=LOW;//记时器开关,LOW表示未定时,HIGH表示定时
unsigned long buttonHoldTime = 0;//按钮按下持续时间
int buttonStateOld;//按钮上一时刻状态
int buttonState;//按钮本时刻状态
void ting()//控制蜂鸣器发声
{
int checkstate = digitalRead(button);
for(int i=0;i<;i++)//输出一个频率的声音
{
digitalWrite(,HIGH);//发声音
delay(1);//延时1ms
digitalWrite(,LOW);//不发声音
delay(1);//延时ms
}
for(int i=0;i<;i++)//输出另一个频率的声音,这里的与前面的一样,用来控制频率,可以自己调节
{
digitalWrite(,HIGH);
delay(2);
digitalWrite(,LOW);
delay(2);
}
}
void clockdate()//显示时间
{
lcd.clear(); //清屏
lcd.setCursor(0,0);
lcd.print(rtc.getDateStr(FORMAT_LONG,FORMAT_BIGENDIAN, '-'));//从的库文件可以看出,这里有下面几种格式FORMAT_BIGENDIAN:;FORMAT_LITTLEENDIAN:
lcd.setCursor(,0);
lcd.print(rtc.getDOWStr());
lcd.setCursor(,0);
lcd.print(" ");
lcd.setCursor(0, 1) ;
lcd.print(rtc.getTimeStr());
}
void setup()
{
lcd.begin(, 2); //初始化LCD
pinMode(,OUTPUT);//设置数字IO脚模式,OUTPUT为输出
pinMode(button,INPUT);//设置引脚为输入模式
// 设置时钟初始值
rtc.halt(false);
rtc.writeProtect(false);
rtc.setDOW(SATURDAY); // 设置星期
rtc.setTime(, ,); //设置时间
rtc.setDate(9, , ); // 设置日期年月9日
rtc.writeProtect(true);
}
void loop()
{
buttonState = digitalRead(button);
delay();
if (buttonState==HIGH && buttonStateOld==LOW)//按钮状态发生变化
{
buttonHoldTime = millis();//用millis()时间函数来记时,该函数最长记录时间为9小时分,由于本程序最多记录分钟,所以可以使用
buttonStateOld =buttonState;
if (onoff==HIGH)//当进入定时设置状态时
{
if (j>)
{
j=0;
timefix=LOW;
}
else
{
j=j+1;
timefix=HIGH;
}
lcd.setCursor(,0);
lcd.print(j);
}
}
else if (buttonState ==HIGH && buttonStateOld==HIGH)//判断按钮是否持续按下
{
if (millis()-buttonHoldTime>)//当按钮持续按下3秒种进入定时状态
{
buttonStateOld=LOW;
if (onoff==LOW)//进入
{
j=0;
timefix=LOW;
lcd.clear(); //清屏
lcd.setCursor(0,0);
lcd.print("Fixed Time:");
lcd.setCursor(,0);
lcd.print(j);
lcd.setCursor(,0);
lcd.print("min");
onoff=HIGH;
}
else//退出
{
clockdate();
// Serial.println(rtc.getTimeStr());
buttonHoldTime = millis();
onoff= LOW;
}
}
else
{
buttonStateOld =buttonState;
}
}
else
{
buttonStateOld =buttonState;
}
if (onoff==LOW)
{
clockdate();
}
if (timefix==HIGH && j>0 && onoff==LOW)
{
unsigned long delaytime=j*;//把分钟计算成秒
if ((millis()-buttonHoldTime)>=delaytime )
{
do
{
buttonState = digitalRead(button);
ting();
}while (buttonState==LOW);//当按下按钮后,停止蜂鸣
j=0;
}
else
{
clockdate();
}
}
delay);
}
这个代码中,初始时间是设定好的,即年月9日点分,因此本程序没有加入时钟时间设定功能,也可以再加上几个按钮,加上时间调节功能。另外在判断按钮按下时间这里,本程序的方法自我感觉有时笨,但也没想出更好的方法,哪位有更好的方法,请给指导一下,谢谢。
四、实现效果
实现过程中,发现存在两个问题,一个是按钮不是很灵敏,另一个是最后再退出调时状态时,长按3秒,时间会增加1分钟。如原本设定分钟,退出时长按3秒会依然会变成分钟。