Hello,
I am working with an RTC module, namely the SD2405AL using the Wire Library.
I have succeeded in running the manufacturers sample code to write to the device
and to read from the internal registers.
However the sample code reads immediately after a write and only starting with the
base internal device address (0x00). The device only has 32 registers and I can
read them all at once However, I assume, in common with most I2C devices available,
it is normal to be able to read individual groups of registers at any internal location.
I find I am unable to do this with the SD2405AL and the Wire Library.
The Wire.requestFrom() function in the Wire library has (understandably) no involvement
with the addressing of device internal registers.
The manufacturers data sheet gives two proposals for reading the device registers under I2C.
One,simply equates to the scenario above namely read after write and from the base address 0x00.
The other scenario it describes as "transmission direction changed during one transmission".
Here we write to the device, a byte identifying the internal address of the device that we wish
reading to take place from, but then rather than the master sending a "stop" to end that
write transmission the master sends a repeated "start" signal, then re-addresses the device
with a read transmission request for a number of bytes. I understand that this type of
transmission is also known as a "combined format" transaction.
I have tried writing the byte identifying the internal address I wish to read, but, then in order
to avoid the mistakes outlined when using the Wire Library, I need to follow this with
the Wire.endTransmission() before proceeding with a Wire.requestFrom().
I think the Wire.endTransmission() code has the effect of resetting the device internal
register pointer to 0x00 and the read once again takes place from there.
I cannot see using the standard functions of the Wire Library how to accommodate this
"transmission direction changed during one transmission" scenario.
I found Nick Gammon's piece on I2C very informative, where he gives examples of reading from
individual locations within a device and this is the method I have adopted. However in the case of
the SD2405AL this does not seem to provide the correct exchange to manipulate the register pointer.
Can anyone help please.
// Attempt to read from an SD2405AL Real Time Clock I2C device, at an internal address other than 0x00
#include "Wire.h"
#define RTC_Address 0x32 //RTC_Address
void setup()
{
Wire.begin();
Serial.begin(9600);
enable_Writing(); //Write enabling bits in control registers to allow writing to data registers
Wire.beginTransmission(RTC_Address);
Wire.write(0x14); //Set the internal address for writing to the 12 general purpose registers
Wire.write("H"); //Stick some text in them
Wire.write("e");
Wire.write("l");
Wire.write("l");
Wire.write("o");
Wire.write(" ");
Wire.write("W");
Wire.write("o");
Wire.write("r");
Wire.write("l");
Wire.write("d");
Wire.write("s");
Wire.endTransmission();
disable_Writing(); //Write disabling bits in control registers to prevent writing to data registers
examine_registers(32); // Read all 32 registers of the device assuming register pointer is at 0x00
// The output confirms the successful writes to the last 12 registers of the device.
Wire.beginTransmission(RTC_Address);
Wire.write(0x14); //Try to set the register pointer to an internal address for reading
Wire.endTransmission();
examine_registers(12); // Hopefully read the last 12 general purpose registers of the device
// assuming the register pointer is now at 0x14
// In fact the output gives the contents of the first 12 registers of the device.
// Implying that the pointer was set at 0x00, rather than 0x14 as was hoped for.
}
//...
void enable_Writing(void){ // procedure required to enable writing to device data registers as per data sheet
Wire.beginTransmission(RTC_Address);
Wire.write(0x10); //Set the register pointer to the control register 10H address
Wire.write(0x80); //Set WRTC1=1 <-Set this bit first
Wire.endTransmission();
Wire.beginTransmission(RTC_Address);
Wire.write(0x0F); //Set the register pointer to the control register 0FH address
Wire.write(0x84); //Set WRTC2=1,WRTC3=1 <-followed by these bits
Wire.endTransmission();
}
void disable_Writing(void){ // procedure required to disable writing to device data registers as per data sheet
Wire.beginTransmission(RTC_Address);
Wire.write(0x0F); //Set the register pointer to the control register 0FH address
Wire.write(0); //Set WRTC2=0,WRTC3=0 <-Clear these bits first
Wire.write(0); //Set WRTC1=0 <- followed by this bit. We assume that we are now pointing
//at the next control register location i.e. 10H
Wire.endTransmission();
}
void examine_registers(int x){ //Request x bytes starting from internal device address currently pointed to and print same.
int n = 0;
char regData[32];
Wire.requestFrom(RTC_Address,x);
while (Wire.available())
{
regData[n++] = Wire.read();
}
n=0;
while(n <= x-1)
{
Serial.println(regData[n]);
n=n+1;
}
}
void loop(void)
{
}
Data sheet for SD2405AL can be found at :-
[
Regards
Dave Paxton](Gravity-I2C-SD2405-RTC-Module/SD2405AL datasheet.pdf at master · DFRobot/Gravity-I2C-SD2405-RTC-Module · GitHub)