Arduino Tiny RTC I2C Module
最近在學習Arduino和RTC的使用,看了葉難先生寫的「輕鬆入門Arduino範例分析與實作設計」一書,其中提到DS1307即時時鐘晶片的使用。就很有興趣的想買一顆來試試,到ICSHOP網站一看,哇!一顆要79塊台幣。這這也不算便宜,而且還要買石英晶體和其他小零件,特別是要一個CR2032電池座,還要把這些東西焊在一起。想想自己手藝不精,眼力也不行了,只怕這些零件到時玩過就散在一邊,浪費了。
沒想到,看到他們也賣另一個[DS1307時鐘模組],而且只要60塊台幣,內含DS1307晶片、石英晶體、CR2032電池座等,還都焊的好好的。
那就先來試試了。
貨到了,看了一下電路圖和文件。哈,除了DS1307外,還有一顆24C32 32K I2C EEPROM,還留了3個接點給DS18B20溫度感測器。太多東西可以玩了,當下不知由那裡玩起啊。
先Google一下好了,果然有一大堆的資料。首先由Matthew的Arduino RTC: TinyRTC v1 with Arduino Mega 2560開始看。
他說只要接Vcc, GND, SCL, SDA這四條線就好了。然後他不知由那裡找到的三支草稿碼:SetRTC,GetRTC,I2CScanner。首先用I2CScanner來找DS1307的位址,嗯,是0x68。
然後再用SetRTC這支來設定日期時間,嘔,要直接改程式才能設定哦!再來就是可以用GetRTC這支來讀取日期時間了。試了一下,沒問題,都可以正常運作的。而且,這三支都只用到內建的Wire程式庫。
可是第一個問題,就是要設定日期時間,還要改草稿碼,然後再上傳,實在有點不方便啊!
此時回頭看看葉難的書,發現他用的是另外的方法,是別的程式庫。不過葉先生寫的設定日期時間的程式很好用的,我就先直接把Matthew的草稿碼GetRTC改成可以設定日期時間。
跑起來的樣子,如下圖:
設定日期時間的方法和葉先生書上寫的一樣,在上圖上方的文字框內輸入y2017後,再按Enter就可以把年份設成2017。要設定月份就用M09之類,日期就用d01之類,小時就用h12之類,分鐘就用m20之類,秒數就用s30之類。
沒想到一個RTC就有這許多玩意可以玩,模組上還有24C32 晶片,放在那裡沒用到呢!下次有時間,再來研究了。
沒想到,看到他們也賣另一個[DS1307時鐘模組],而且只要60塊台幣,內含DS1307晶片、石英晶體、CR2032電池座等,還都焊的好好的。
那就先來試試了。
貨到了,看了一下電路圖和文件。哈,除了DS1307外,還有一顆24C32 32K I2C EEPROM,還留了3個接點給DS18B20溫度感測器。太多東西可以玩了,當下不知由那裡玩起啊。
先Google一下好了,果然有一大堆的資料。首先由Matthew的Arduino RTC: TinyRTC v1 with Arduino Mega 2560開始看。
他說只要接Vcc, GND, SCL, SDA這四條線就好了。然後他不知由那裡找到的三支草稿碼:SetRTC,GetRTC,I2CScanner。首先用I2CScanner來找DS1307的位址,嗯,是0x68。
然後再用SetRTC這支來設定日期時間,嘔,要直接改程式才能設定哦!再來就是可以用GetRTC這支來讀取日期時間了。試了一下,沒問題,都可以正常運作的。而且,這三支都只用到內建的Wire程式庫。
可是第一個問題,就是要設定日期時間,還要改草稿碼,然後再上傳,實在有點不方便啊!
此時回頭看看葉難的書,發現他用的是另外的方法,是別的程式庫。不過葉先生寫的設定日期時間的程式很好用的,我就先直接把Matthew的草稿碼GetRTC改成可以設定日期時間。
/* Downloaded from http://projectsfromtech.blogspot.com/
*Connect SCL, SDA, Vcc, and GND
*Open Serial Monitor and enjoy!
*/
//Arduino 1.0+ Only
#include "Wire.h"
#define DS1307_ADDRESS 0x68
void setDateTime(byte second, byte minute, byte hour,
byte weekDay, byte monthDay, byte month, byte year);
void setup(){
Wire.begin();
Serial.begin(9600);
}
void loop(){
printDate();
delay(1000);
}
void pf(const char *fmt, ...) {
char tmp[128]; // max 128 chars
va_list args;
va_start(args, fmt);
vsnprintf(tmp, 128, fmt, args);
va_end(args);
Serial.print(tmp);
}
byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
void printDate(){
// Reset the register pointer
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.read());
int minute = bcdToDec(Wire.read());
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
int monthDay = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());
//print the date EG 3/1/11 23:59:59
Serial.print(month);
Serial.print("/");
Serial.print(monthDay);
Serial.print("/");
Serial.print(year);
Serial.print(" ");
Serial.print(hour);
Serial.print(":");
Serial.print(minute);
Serial.print(":");
Serial.println(second);
}
void serialEvent()
{
int type = Serial.read();
int v = 0;
int temp;
while ((temp = Serial.read()) > '0' - 1) {
pf("temp - 0 : %d\n", temp - '0');
v = v * 10 + (temp - '0');
pf("v : %d\n", v);
}
pf("type: %c\n", type);
pf("v : %d\n", v);
// -------------------------------
// Reset the register pointer
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
byte s = bcdToDec(Wire.read());
byte m = bcdToDec(Wire.read());
byte h = bcdToDec(Wire.read() & 0b111111); //24 hour time
byte weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
byte d = bcdToDec(Wire.read());
byte M = bcdToDec(Wire.read());
byte y = bcdToDec(Wire.read());
switch(type) {
case 'y':
y = v - 2000;
break;
case 'M':
M = v;
break;
case 'd':
d = v;
break;
case 'h':
h = v;
break;
case 'm':
m = v;
break;
case 's':
s = v;
break;
default:
Serial.println("Wrong\n");
break;
}
setDateTime(s, m, h, weekDay, d, M, y);
}
void setDateTime(byte second, byte minute, byte hour,
byte weekDay, byte monthDay, byte month, byte year) {
byte zero = 0x00;
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); //stop Oscillator
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekDay));
Wire.write(decToBcd(monthDay));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(zero); //start
Wire.endTransmission();
}
跑起來的樣子,如下圖:
設定日期時間的方法和葉先生書上寫的一樣,在上圖上方的文字框內輸入y2017後,再按Enter就可以把年份設成2017。要設定月份就用M09之類,日期就用d01之類,小時就用h12之類,分鐘就用m20之類,秒數就用s30之類。
沒想到一個RTC就有這許多玩意可以玩,模組上還有24C32 晶片,放在那裡沒用到呢!下次有時間,再來研究了。

留言