SHOW:
|
|
- or go back to the newest paste.
| 1 | // DS1302 RTC | |
| 2 | // ---------- | |
| 3 | // | |
| 4 | // By arduino.cc user "Krodal". | |
| 5 | // June 2012 | |
| 6 | // Open Source / Public Domain | |
| 7 | // | |
| 8 | // Using Arduino 1.0.1 | |
| 9 | // | |
| 10 | // Documentation: datasheet | |
| 11 | // | |
| 12 | // | |
| 13 | // The DS1302 uses a 3-wire interface: | |
| 14 | // - bidirectional data. | |
| 15 | // - clock | |
| 16 | // - chip select | |
| 17 | // It is not I2C, not OneWire, and not SPI. | |
| 18 | // So the standard libraries can not be used. | |
| 19 | // Even the shiftOut() function is not used, since it | |
| 20 | // could be too fast (it might be slow enough, | |
| 21 | // but that's not certain). | |
| 22 | // | |
| 23 | // I wrote my own interface code according to the datasheet. | |
| 24 | // Any three pins of the Arduino can be used. | |
| 25 | // See the first defines below this comment, | |
| 26 | // to set your own pins. | |
| 27 | // | |
| 28 | // The "Chip Enable" pin was called "/Reset" before. | |
| 29 | // | |
| 30 | // The chip has internal pull-down registers. | |
| 31 | // This keeps the chip disabled, even if the pins of | |
| 32 | // the Arduino are floating. | |
| 33 | // | |
| 34 | // | |
| 35 | // Range | |
| 36 | // ----- | |
| 37 | // seconds : 00-59 | |
| 38 | // minutes : 00-59 | |
| 39 | // hour : 1-12 or 0-23 | |
| 40 | // date : 1-31 | |
| 41 | // month : 1-12 | |
| 42 | // day : 1-7 | |
| 43 | // year : 00-99 | |
| 44 | // | |
| 45 | // | |
| 46 | // Burst mode | |
| 47 | // ---------- | |
| 48 | // In burst mode, all the clock data is read at once. | |
| 49 | // This is to prevent a rollover of a digit during reading. | |
| 50 | // The read data is from an internal buffer. | |
| 51 | // | |
| 52 | // The burst registers are commands, rather than addresses. | |
| 53 | // Clock Data Read in Burst Mode | |
| 54 | // Start by writing 0xBF (as the address), | |
| 55 | // after that: read clock data | |
| 56 | // Clock Data Write in Burst Mode | |
| 57 | // Start by writing 0xBE (as the address), | |
| 58 | // after that: write clock data | |
| 59 | // Ram Data Read in Burst Mode | |
| 60 | // Start by writing 0xFF (as the address), | |
| 61 | // after that: read ram data | |
| 62 | // Ram Data Write in Burst Mode | |
| 63 | // Start by writing 0xFE (as the address), | |
| 64 | // after that: write ram data | |
| 65 | // | |
| 66 | // | |
| 67 | // Ram | |
| 68 | // --- | |
| 69 | // The DS1302 has 31 of ram, which can be used to store data. | |
| 70 | // The contents will be lost if the Arduino is off, | |
| 71 | // and the backup battery gets empty. | |
| 72 | // It is better to store data in the EEPROM of the Arduino. | |
| 73 | // The burst read or burst write for ram is not implemented | |
| 74 | // in this code. | |
| 75 | // | |
| 76 | // | |
| 77 | // Trickle charge | |
| 78 | // -------------- | |
| 79 | // The DS1302 has a build-in trickle charger. | |
| 80 | // That can be used for example with a lithium battery | |
| 81 | // or a supercap. | |
| 82 | // Using the trickle charger has not been implemented | |
| 83 | // in this code. | |
| 84 | // | |
| 85 | ||
| 86 | ||
| 87 | // Set your own pins with these defines ! | |
| 88 | #define DS1302_SCLK 6 // Arduino pin for the Serial Clock | |
| 89 | #define DS1302_IO 7 // Arduino pin for the Data I/O | |
| 90 | #define DS1302_CE 8 // Arduino pin for the Chip Enable | |
| 91 | ||
| 92 | ||
| 93 | ||
| 94 | // Register names. | |
| 95 | // Since the highest bit is always '1', | |
| 96 | // the registers start at 0x80 | |
| 97 | // If the register is read, the lowest bit should be '1'. | |
| 98 | #define DS1302_SECONDS 0x80 | |
| 99 | #define DS1302_MINUTES 0x82 | |
| 100 | #define DS1302_HOURS 0x84 | |
| 101 | #define DS1302_DATE 0x86 | |
| 102 | #define DS1302_MONTH 0x88 | |
| 103 | #define DS1302_DAY 0x8A | |
| 104 | #define DS1302_YEAR 0x8C | |
| 105 | #define DS1302_ENABLE 0x8E | |
| 106 | #define DS1302_TRICKLE 0x90 | |
| 107 | #define DS1302_CLOCK_BURST 0xBE | |
| 108 | #define DS1302_CLOCK_BURST_WRITE 0xBE | |
| 109 | #define DS1302_CLOCK_BURST_READ 0xBF | |
| 110 | #define DS1302_RAMSTART 0xC0 | |
| 111 | #define DS1302_RAMEND 0xFC | |
| 112 | #define DS1302_RAM_BURST 0xFE | |
| 113 | #define DS1302_RAM_BURST_WRITE 0xFE | |
| 114 | #define DS1302_RAM_BURST_READ 0xFF | |
| 115 | ||
| 116 | ||
| 117 | ||
| 118 | // Defines for the bits, to be able to change | |
| 119 | // between bit number and binary definition. | |
| 120 | // By using the bit number, using the DS1302 | |
| 121 | // is like programming an AVR microcontroller. | |
| 122 | // But instead of using "(1<<X)", or "_BV(X)", | |
| 123 | // the Arduino "bit(X)" is used. | |
| 124 | #define DS1302_D0 0 | |
| 125 | #define DS1302_D1 1 | |
| 126 | #define DS1302_D2 2 | |
| 127 | #define DS1302_D3 3 | |
| 128 | #define DS1302_D4 4 | |
| 129 | #define DS1302_D5 5 | |
| 130 | #define DS1302_D6 6 | |
| 131 | #define DS1302_D7 7 | |
| 132 | ||
| 133 | ||
| 134 | // Bit for reading (bit in address) | |
| 135 | #define DS1302_READBIT DS1302_D0 // READBIT=1: read instruction | |
| 136 | ||
| 137 | // Bit for clock (0) or ram (1) area, | |
| 138 | // called R/C-bit (bit in address) | |
| 139 | #define DS1302_RC DS1302_D6 | |
| 140 | ||
| 141 | // Seconds Register | |
| 142 | #define DS1302_CH DS1302_D7 // 1 = Clock Halt, 0 = start | |
| 143 | ||
| 144 | // Hour Register | |
| 145 | #define DS1302_AM_PM DS1302_D5 // 0 = AM, 1 = PM | |
| 146 | #define DS1302_12_24 DS1302 D7 // 0 = 24 hour, 1 = 12 hour | |
| 147 | ||
| 148 | // Enable Register | |
| 149 | #define DS1302_WP DS1302_D7 // 1 = Write Protect, 0 = enabled | |
| 150 | ||
| 151 | // Trickle Register | |
| 152 | #define DS1302_ROUT0 DS1302_D0 | |
| 153 | #define DS1302_ROUT1 DS1302_D1 | |
| 154 | #define DS1302_DS0 DS1302_D2 | |
| 155 | #define DS1302_DS1 DS1302_D2 | |
| 156 | #define DS1302_TCS0 DS1302_D4 | |
| 157 | #define DS1302_TCS1 DS1302_D5 | |
| 158 | #define DS1302_TCS2 DS1302_D6 | |
| 159 | #define DS1302_TCS3 DS1302_D7 | |
| 160 | ||
| 161 | ||
| 162 | // Structure for the first 8 registers. | |
| 163 | // These 8 bytes can be read at once with | |
| 164 | // the 'clock burst' command. | |
| 165 | // Note that this structure contains an anonymous union. | |
| 166 | // It might cause a problem on other compilers. | |
| 167 | typedef struct ds1302_struct | |
| 168 | {
| |
| 169 | uint8_t Seconds: | |
| 170 | 4; // low decimal digit 0-9 | |
| 171 | uint8_t Seconds10: | |
| 172 | 3; // high decimal digit 0-5 | |
| 173 | uint8_t CH: | |
| 174 | 1; // CH = Clock Halt | |
| 175 | uint8_t Minutes: | |
| 176 | 5; | |
| 177 | uint8_t Minutes10: | |
| 178 | 2; | |
| 179 | uint8_t reserved1: | |
| 180 | 1; | |
| 181 | union | |
| 182 | {
| |
| 183 | struct | |
| 184 | {
| |
| 185 | uint8_t Hour: | |
| 186 | 4; | |
| 187 | uint8_t Hour10: | |
| 188 | 1; | |
| 189 | uint8_t reserved2: | |
| 190 | 1; | |
| 191 | uint8_t hour_12_24: | |
| 192 | 1; // 0 for 24 hour format | |
| 193 | } | |
| 194 | h24; | |
| 195 | struct | |
| 196 | {
| |
| 197 | uint8_t Hour: | |
| 198 | 4; | |
| 199 | uint8_t Hour10: | |
| 200 | 1; | |
| 201 | uint8_t AM_PM: | |
| 202 | 1; // 0 for AM, 1 for PM | |
| 203 | uint8_t reserved2: | |
| 204 | 1; | |
| 205 | uint8_t hour_12_24: | |
| 206 | 1; // 1 for 12 hour format | |
| 207 | } | |
| 208 | h12; | |
| 209 | }; | |
| 210 | uint8_t Date: | |
| 211 | 4; | |
| 212 | uint8_t Date10: | |
| 213 | 2; | |
| 214 | uint8_t reserved3: | |
| 215 | 2; | |
| 216 | uint8_t Month: | |
| 217 | 4; | |
| 218 | uint8_t Month10: | |
| 219 | 1; | |
| 220 | uint8_t reserved4: | |
| 221 | 3; | |
| 222 | uint8_t Day: | |
| 223 | 3; | |
| 224 | uint8_t reserved5: | |
| 225 | 5; | |
| 226 | uint8_t Year: | |
| 227 | 4; | |
| 228 | uint8_t Year10: | |
| 229 | 4; | |
| 230 | uint8_t reserved6: | |
| 231 | 7; | |
| 232 | uint8_t WP: | |
| 233 | 1; // WP = Write Protect | |
| 234 | }; | |
| 235 | ||
| 236 | ||
| 237 | void setup() | |
| 238 | {
| |
| 239 | ds1302_struct rtc; | |
| 240 | ||
| 241 | ||
| 242 | Serial.begin(9600); | |
| 243 | Serial.println(F("DS1302 Real Time Clock"));
| |
| 244 | Serial.println(F("June 2012"));
| |
| 245 | ||
| 246 | ||
| 247 | // Start by clearing the Write Protect bit | |
| 248 | // Otherwise the clock data cannot be written | |
| 249 | // The whole register is written, | |
| 250 | // but the WP-bit is the only bit in that register. | |
| 251 | DS1302_write (DS1302_ENABLE, 0); | |
| 252 | ||
| 253 | // Disable Trickle Charger. | |
| 254 | DS1302_write (DS1302_TRICKLE, 0x00); | |
| 255 | ||
| 256 | // Remove the next define, | |
| 257 | // after the right date and time are set. | |
| 258 | #define SET_DATE_TIME_JUST_ONCE | |
| 259 | #ifdef SET_DATE_TIME_JUST_ONCE | |
| 260 | // Set a time and date | |
| 261 | // This also clears the CH (Clock Halt) bit, | |
| 262 | // to start the clock. | |
| 263 | ||
| 264 | // Fill the structure with zeros to make | |
| 265 | // any unused bits zero | |
| 266 | memset ((char *) &rtc, 0, sizeof(rtc)); | |
| 267 | ||
| 268 | rtc.Seconds = 0; | |
| 269 | rtc.Seconds10 = 0; | |
| 270 | rtc.CH = 0; // 1 for Clock Halt, 0 to run; | |
| 271 | rtc.Minutes = 0; | |
| 272 | rtc.Minutes10 = 0; | |
| 273 | rtc.h24.Hour = 0; | |
| 274 | rtc.h24.Hour10 = 0; | |
| 275 | rtc.h24.hour_12_24 = 0; // 0 for 24 hour format | |
| 276 | rtc.Date = 0; | |
| 277 | rtc.Date10 = 0; | |
| 278 | rtc.Month = 0; | |
| 279 | rtc.Month10 = 0; | |
| 280 | rtc.Day = 0; | |
| 281 | rtc.Year = 0; | |
| 282 | rtc.Year10 = 0; | |
| 283 | rtc.WP = 0; | |
| 284 | ||
| 285 | // Write all clock data at once (burst mode). | |
| 286 | DS1302_clock_burst_write( (uint8_t *) &rtc); | |
| 287 | #endif | |
| 288 | ||
| 289 | ||
| 290 | //interrupt voor knop | |
| 291 | pinMode(2, INPUT); | |
| 292 | attachInterrupt(0, uurErbij, FALLING); | |
| 293 | ||
| 294 | } | |
| 295 | ||
| 296 | ||
| 297 | void loop() | |
| 298 | {
| |
| 299 | ds1302_struct rtc; | |
| 300 | char buffer[80]; // the code uses 70 characters. | |
| 301 | ||
| 302 | // Read all clock data at once (burst mode). | |
| 303 | DS1302_clock_burst_read( (uint8_t *) &rtc); | |
| 304 | ||
| 305 | sprintf(buffer, "Time = %02d:%02d:%02d, ", \ | |
| 306 | (rtc.h24.Hour10 * 10) + rtc.h24.Hour, \ | |
| 307 | (rtc.Minutes10 * 10) + rtc.Minutes, \ | |
| 308 | (rtc.Seconds10 * 10) + rtc.Seconds); | |
| 309 | Serial.print(buffer); | |
| 310 | ||
| 311 | sprintf(buffer, "Date(day of month) = %d, Month = %d, " \ | |
| 312 | "Day(day of week) = %d, Year = %d", \ | |
| 313 | (rtc.Date10 * 10) + rtc.Date, \ | |
| 314 | (rtc.Month10 * 10) + rtc.Month, \ | |
| 315 | rtc.Day, \ | |
| 316 | 2000 + (rtc.Year10 * 10) + rtc.Year); | |
| 317 | Serial.println(buffer); | |
| 318 | ||
| 319 | delay(5000); | |
| 320 | } | |
| 321 | ||
| 322 | ||
| 323 | // -------------------------------------------------------- | |
| 324 | // DS1302_clock_burst_read | |
| 325 | // | |
| 326 | // This function reads 8 bytes clock data in burst mode | |
| 327 | // from the DS1302. | |
| 328 | // | |
| 329 | // This function may be called as the first function, | |
| 330 | // also the pinMode is set. | |
| 331 | // | |
| 332 | void DS1302_clock_burst_read( uint8_t *p) | |
| 333 | {
| |
| 334 | int i; | |
| 335 | ||
| 336 | _DS1302_start(); | |
| 337 | ||
| 338 | // Instead of the address, | |
| 339 | // the CLOCK_BURST_READ command is issued | |
| 340 | // the I/O-line is released for the data | |
| 341 | _DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true); | |
| 342 | ||
| 343 | for (i=0; i<8; i++) | |
| 344 | {
| |
| 345 | *p++ = _DS1302_toggleread(); | |
| 346 | } | |
| 347 | _DS1302_stop(); | |
| 348 | } | |
| 349 | ||
| 350 | ||
| 351 | // -------------------------------------------------------- | |
| 352 | // DS1302_clock_burst_write | |
| 353 | // | |
| 354 | // This function writes 8 bytes clock data in burst mode | |
| 355 | // to the DS1302. | |
| 356 | // | |
| 357 | // This function may be called as the first function, | |
| 358 | // also the pinMode is set. | |
| 359 | // | |
| 360 | void DS1302_clock_burst_write( uint8_t *p) | |
| 361 | {
| |
| 362 | int i; | |
| 363 | ||
| 364 | _DS1302_start(); | |
| 365 | ||
| 366 | // Instead of the address, | |
| 367 | // the CLOCK_BURST_WRITE command is issued. | |
| 368 | // the I/O-line is not released | |
| 369 | _DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false); | |
| 370 | ||
| 371 | for (i=0; i<8; i++) | |
| 372 | {
| |
| 373 | // the I/O-line is not released | |
| 374 | _DS1302_togglewrite( *p++, false); | |
| 375 | } | |
| 376 | _DS1302_stop(); | |
| 377 | } | |
| 378 | ||
| 379 | ||
| 380 | // -------------------------------------------------------- | |
| 381 | // DS1302_read | |
| 382 | // | |
| 383 | // This function reads a byte from the DS1302 | |
| 384 | // (clock or ram). | |
| 385 | // | |
| 386 | // The address could be like "0x80" or "0x81", | |
| 387 | // the lowest bit is set anyway. | |
| 388 | // | |
| 389 | // This function may be called as the first function, | |
| 390 | // also the pinMode is set. | |
| 391 | // | |
| 392 | uint8_t DS1302_read(int address) | |
| 393 | {
| |
| 394 | uint8_t data; | |
| 395 | ||
| 396 | // set lowest bit (read bit) in address | |
| 397 | bitSet (address, DS1302_READBIT); | |
| 398 | ||
| 399 | _DS1302_start(); | |
| 400 | // the I/O-line is released for the data | |
| 401 | _DS1302_togglewrite (address, true); | |
| 402 | data = _DS1302_toggleread (); | |
| 403 | _DS1302_stop(); | |
| 404 | ||
| 405 | return (data); | |
| 406 | } | |
| 407 | ||
| 408 | ||
| 409 | // -------------------------------------------------------- | |
| 410 | // DS1302_write | |
| 411 | // | |
| 412 | // This function writes a byte to the DS1302 (clock or ram). | |
| 413 | // | |
| 414 | // The address could be like "0x80" or "0x81", | |
| 415 | // the lowest bit is cleared anyway. | |
| 416 | // | |
| 417 | // This function may be called as the first function, | |
| 418 | // also the pinMode is set. | |
| 419 | // | |
| 420 | void DS1302_write(int address, uint8_t data) | |
| 421 | {
| |
| 422 | // clear lowest bit (read bit) in address | |
| 423 | bitClear (address, DS1302_READBIT); | |
| 424 | ||
| 425 | _DS1302_start(); | |
| 426 | // don't release the I/O-line | |
| 427 | _DS1302_togglewrite (address, false); | |
| 428 | // don't release the I/O-line | |
| 429 | _DS1302_togglewrite (data, false); | |
| 430 | _DS1302_stop(); | |
| 431 | } | |
| 432 | ||
| 433 | ||
| 434 | // -------------------------------------------------------- | |
| 435 | // _DS1302_start | |
| 436 | // | |
| 437 | // A helper function to setup the start condition. | |
| 438 | // | |
| 439 | // I don't use an 'init' function. | |
| 440 | // But now the pinMode is set every time. | |
| 441 | // That's not a big deal, and it's valid. | |
| 442 | void _DS1302_start(void) | |
| 443 | {
| |
| 444 | digitalWrite (DS1302_CE, LOW); // default, not enabled | |
| 445 | pinMode (DS1302_CE, OUTPUT); | |
| 446 | ||
| 447 | digitalWrite (DS1302_SCLK, LOW); // default, clock low | |
| 448 | pinMode (DS1302_SCLK, OUTPUT); | |
| 449 | ||
| 450 | pinMode (DS1302_IO, OUTPUT); | |
| 451 | ||
| 452 | digitalWrite (DS1302_CE, HIGH); // start the session | |
| 453 | delayMicroseconds(4); // tCC = 4us | |
| 454 | } | |
| 455 | ||
| 456 | ||
| 457 | // -------------------------------------------------------- | |
| 458 | // _DS1302_stop | |
| 459 | // | |
| 460 | // A helper function to finish the communication. | |
| 461 | // | |
| 462 | void _DS1302_stop(void) | |
| 463 | {
| |
| 464 | // Set CE low | |
| 465 | digitalWrite (DS1302_CE, LOW); | |
| 466 | ||
| 467 | delayMicroseconds(4); // tCWH = 4us | |
| 468 | } | |
| 469 | ||
| 470 | ||
| 471 | // -------------------------------------------------------- | |
| 472 | // _DS1302_toggleread | |
| 473 | // | |
| 474 | // A helper function for reading a byte with bit toggle | |
| 475 | // | |
| 476 | // This function assumes that the SCLK is still high. | |
| 477 | // | |
| 478 | uint8_t _DS1302_toggleread(void) | |
| 479 | {
| |
| 480 | uint8_t i, data; | |
| 481 | ||
| 482 | data = 0; | |
| 483 | for (i = 0; i <= 7; i++) | |
| 484 | {
| |
| 485 | // Issue a clock pulse for the next databit. | |
| 486 | // If the 'togglewrite' function was used before | |
| 487 | // this function, the SCLK is already high. | |
| 488 | digitalWrite (DS1302_SCLK, HIGH); | |
| 489 | delayMicroseconds(1); | |
| 490 | ||
| 491 | // Clock down, data is ready after some time. | |
| 492 | digitalWrite (DS1302_SCLK, LOW); | |
| 493 | delayMicroseconds(1); // tCL=1000ns, tCDD=800ns | |
| 494 | ||
| 495 | // read bit, and set it in place in 'data' variable | |
| 496 | bitWrite (data, i, digitalRead(DS1302_IO)); | |
| 497 | } | |
| 498 | return (data); | |
| 499 | } | |
| 500 | ||
| 501 | ||
| 502 | // -------------------------------------------------------- | |
| 503 | // _DS1302_togglewrite | |
| 504 | // | |
| 505 | // A helper function for writing a byte with bit toggle | |
| 506 | // | |
| 507 | // The 'release' parameter is for a read after this write. | |
| 508 | // It will release the I/O-line and will keep the SCLK high. | |
| 509 | // | |
| 510 | void _DS1302_togglewrite(uint8_t data, uint8_t release) | |
| 511 | {
| |
| 512 | int i; | |
| 513 | ||
| 514 | for (i = 0; i <= 7; i++) | |
| 515 | {
| |
| 516 | // set a bit of the data on the I/O-line | |
| 517 | digitalWrite (DS1302_IO, bitRead(data, i)); | |
| 518 | delayMicroseconds(1); // tDC = 200ns | |
| 519 | ||
| 520 | // clock up, data is read by DS1302 | |
| 521 | digitalWrite (DS1302_SCLK, HIGH); | |
| 522 | delayMicroseconds(1); // tCH = 1000ns, tCDH = 800ns | |
| 523 | ||
| 524 | if (release && i == 7) | |
| 525 | {
| |
| 526 | // If this write is followed by a read, | |
| 527 | // the I/O-line should be released after | |
| 528 | // the last bit, before the clock line is made low. | |
| 529 | // This is according the datasheet. | |
| 530 | // I have seen other programs that don't release | |
| 531 | // the I/O-line at this moment, | |
| 532 | // and that could cause a shortcut spike | |
| 533 | // on the I/O-line. | |
| 534 | pinMode (DS1302_IO, INPUT); | |
| 535 | digitalWrite (DS1302_IO, LOW); // remove any pull-up | |
| 536 | } | |
| 537 | else | |
| 538 | {
| |
| 539 | digitalWrite (DS1302_SCLK, LOW); | |
| 540 | delayMicroseconds(1); // tCL=1000ns, tCDD=800ns | |
| 541 | } | |
| 542 | } | |
| 543 | } | |
| 544 | void uurErbij(){
| |
| 545 | ds1302_struct rtc; | |
| 546 | rtc.h24.Hour++; | |
| 547 | ||
| 548 | } |