5 Replies Latest reply on Aug 29, 2017 10:44 PM by kymoz_2651751

    I2C communication with RTC

    kymoz_2651751

      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