迷恋各种arduino的电子钟,这次是一个基于1602显示加DS3231时钟模块的版本。
硬件:
Arduino UNO(特殊版带1602接口)一块
LCD1602显示模块一个
DS3231模块一个
杜邦线若干
接线:
1602:
因为板子特殊,留有直插口所以直接插上就行了。
板子如下:
通过原理图查询得知它的接口就是自带1602库里面的标准接口,直接用就行,不用改引脚。
附上电路图,方便查阅:
DS3231:
VCC —— VCC
GND —— GND
SCL —— SCL/A5
SDA —— SDA/A4
显示代码:
#include <Wire.h>
#include "ds3231_2.h"
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define BUFF_MAX 128
uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;
void setup()
{
Serial.begin(9600);
Wire.begin();
DS3231_init(DS3231_INTCN);
memset(recv, 0, BUFF_MAX);
Serial.println("GET time");
lcd.begin(16, 2);
lcd.clear();
Serial.println("Setting time");
//parse_cmd("T302911604102014",16);
}
void loop()
{
char in;
char tempF[6];
float temperature;
char buff[BUFF_MAX];
unsigned long now = millis();
struct ts t;
// show time once in a while
if ((now - prev > interval) && (Serial.available() <= 0)) {
DS3231_get(&t); //Get time
parse_cmd("C",1);
temperature = DS3231_get_treg(); //Get temperature
dtostrf(temperature, 5, 1, tempF);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(t.mday);
printMonth(t.mon);
lcd.print(t.year);
lcd.setCursor(0,1); //Go to second line of the LCD Screen
lcd.print(t.hour);
lcd.print(":");
if(t.min<10)
{
lcd.print("0");
}
lcd.print(t.min);
lcd.print(":");
if(t.sec<10)
{
lcd.print("0");
}
lcd.print(t.sec);
lcd.print(' ');
lcd.print(tempF);
lcd.print((char)223);
lcd.print("C ");
prev = now;
}
if (Serial.available() > 0) {
in = Serial.read();
if ((in == 10 || in == 13) && (recv_size > 0)) {
parse_cmd(recv, recv_size);
recv_size = 0;
recv[0] = 0;
} else if (in < 48 || in > 122) {; // ignore ~[0-9A-Za-z]
} else if (recv_size > BUFF_MAX - 2) { // drop lines that are too long
// drop
recv_size = 0;
recv[0] = 0;
} else if (recv_size < BUFF_MAX - 2) {
recv[recv_size] = in;
recv[recv_size + 1] = 0;
recv_size += 1;
}
}
}
void parse_cmd(char *cmd, int cmdsize)
{
uint8_t i;
uint8_t reg_val;
char buff[BUFF_MAX];
struct ts t;
//snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
//Serial.print(buff);
// TssmmhhWDDMMYYYY aka set time
if (cmd[0] == 84 && cmdsize == 16) {
//T355720619112011
t.sec = inp2toi(cmd, 1);
t.min = inp2toi(cmd, 3);
t.hour = inp2toi(cmd, 5);
t.wday = inp2toi(cmd, 7);
t.mday = inp2toi(cmd, 8);
t.mon = inp2toi(cmd, 10);
t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
DS3231_set(t);
Serial.println("OK");
} else if (cmd[0] == 49 && cmdsize == 1) { // "1" get alarm 1
DS3231_get_a1(&buff[0], 59);
Serial.println(buff);
} else if (cmd[0] == 50 && cmdsize == 1) { // "2" get alarm 1
DS3231_get_a2(&buff[0], 59);
Serial.println(buff);
} else if (cmd[0] == 51 && cmdsize == 1) { // "3" get aging register
Serial.print("aging reg is ");
Serial.println(DS3231_get_aging(), DEC);
} else if (cmd[0] == 65 && cmdsize == 9) { // "A" set alarm 1
DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
//ASSMMHHDD
for (i = 0; i < 4; i++) {
time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
}
byte flags[5] = { 0, 0, 0, 0, 0 };
DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
DS3231_get_a1(&buff[0], 59);
Serial.println(buff);
} else if (cmd[0] == 66 && cmdsize == 7) { // "B" Set Alarm 2
DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
//BMMHHDD
for (i = 0; i < 4; i++) {
time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
}
byte flags[5] = { 0, 0, 0, 0 };
DS3231_set_a2(time[0], time[1], time[2], flags);
DS3231_get_a2(&buff[0], 59);
Serial.println(buff);
} else if (cmd[0] == 67 && cmdsize == 1) { // "C" - get temperature register
Serial.print("temperature reg is ");
Serial.println(DS3231_get_treg(), DEC);
} else if (cmd[0] == 68 && cmdsize == 1) { // "D" - reset status register alarm flags
reg_val = DS3231_get_sreg();
reg_val &= B11111100;
DS3231_set_sreg(reg_val);
} else if (cmd[0] == 70 && cmdsize == 1) { // "F" - custom fct
reg_val = DS3231_get_addr(0x5);
Serial.print("orig ");
Serial.print(reg_val,DEC);
Serial.print("month is ");
Serial.println(bcdtodec(reg_val & 0x1F),DEC);
} else if (cmd[0] == 71 && cmdsize == 1) { // "G" - set aging status register
DS3231_set_aging(0);
} else if (cmd[0] == 83 && cmdsize == 1) { // "S" - get status register
Serial.print("status reg is ");
Serial.println(DS3231_get_sreg(), DEC);
} else {
Serial.print("unknown command prefix ");
Serial.println(cmd[0]);
Serial.println(cmd[0], DEC);
}
}
void printMonth(int month)
{
switch(month)
{
case 1: lcd.print(" January ");break;
case 2: lcd.print(" February ");break;
case 3: lcd.print(" March ");break;
case 4: lcd.print(" April ");break;
case 5: lcd.print(" May ");break;
case 6: lcd.print(" June ");break;
case 7: lcd.print(" July ");break;
case 8: lcd.print(" August ");break;
case 9: lcd.print(" September ");break;
case 10: lcd.print(" October ");break;
case 11: lcd.print(" November ");break;
case 12: lcd.print(" December ");break;
default: lcd.print(" Error ");break;
}
}
用到的库文件:https://github.com/rodan/ds3231
串口调时间代码:
#include <DS3231test.h>
#include <Wire.h>
DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
int year, month, date, DoW,week , hour, minute, second,temperature;
String comdata = "";
int numdata[7] = {0}, mark = 0;
void setup (void)
{
Serial.begin(9600);
//Wire.begin();
Serial.println("set_time :");
Serial.println("year mouth day week hour minute second");
Serial.println();
Serial.println("week : 1 -> Sunday; 2 -> Monday; 3 -> Tuesday: ....7 -> Saturday");
Serial.println();
Serial.println("for example :2014-5-20 Tue 0:33:30 ");
Serial.println("set_time :");
Serial.println("14 5 20 3 0 33 30");
Serial.println();
}
void set_time() //DS3231设置时间
{
Wire.begin();
Clock.setSecond(numdata[6]); //秒
Clock.setMinute(numdata[5]); //分
Clock.setHour(numdata[4]); //时
Clock.setDoW(numdata[3]); //周
Clock.setDate(numdata[2]); //日
Clock.setMonth(numdata[1]); //月
Clock.setYear(numdata[0]); //年
}
void loop (void)
{
int j = 0;
while (Serial.available() > 0) //检测串口是否有数据
{
comdata += char(Serial.read());
delay(2);
mark = 1;
}
if(mark == 1)
{
Serial.println(comdata); //串口打印检测到的数据
for(int i = 0; i < comdata.length() ; i++)
{
if(comdata[i] == ' ')
{
j++;
}
else
{
numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
}
}
comdata = String("");
Serial.print("set_time... ");
set_time();
Serial.println(" OK ");
for(int i = 0; i < 7; i++)
{
numdata[i] = 0;
}
mark = 0;
}
}
用到的库文件:http://image.geek-workshop.com/forum/201405/20/131459ouvueuv08gph0uqh.rar?_upd=DS3231.rar(注意库文件的重命名,两个都是,.h和.cpp都要修改,.cpp里还要修改对应的.h名称)
调时间说明:打开arduino 串口监视器
输入要设定日期以及时间
格式为(年+空格+月+空格+日+空格+星期+空格+时+空格+分+空格+秒)
设置中星期:01对应星期天;02对应星期一;03对应星期二;……07对应星期六
例如:现在是 2014年5月20日 星期二 13:35:00
那么在串口数据发送栏中输入 : 14 05 20 03 13 35 00
先烧录调时间的代码,完成后再烧录显示代码即可。
效果图:
参考链接:
http://www.geek-workshop.com/thread-9841-1-1.html
http://educ8s.tv/arduino-project-real-time-clock-with-ds3231-module/






发表评论: