Realtime clock library for DS1307 and DS3231m
Dependents: vfd_modular_clock_mbed
ds3231m.cpp@2:6119507e6713, 2015-08-10 (annotated)
- Committer:
- perjg
- Date:
- Mon Aug 10 03:16:52 2015 +0000
- Revision:
- 2:6119507e6713
- Parent:
- 1:3fe5649f1e02
Fixed compile error
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Backstrom | 0:1602fdac44ec | 1 | /* |
Backstrom | 0:1602fdac44ec | 2 | * RTC library - mbed |
Backstrom | 0:1602fdac44ec | 3 | * (C) 2011-15 Akafugu Corporation |
Backstrom | 0:1602fdac44ec | 4 | * |
Backstrom | 0:1602fdac44ec | 5 | * This program is free software; you can redistribute it and/or modify it under the |
Backstrom | 0:1602fdac44ec | 6 | * terms of the GNU General Public License as published by the Free Software |
Backstrom | 0:1602fdac44ec | 7 | * Foundation; either version 2 of the License, or (at your option) any later |
Backstrom | 0:1602fdac44ec | 8 | * version. |
Backstrom | 0:1602fdac44ec | 9 | * |
Backstrom | 0:1602fdac44ec | 10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY |
Backstrom | 0:1602fdac44ec | 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
Backstrom | 0:1602fdac44ec | 12 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. |
Backstrom | 0:1602fdac44ec | 13 | * |
Backstrom | 0:1602fdac44ec | 14 | */ |
Backstrom | 0:1602fdac44ec | 15 | |
Backstrom | 0:1602fdac44ec | 16 | #include "ds3231m.h" |
Backstrom | 0:1602fdac44ec | 17 | |
Backstrom | 0:1602fdac44ec | 18 | #define DS3231M_SLAVE_ADDR 0xD0 |
Backstrom | 0:1602fdac44ec | 19 | |
Backstrom | 0:1602fdac44ec | 20 | DS3231M::DS3231M(I2C& i2c) |
Backstrom | 0:1602fdac44ec | 21 | : RTC() |
Backstrom | 0:1602fdac44ec | 22 | , m_i2c(i2c) |
Backstrom | 0:1602fdac44ec | 23 | { |
Backstrom | 0:1602fdac44ec | 24 | m_i2c.frequency(100000); |
Backstrom | 0:1602fdac44ec | 25 | } |
Backstrom | 0:1602fdac44ec | 26 | |
Backstrom | 0:1602fdac44ec | 27 | void DS3231M::begin() |
Backstrom | 0:1602fdac44ec | 28 | { |
Backstrom | 0:1602fdac44ec | 29 | } |
Backstrom | 0:1602fdac44ec | 30 | |
Backstrom | 0:1602fdac44ec | 31 | time_t DS3231M::time() |
Backstrom | 0:1602fdac44ec | 32 | { |
Backstrom | 0:1602fdac44ec | 33 | return m_time; |
Backstrom | 0:1602fdac44ec | 34 | } |
Backstrom | 0:1602fdac44ec | 35 | |
Backstrom | 0:1602fdac44ec | 36 | struct tm* DS3231M::getTime() |
Backstrom | 0:1602fdac44ec | 37 | { |
Backstrom | 0:1602fdac44ec | 38 | char rtc[7]; |
Backstrom | 0:1602fdac44ec | 39 | |
Backstrom | 0:1602fdac44ec | 40 | rtc[0] = 0; // second register, 0 |
Backstrom | 0:1602fdac44ec | 41 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); |
Backstrom | 0:1602fdac44ec | 42 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 7); |
Backstrom | 0:1602fdac44ec | 43 | |
Backstrom | 0:1602fdac44ec | 44 | // Clear clock halt bit from read data |
Backstrom | 0:1602fdac44ec | 45 | //rtc[0] &= ~(_BV(CH_BIT)); |
Backstrom | 0:1602fdac44ec | 46 | |
Backstrom | 0:1602fdac44ec | 47 | m_tm.tm_sec = bcd2dec(rtc[0]); |
Backstrom | 0:1602fdac44ec | 48 | m_tm.tm_min = bcd2dec(rtc[1]); |
Backstrom | 0:1602fdac44ec | 49 | m_tm.tm_hour = bcd2dec(rtc[2]); |
Backstrom | 0:1602fdac44ec | 50 | m_tm.tm_wday = bcd2dec(rtc[3])-1; |
Backstrom | 0:1602fdac44ec | 51 | m_tm.tm_mday = bcd2dec(rtc[4]); |
Backstrom | 0:1602fdac44ec | 52 | m_tm.tm_mon = bcd2dec(rtc[5])-1; // tm_mon is 0-11 |
Backstrom | 0:1602fdac44ec | 53 | m_tm.tm_year = bcd2dec(rtc[6]); |
Backstrom | 0:1602fdac44ec | 54 | |
Backstrom | 0:1602fdac44ec | 55 | return &m_tm; |
Backstrom | 0:1602fdac44ec | 56 | } |
Backstrom | 0:1602fdac44ec | 57 | |
Backstrom | 0:1602fdac44ec | 58 | void DS3231M::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) |
Backstrom | 0:1602fdac44ec | 59 | { |
Backstrom | 0:1602fdac44ec | 60 | char rtc[3]; |
Backstrom | 0:1602fdac44ec | 61 | |
Backstrom | 0:1602fdac44ec | 62 | rtc[0] = 0; // second register, 0 |
Backstrom | 0:1602fdac44ec | 63 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); |
Backstrom | 0:1602fdac44ec | 64 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 3); |
Backstrom | 0:1602fdac44ec | 65 | |
Backstrom | 0:1602fdac44ec | 66 | // Clear clock halt bit from read data |
Backstrom | 0:1602fdac44ec | 67 | //rtc[0] &= ~(_BV(CH_BIT)); |
Backstrom | 0:1602fdac44ec | 68 | |
Backstrom | 0:1602fdac44ec | 69 | if (sec) *sec = bcd2dec(rtc[0]); |
Backstrom | 0:1602fdac44ec | 70 | if (min) *min = bcd2dec(rtc[1]); |
Backstrom | 0:1602fdac44ec | 71 | if (hour) *hour = bcd2dec(rtc[2]); |
Backstrom | 0:1602fdac44ec | 72 | } |
Backstrom | 0:1602fdac44ec | 73 | |
Backstrom | 0:1602fdac44ec | 74 | void DS3231M::setTime(time_t t) |
Backstrom | 0:1602fdac44ec | 75 | { |
Backstrom | 0:1602fdac44ec | 76 | struct tm * timeinfo; |
Backstrom | 0:1602fdac44ec | 77 | timeinfo = localtime (&t); |
Backstrom | 0:1602fdac44ec | 78 | setTime(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
Backstrom | 0:1602fdac44ec | 79 | } |
Backstrom | 0:1602fdac44ec | 80 | |
Backstrom | 0:1602fdac44ec | 81 | void DS3231M::setTime(uint8_t hour, uint8_t min, uint8_t sec) |
Backstrom | 0:1602fdac44ec | 82 | { |
Backstrom | 0:1602fdac44ec | 83 | write_byte(dec2bcd(sec), 0); |
Backstrom | 0:1602fdac44ec | 84 | write_byte(dec2bcd(min), 1); |
Backstrom | 0:1602fdac44ec | 85 | write_byte(dec2bcd(hour), 2); |
Backstrom | 0:1602fdac44ec | 86 | } |
Backstrom | 0:1602fdac44ec | 87 | |
Backstrom | 0:1602fdac44ec | 88 | void DS3231M::setTime(struct tm* tm) |
Backstrom | 0:1602fdac44ec | 89 | { |
Backstrom | 0:1602fdac44ec | 90 | write_byte(dec2bcd(tm->tm_sec), 0); |
Backstrom | 0:1602fdac44ec | 91 | write_byte(dec2bcd(tm->tm_min), 1); |
Backstrom | 0:1602fdac44ec | 92 | write_byte(dec2bcd(tm->tm_hour), 2); |
Backstrom | 0:1602fdac44ec | 93 | write_byte(dec2bcd(tm->tm_wday+1), 3); |
Backstrom | 0:1602fdac44ec | 94 | write_byte(dec2bcd(tm->tm_mday), 4); |
Backstrom | 0:1602fdac44ec | 95 | write_byte(dec2bcd(tm->tm_mon+1), 5); |
Backstrom | 0:1602fdac44ec | 96 | write_byte(dec2bcd(tm->tm_year), 6); |
Backstrom | 0:1602fdac44ec | 97 | } |
Backstrom | 0:1602fdac44ec | 98 | |
Backstrom | 0:1602fdac44ec | 99 | void DS3231M::setAlarm(time_t t) |
Backstrom | 0:1602fdac44ec | 100 | { |
Backstrom | 0:1602fdac44ec | 101 | struct tm * timeinfo; |
Backstrom | 0:1602fdac44ec | 102 | timeinfo = localtime (&t); |
Backstrom | 0:1602fdac44ec | 103 | setAlarm(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
Backstrom | 0:1602fdac44ec | 104 | } |
Backstrom | 0:1602fdac44ec | 105 | |
Backstrom | 0:1602fdac44ec | 106 | void DS3231M::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) |
Backstrom | 0:1602fdac44ec | 107 | { |
Backstrom | 0:1602fdac44ec | 108 | /* |
Backstrom | 0:1602fdac44ec | 109 | * 07h: A1M1:0 Alarm 1 seconds |
Backstrom | 0:1602fdac44ec | 110 | * 08h: A1M2:0 Alarm 1 minutes |
Backstrom | 0:1602fdac44ec | 111 | * 09h: A1M3:0 Alarm 1 hour (bit6 is am/pm flag in 12h mode) |
Backstrom | 0:1602fdac44ec | 112 | * 0ah: A1M4:1 Alarm 1 day/date (bit6: 1 for day, 0 for date) |
Backstrom | 0:1602fdac44ec | 113 | * Sets alarm to fire when hour, minute and second matches |
Backstrom | 0:1602fdac44ec | 114 | */ |
Backstrom | 0:1602fdac44ec | 115 | write_byte(dec2bcd(sec), 0x07); // second |
Backstrom | 0:1602fdac44ec | 116 | write_byte(dec2bcd(min), 0x08); // minute |
Backstrom | 0:1602fdac44ec | 117 | write_byte(dec2bcd(hour), 0x09); // hour |
Backstrom | 0:1602fdac44ec | 118 | write_byte(0x81, 0x0a); // day (upper bit must be set) |
Backstrom | 0:1602fdac44ec | 119 | |
Backstrom | 0:1602fdac44ec | 120 | // clear alarm flag |
Backstrom | 0:1602fdac44ec | 121 | uint8_t val = read_byte(0x0f); |
Backstrom | 0:1602fdac44ec | 122 | write_byte(val & ~0x01, 0x0f); |
Backstrom | 0:1602fdac44ec | 123 | } |
Backstrom | 0:1602fdac44ec | 124 | |
Backstrom | 0:1602fdac44ec | 125 | |
Backstrom | 0:1602fdac44ec | 126 | struct tm* DS3231M::getAlarm(void) |
Backstrom | 0:1602fdac44ec | 127 | { |
Backstrom | 0:1602fdac44ec | 128 | struct tm * timeinfo = getTime(); |
Backstrom | 0:1602fdac44ec | 129 | uint8_t hour, min, sec; |
Backstrom | 0:1602fdac44ec | 130 | |
Backstrom | 0:1602fdac44ec | 131 | getAlarm(&hour, &min, &sec); |
Backstrom | 0:1602fdac44ec | 132 | timeinfo->tm_hour = hour; |
Backstrom | 0:1602fdac44ec | 133 | timeinfo->tm_min = min; |
Backstrom | 0:1602fdac44ec | 134 | timeinfo->tm_sec = sec; |
Backstrom | 0:1602fdac44ec | 135 | return timeinfo; |
Backstrom | 0:1602fdac44ec | 136 | } |
Backstrom | 0:1602fdac44ec | 137 | |
Backstrom | 0:1602fdac44ec | 138 | void DS3231M::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) |
Backstrom | 0:1602fdac44ec | 139 | { |
Backstrom | 0:1602fdac44ec | 140 | *sec = bcd2dec(read_byte(0x07) & ~0x80); |
Backstrom | 0:1602fdac44ec | 141 | *min = bcd2dec(read_byte(0x08) & ~0x80); |
Backstrom | 0:1602fdac44ec | 142 | *hour = bcd2dec(read_byte(0x09) & ~0x80); |
Backstrom | 0:1602fdac44ec | 143 | } |
Backstrom | 0:1602fdac44ec | 144 | |
Backstrom | 0:1602fdac44ec | 145 | bool DS3231M::checkAlarm(void) |
Backstrom | 0:1602fdac44ec | 146 | { |
Backstrom | 0:1602fdac44ec | 147 | // Alarm 1 flag (A1F) in bit 0 |
Backstrom | 0:1602fdac44ec | 148 | uint8_t val = read_byte(0x0f); |
Backstrom | 0:1602fdac44ec | 149 | |
Backstrom | 0:1602fdac44ec | 150 | // clear flag when set |
Backstrom | 0:1602fdac44ec | 151 | if (val & 1) |
Backstrom | 0:1602fdac44ec | 152 | write_byte(val & ~0x01, 0x0f); |
Backstrom | 0:1602fdac44ec | 153 | |
Backstrom | 0:1602fdac44ec | 154 | return val & 1 ? 1 : 0; |
Backstrom | 0:1602fdac44ec | 155 | } |
Backstrom | 0:1602fdac44ec | 156 | |
Backstrom | 0:1602fdac44ec | 157 | void DS3231M::SQWEnable(bool enable) |
Backstrom | 0:1602fdac44ec | 158 | { |
Backstrom | 0:1602fdac44ec | 159 | uint8_t control = read_byte(0x0E); // read control register |
Backstrom | 0:1602fdac44ec | 160 | if (enable) { |
Backstrom | 0:1602fdac44ec | 161 | control |= 0x40; // set BBSQW to 1 |
Backstrom | 0:1602fdac44ec | 162 | control &= ~0x04; // set INTCN to 0 |
Backstrom | 0:1602fdac44ec | 163 | } |
Backstrom | 0:1602fdac44ec | 164 | else { |
Backstrom | 0:1602fdac44ec | 165 | control &= ~0x40; // set BBSQW to 0 |
Backstrom | 0:1602fdac44ec | 166 | } |
Backstrom | 0:1602fdac44ec | 167 | // write control back |
Backstrom | 0:1602fdac44ec | 168 | write_byte(control, 0x0E); |
Backstrom | 0:1602fdac44ec | 169 | } |
Backstrom | 0:1602fdac44ec | 170 | |
Backstrom | 0:1602fdac44ec | 171 | void DS3231M::SQWSetFreq(enum RTC_SQW_FREQ freq) |
Backstrom | 0:1602fdac44ec | 172 | { |
Backstrom | 0:1602fdac44ec | 173 | uint8_t control = read_byte(0x0E); // read control register |
Backstrom | 0:1602fdac44ec | 174 | control &= ~0x18; // Set to 0 |
Backstrom | 0:1602fdac44ec | 175 | control |= (freq << 4); // Set freq bitmask |
Backstrom | 0:1602fdac44ec | 176 | |
Backstrom | 0:1602fdac44ec | 177 | // write control back |
Backstrom | 0:1602fdac44ec | 178 | write_byte(control, 0x0E); |
Backstrom | 0:1602fdac44ec | 179 | } |
Backstrom | 0:1602fdac44ec | 180 | |
Backstrom | 0:1602fdac44ec | 181 | void DS3231M::Osc32kHzEnable(bool enable) |
Backstrom | 0:1602fdac44ec | 182 | { |
Backstrom | 0:1602fdac44ec | 183 | uint8_t status = read_byte(0x0F); // read status |
Backstrom | 0:1602fdac44ec | 184 | |
Backstrom | 0:1602fdac44ec | 185 | if (enable) |
Backstrom | 0:1602fdac44ec | 186 | status |= 0x08; // set to 1 |
Backstrom | 0:1602fdac44ec | 187 | else |
Backstrom | 0:1602fdac44ec | 188 | status &= ~0x08; // Set to 0 |
Backstrom | 0:1602fdac44ec | 189 | |
Backstrom | 0:1602fdac44ec | 190 | // write status back |
Backstrom | 0:1602fdac44ec | 191 | write_byte(status, 0x0F); |
Backstrom | 0:1602fdac44ec | 192 | } |
Backstrom | 0:1602fdac44ec | 193 | |
Backstrom | 1:3fe5649f1e02 | 194 | void DS3231M::getTemp(int8_t* i, uint8_t* f) |
Backstrom | 1:3fe5649f1e02 | 195 | { |
Backstrom | 1:3fe5649f1e02 | 196 | char data[2]; // msb, lsb |
Backstrom | 1:3fe5649f1e02 | 197 | |
Backstrom | 1:3fe5649f1e02 | 198 | *i = 0; |
Backstrom | 1:3fe5649f1e02 | 199 | *f = 0; |
Backstrom | 1:3fe5649f1e02 | 200 | |
Backstrom | 1:3fe5649f1e02 | 201 | data[0] = 0x11; |
Backstrom | 1:3fe5649f1e02 | 202 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, data, 1); |
Backstrom | 1:3fe5649f1e02 | 203 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, data, 2); |
Backstrom | 1:3fe5649f1e02 | 204 | |
Backstrom | 1:3fe5649f1e02 | 205 | // integer part in entire byte |
Backstrom | 1:3fe5649f1e02 | 206 | *i = (uint8_t)data[0]; |
Backstrom | 1:3fe5649f1e02 | 207 | // fractional part in top two bits (increments of 0.25) |
Backstrom | 1:3fe5649f1e02 | 208 | *f = ((uint8_t)data[1] >> 6) * 25; |
Backstrom | 1:3fe5649f1e02 | 209 | |
Backstrom | 1:3fe5649f1e02 | 210 | // float value can be read like so: |
Backstrom | 1:3fe5649f1e02 | 211 | // float temp = ((((short)data[0] << 8) | (short)data[1]) >> 6) / 4.0f; |
Backstrom | 1:3fe5649f1e02 | 212 | } |
Backstrom | 1:3fe5649f1e02 | 213 | |
Backstrom | 1:3fe5649f1e02 | 214 | void DS3231M::forceTempConversion(uint8_t block) |
Backstrom | 1:3fe5649f1e02 | 215 | { |
Backstrom | 1:3fe5649f1e02 | 216 | // read control register (0x0E) |
Backstrom | 1:3fe5649f1e02 | 217 | uint8_t control = read_byte(0x0E); // read control register |
Backstrom | 1:3fe5649f1e02 | 218 | control |= 0x20; // Set CONV bit |
Backstrom | 1:3fe5649f1e02 | 219 | |
Backstrom | 1:3fe5649f1e02 | 220 | // write new control register value |
Backstrom | 1:3fe5649f1e02 | 221 | write_byte(control, 0x0E); |
Backstrom | 1:3fe5649f1e02 | 222 | |
Backstrom | 1:3fe5649f1e02 | 223 | if (!block) return; |
Backstrom | 1:3fe5649f1e02 | 224 | |
Backstrom | 1:3fe5649f1e02 | 225 | uint8_t data; |
Backstrom | 1:3fe5649f1e02 | 226 | // Temp conversion is ready when control register becomes 0 |
Backstrom | 1:3fe5649f1e02 | 227 | do { |
Backstrom | 1:3fe5649f1e02 | 228 | // Block until CONV is 0 |
Backstrom | 1:3fe5649f1e02 | 229 | data = read_byte(0x0E); |
Backstrom | 1:3fe5649f1e02 | 230 | } while ((data & 0x20) != 0); |
Backstrom | 1:3fe5649f1e02 | 231 | } |
Backstrom | 1:3fe5649f1e02 | 232 | |
Backstrom | 1:3fe5649f1e02 | 233 | |
Backstrom | 0:1602fdac44ec | 234 | uint8_t DS3231M::read_byte(uint8_t offset) |
Backstrom | 0:1602fdac44ec | 235 | { |
Backstrom | 0:1602fdac44ec | 236 | char buf[1]; |
Backstrom | 0:1602fdac44ec | 237 | buf[0] = offset; |
Backstrom | 0:1602fdac44ec | 238 | |
Backstrom | 0:1602fdac44ec | 239 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 1); |
Backstrom | 0:1602fdac44ec | 240 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, buf, 1); |
Backstrom | 0:1602fdac44ec | 241 | //error = ((w!=0) || (r!=0)); |
Backstrom | 0:1602fdac44ec | 242 | |
Backstrom | 0:1602fdac44ec | 243 | return buf[0]; |
Backstrom | 0:1602fdac44ec | 244 | } |
Backstrom | 0:1602fdac44ec | 245 | |
Backstrom | 0:1602fdac44ec | 246 | void DS3231M::write_byte(uint8_t b, uint8_t offset) |
Backstrom | 0:1602fdac44ec | 247 | { |
Backstrom | 0:1602fdac44ec | 248 | char buf[2]; |
Backstrom | 0:1602fdac44ec | 249 | buf[0] = offset; |
Backstrom | 0:1602fdac44ec | 250 | buf[1] = b; |
Backstrom | 0:1602fdac44ec | 251 | |
Backstrom | 0:1602fdac44ec | 252 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 2); |
Backstrom | 0:1602fdac44ec | 253 | //error=(w!=0); |
Backstrom | 0:1602fdac44ec | 254 | } |
Backstrom | 0:1602fdac44ec | 255 | |
Backstrom | 0:1602fdac44ec | 256 | void DS3231M::write_addr(uint8_t addr) |
Backstrom | 0:1602fdac44ec | 257 | { |
Backstrom | 0:1602fdac44ec | 258 | /* |
Backstrom | 0:1602fdac44ec | 259 | Wire.beginTransmission(RTC_ADDR); |
Backstrom | 0:1602fdac44ec | 260 | Wire.write(addr); |
Backstrom | 0:1602fdac44ec | 261 | Wire.endTransmission(); |
Backstrom | 0:1602fdac44ec | 262 | */ |
Backstrom | 0:1602fdac44ec | 263 | } |
Backstrom | 0:1602fdac44ec | 264 |