View previous topic :: View next topic |
Author |
Message |
ahmed-agt
Joined: 24 Oct 2014 Posts: 9
|
This is one of the suggested solution! |
Posted: Tue Nov 13, 2018 9:14 am |
|
|
Ttelmah wrote: | Simple answer then, switch to using software I2C. On your chip this will make no difference at all (software can give over a MHz on a chip at this speed), and will fix the issue. |
Using a software I2C instead of a hardware I2C, this can be done by adding the option FORCE_SW to your #use i2c() line as stated by CCS Support. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Nov 13, 2018 9:23 am |
|
|
Which is why I suggested it. |
|
|
ahmed-agt
Joined: 24 Oct 2014 Posts: 9
|
The second solution using the hardware I2C. |
Posted: Tue Nov 13, 2018 9:33 am |
|
|
The second option is to add a read of the I2CRCV
register before the first call to i2c_read() in your ds1307_read() function, for example changing
your ds1307_read() function the following:
Code: | void ds1307_read()
{
#byte I2CRCV = getenv("SFR:I2CRCV")
unsigned int8 temp;
i2c_start(); // Start I2C
i2c_write(0xD0); // DS1307 address
i2c_write(0x00); // Send register address
i2c_start(); // Restart I2C
i2c_write(0xD1); // Initialize data read
temp = I2CRCV;
second =i2c_read(1); // Read seconds from register 0 second
minute =i2c_read(1); // Read minuts from register 1
hour = i2c_read(1); // Read hour from register 2
day = i2c_read(1); // Read day from register 3
date = i2c_read(1); // Read date from register 4
month = i2c_read(1); // Read month from register 5
year = i2c_read(0); // Read year from register 6
i2c_stop(); // Stop I2C
} |
Finally, reading and copying the I2CRCV register to a temp RAM location before using the register solve the problem. These work for me!
Thanks you all for your support. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Nov 13, 2018 9:42 am |
|
|
I actually wonder if his problem is errata 13 for this chip. It appears that the output latch bit on the SDA pin overrides the I2C peripheral, so this pin must be set low for the hardware I2C to work correctly. Problem is this has to be done before enabling the I2C, so one would have to use 'NOINIT' in the #use I2C, then set this pin low, and call I2C_init. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
Re: The second solution using the hardware I2C. |
Posted: Tue Nov 13, 2018 1:23 pm |
|
|
ahmed-agt wrote: | The second option is to add a read of the I2CRCV
register before the first call to i2c_read() in your ds1307_read() function, for example changing
your ds1307_read() function the following:
Code: | void ds1307_read()
{
#byte I2CRCV = getenv("SFR:I2CRCV")
unsigned int8 temp;
i2c_start(); // Start I2C
i2c_write(0xD0); // DS1307 address
i2c_write(0x00); // Send register address
i2c_start(); // Restart I2C
i2c_write(0xD1); // Initialize data read
temp = I2CRCV;
second =i2c_read(1); // Read seconds from register 0 second
minute =i2c_read(1); // Read minuts from register 1
hour = i2c_read(1); // Read hour from register 2
day = i2c_read(1); // Read day from register 3
date = i2c_read(1); // Read date from register 4
month = i2c_read(1); // Read month from register 5
year = i2c_read(0); // Read year from register 6
i2c_stop(); // Stop I2C
} |
Finally, reading and copying the I2CRCV register to a temp RAM location before using the register solve the problem. These work for me!
Thanks you all for your support. |
Interesting finding.
On the SPI, the register is meant to work this way, and the first SPI_read, will return what is already in the register, if there is a value in it, rather than performing a transfer, so you have to ensure the register is read before performing a request.
I2C though is not meant to behave this way and certainly does not for me on a lot of transfers.
It suggests that in this particular case, either because of an oddity in the DS chip or the PIC peripheral, it is functioning this way.
Definitely worth trying. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Nov 14, 2018 6:18 am |
|
|
been following this thread with interest.... and a couple comments.
1..I've never had a problem using the DS1307 with several types of PIC (46k22 being the latest) and since a LOT of people use it and the CCS driver, we'd have heard about this before so I suspect the OP's PIC.
2) I'd like to know what happens if 'seconds' are not read. Say start with 'minutes'. Does the 'minutes' come back as '00' ? If so try reading JUST 'hours' (or any one register), does that come back as '00' ? If so Only the 1st time or always ?
My projects with RTC all use the RTC to send an interrupt at a 1Hz rate, a 'heartbeat', to then have main() read sensors, update the local LCD and do some 'control'. I cannot recall ever seeing bad data from the RTC.
Assuming the devices are next to each other and proper pullups, I can't see any hardware issues.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Nov 14, 2018 6:58 am |
|
|
One comment to this (which is why I suggested adding a delay earlier), the DS1307, only supports slow I2C, and has a longer delay between a repeated start, or a stop and a restart, than the standard I2C 'spec. It requires 4.7uSec between such events. Now on a normal PIC at a few MHz, this won't be a problem, but on the DsPIC at speed it is likely that extra delays _will_ be needed. |
|
|
|