You are here

I2C communication with RTC | Cypress Semiconductor

I2C communication with RTC

Summary:4 Replies, Latest post by bobgoar on 12 Aug 2017 06:58 AM PDT
Verified Answers:0
Last post
Log in to post new comments.
grecobene's picture
User
2 posts

Hello All,

I have just picked up working with PSoC and went through the PSoC 101 Lessons to get the basics.Turning LEDs on and off got old quite fast so now I am trying to communicate with an RTC through I2C.

With the “automatic mode” I am getting results that I do not understand.With the “manual mode” I seem to be able to feed the RTC with some data but just can’t extract it back.

Setup:
I am using PSoC Creator 3.1 SP3 with the CY8CKIT-049-42xx kit with the corresponding CyInstaller.
The RTC is a no-name DS1307 bought on eBay (I2C address = 0b1101000).
10k pullups are installed on the I2C lines, with the 32khz xtal for the RTC.

The code:
Nothing special in the header:

#include <project.h>

uint8 rtcBuffer[] = {0b00101010, 0b00101001, 0b00000111, 0b10, 0b10001, 0b100, 0b10111, 0b0};; // Values to be written in the RTC
uint8 rtcRegisterArray[8];  // array where data read from RTC will be placed.
uint8 i=0;
uint8 status;

I’ll start with the “manual mode” since this yields the most understandable results.Most if not all of the code I use for the communication comes straight from the I2C SCB datasheet from Cypress.

I2Crtc_Start();

CyDelay(1000); // Read somewhere to make sure to let the RTC initialize.1s should be a safe value.

   // CyGlobalIntEnable;  // Uncomment this line to enable global interrupts.

   while(1){
       
       I2Crtc_I2CMasterClearStatus(); // Clear any previous status
       status = I2Crtc_I2CMasterSendStart(0x68, I2Crtc_I2C_WRITE_XFER_MODE);
       if(I2Crtc_I2C_MSTR_NO_ERROR == status) /* Check if transfer completed without errors */
       {
           // Send array of 8 bytes
           for(i=0; i<8u; i++){
               status = I2Crtc_I2CMasterWriteByte(rtcBuffer[i]);
               if(I2Crtc_I2C_MSTR_NO_ERROR !=status){
                   break;
               }
           }
       }
       I2Crtc_I2CMasterSendStop(); // Stop the Xmission

Results:
(refering to screeshot write_manual.png) The RTC ACKs when called and fed with 8 bytes of data.Looking good so far…

Afterwards, I read the first 8 registers in the RTC using the “manual mode”

status = I2Crtc_I2CMasterSendStart(0x68, I2Crtc_I2C_READ_XFER_MODE);
       if(I2Crtc_I2C_MSTR_NO_ERROR == status){ /* Check if transfer completed without errors */
           // Read array of 8 bytes
           for(i=0; i<8u; i++){
               if(i < 7u){
                   rtcRegisterArray[i] = I2Crtc_I2CMasterReadByte(I2Crtc_I2C_ACK_DATA);
               }
               else{ // sends a NACK after the last byte to be read to stop the RTC from sending data
                   rtcRegisterArray[i] = I2Crtc_I2CMasterReadByte(I2Crtc_I2C_NAK_DATA);
               }
           }
       }
       I2Crtc_I2CMasterSendStop(); // Send Stop

Here the RTC returns random values for subsequent read operations:(refering to screenshot read_manual.png)
Some returned values event have ones in places where there should be a 0 according to the datasheet.

I am missing something here?

Now, if try to do the same with the “automatic mode”, even writing data does not seem to work.(The pinLedx here in the code are some LEDs that light up on the breadboard to help debug the code so I know where it’s stuck or not reaching.)

I2Crtc_I2CMasterClearStatus(); // Clear any previous status
       I2Crtc_I2CMasterWriteBuf(0b01101000, rtcBuffer, 8, I2Crtc_I2C_MODE_COMPLETE_XFER); // "automatic" write command as used in the datasheet
       pinLed1_Write(1);
       CyDelay(500);
       pinLed1_Write(0);
        
        
       while(1){
            
           pinLed2_Write(1);
            
           if(0u !=(I2Crtc_I2CMasterStatus() & I2Crtc_I2C_MSTAT_WR_CMPLT)){
            
               pinLed2_Write(0);    
                //Transfer complete.Check Master status to make sure that transfer completed without errors.
               break;
           }
       }

Here too, the RTC ACKs the address call, but the PSoC stays mute afterwards.It even appears as if it keeps the clock low and never puts it back up (even 5 seconds to the right of this screenshot, the clock stays low). (refering to screeshot write_auto.png)

The LED#2 is kept lit which tells the program is stuck in the following loop.

If I comment out this verification and only add a delay to let the transfer to complete, I get exactly the same thing:The PSoC master calls the RTC address, gets the ACK and then keeps the clock low permanently.

Now, if I comment out the “write” portion of this program and only “read” the registers upon start in the RTC

I2Crtc_I2CMasterClearStatus(); /* Clear any previous status */
       I2Crtc_I2CMasterReadBuf(0b1101000, rtcRegisterArray, 8, I2Crtc_I2C_MODE_COMPLETE_XFER); // "automatic" read command as used in the datasheet
        
       pinLed3_Write(1);
       while(1){
                
           if(0u !=(I2Crtc_I2CMasterStatus() & I2Crtc_I2C_MSTAT_RD_CMPLT)){
               pinLed3_Write(0);    
                //Transfer complete.Check Master status to make sure that transfer completed without errors.
               break;
           }
       }

here is what I get:(refering to screeshot read_auto.png)

Still, the clock looks like it stuck on “low” after the last byte.

Here too, I have to comment out the loop that checks the master status for a complete flag otherwise it never comes out of it (the LED3 stays on).I am guessing that the status never reaches COMPLETE since the stop command is never issued, because the clock is stuck low.

Thank you guys,

Marc

user_242978793's picture
User
1485 posts

You must set the time on the DS1307 module or it will return only Zero. So you must write the current time and date to the DS1307 then it will start to return the time and date and start counting. 

grecobene's picture
User
2 posts

Thanks Bob for the heads up.

Based on your suggestion, pushing the complete init values for the clock and the calendar helped.It made me realize I was trying to push a 7 in the 10minutes field which caused the RTC to "crash" I guess and return only zeros.However, the answer I get from the RTC looks quite random to me.I make a reading every seconds and each register returns completely random values, even some that are impossible (ones in bits that can only hold zero according to the datasheet).I have updated the code and the screenshots in the first post accordingly.

And the "auto" mode still holds the clock down after the first communication.

user_242978793's picture
User
1485 posts

Try this program.You will have to add the routine to write the start time.

user_242978793's picture
User
1485 posts

I am using the latest PSoc Creator release and you will need to upgrade to PSOC Creator 4.1,

Log in to post new comments.