| Arduino, SPI and the DS1306 RTC | |
|
Converting BCD to DecimalAs we'll need a similar conversion for several of the other DS1306 regisers, it's neater to write it as a separate function.
void loop() {
digitalWrite(chipEnablePin, HIGH);
SPI.transfer(0x00);
byte seconds = SPI.transfer(0x00);
seconds = bcd2dec(seconds);
digitalWrite(chipEnablePin, LOW);
Serial.println(seconds, DEC);
delay(1000);
}
byte bcd2dec(byte value) {
byte units = value & B00001111; // For the units, we only want bits 0 to 3 so mask off the rest.
byte tens = (value >> 4) * 10; // Shift the top 4 bits to the right, 4 times. Then
// multiply by 10 to make decimal 'tens'.
return tens + units; // Return the sum.
}
As can be seen from the Arduino Serial Monitor, the result is almost correct but not quite. Ideally we need to add a leading '0' when the value is less than 10. As the project will ultimately be using a Liquid Crystal Display, I think it's best to add the '0' later, as and when required.
It also makes sense to put the actual reading of the register into a function of its own because we'll obviously be reading other registers.
#include <SPI.h>
// The DS1306 CE (chip enable) pin is connected to Arduino digital pin 10.
int chipEnablePin = 10;
void setup() {
// Set the Chip enable pin as OUTPUT.
pinMode(chipEnablePin, OUTPUT);
// The DS1306 datasheet states the chip enable signal must be asserted HIGH
// during a read or a write so set it LOW before the SPI interface is set up.
digitalWrite(chipEnablePin, LOW);
SPI.begin();
// The DS1306 datasheet states that data is clocked into or out of the registers
// Most Significant Bit first and that it Supports Motorola SPI Modes 1 and 3. We'll use
// Mode 1.
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1); // or SPI_MODE3
// Initialize RTC Control Register
digitalWrite(chipEnablePin, HIGH); // Enable the Chip Enable by taking it HIGH
SPI.transfer(0x8f); // Address the Control Register for a Write.
SPI.transfer(B00000100); // bit 2 set = 1Hz (pin 7) ON
digitalWrite(chipEnablePin, LOW); // All done so take the Chip Enable LOW.
}
void loop() {
byte seconds = readRegister(0x00);
seconds = bcd2dec(seconds);
if (seconds < 10) {
Serial.print("0");
}
Serial.println(seconds);
delay(1000);
}
byte readRegister(byte Reg) {
digitalWrite(chipEnablePin, HIGH);
SPI.transfer(Reg);
byte getByte = SPI.transfer(Reg);
digitalWrite(chipEnablePin, LOW);
return getByte;
}
byte bcd2dec(byte value) {
byte units = value & B00001111; // We only want bits 0 to 3 so mask off the rest.
byte tens = (value >> 4) * 10; // Shift the top 4 bits to the right, 4 times. Then
// multiply by 10 to make decimal 'tens'.
return tens + units; // Return the sum.
}
| |