CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C issue on PIC16F877A
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
OldPhart



Joined: 04 Dec 2017
Posts: 8
Location: Canada

View user's profile Send private message

PostPosted: Tue Dec 05, 2017 10:26 am     Reply with quote

Ttelmah,

I indeed do not get that one (does not seem very clear in the documentation), but I will go with it. Also thanks for fixing my code for the lacking NACK on my last read, very simple, THANKS!

Now if I can just get the first write to work.....

Thanks again,
OldPhart
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Tue Dec 05, 2017 11:38 am     Reply with quote

Yes, it's a fundamental thing of understanding I2C.
99.9% of it is always controlled only by the master. It generates the clocks etc., so the slave only 'sends' bits when the master actually asks for them.
The '0.1%', is that the slave can hold the clock line low at the end of a byte, to delay the master being able to advance.
Have fun.
OldPhart



Joined: 04 Dec 2017
Posts: 8
Location: Canada

View user's profile Send private message

PostPosted: Tue Dec 05, 2017 6:56 pm     Reply with quote

I figured it out!
I am suffering from a locked up I2C bus. At some point in time a data transfer was interrupted, or an incorrect sequence run that left the bus in an unknown state.
When not active, both SCL and SDA must be high, but my logic probe showed that SDA was held low by the slave. Normally a power reset would reset this condition, but since the DS3231 has a battery backup, this did not happen. Esentially, the slave is waiting for an ACK signal from the master to send the next byte of data, but the master thinks the bus is idle. Analog Devices app note AN-686 has a real good description of the problem.
How to fix this?
A reset of the PIC does not do it, because of the backup battery. Besides, a reset of the DS3231 would destroy all the settings in it.
The master must produce a 1-0-1 sequence on the SCL line, and check the bus status (both lines should be high). This can take as many as 9 cycles, but also as few as 1 or 2. That all depends on where it got stuck. So.....
I was thinking of running the following at the start of MAIN.c:

Code:

output_float(PIN_C3)
output_float(PIN_C4)
while ((input_state(PIN_C4) && input_state(PIN_C3)) != 1)
   {
   output_low (PIN_C3);  //SCL
   delay_cycles(1);
   output_float (PIN_C3);  //SCL
   }


I have not tried it yet, something for tomorrow!

Cheers,
OldPhart
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 05, 2017 7:05 pm     Reply with quote

This recent post has code to implement the i2c reset method described
in Analog Devices AN-686:
http://www.ccsinfo.com/forum/viewtopic.php?t=56821&start=15
Instead of the I2CEN bit, you should use the SSPEN bit, since your PIC
is the 16F877A. Also use getenv() instead of hard-coding the register
address.
OldPhart



Joined: 04 Dec 2017
Posts: 8
Location: Canada

View user's profile Send private message

PostPosted: Wed Dec 06, 2017 3:31 pm     Reply with quote

PCM programmer,

WONDERFUL! You got me on the right track; I now have a perfectly working timer! My code ended up like this:
Code:

#bit I2CEN = 0x14.5      // SSPEN bit to enable/disable hardware I2C module
#define i2c_SCL     PIN_C3
#define i2c_SDA     PIN_C4

if(!input(i2c_SDA)){            // if SDA stuck low - Fault Condition
    I2CEN=0;                    // disable I2C2 Hardware Module
    output_drive(i2c_SCL);      // set SCL as output
    while(!input(i2c_SDA)){     // Toggle clock line till fault clears
       output_toggle(i2c_SCL);
       delay_us(1);
    }
    output_float(i2c_SCL);      // set SCL as input
    I2CEN=1;                    // enable I2C2 Hardware Module
}   


I did hardcode the SSPEN address for now, I have to look up how to use the getenv(). OldPhart,...... Learn slowwwwww.

On to the next part of the project....

Thanks again,
OldPhart
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group