迷恋各种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; } }
调时间说明:打开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/