11 Replies Latest reply on Nov 16, 2016 1:38 PM by mfarkas_1728531

    I2C Get Byte, Print over UART

    vkaiser_1860311

      Hello,

         

      I seem to be having some trouble setting up I2C, and/or formatting the data to view it over the UART.  I'm hoping someone can please identify my error(s) and help me to correct them.

         

      I am using the PSoC4 Pioneer kit.

         

      I have connected to the SCL/SDA the corresponding pins of an MCP9808 breakout board (and +5V/GND).
      MCP9808 I2C Address: 0x18
      MCP9808 Temperature Register: 0x05  (2 Byte data output)

         

      I have confirmed with a different MCU/FW setup that the MCP9808 is working correctly over I2C.

         

      The output I2C data out (Address and Register seem to be sending correctly) I see on the scope is not data I would expect - which leads me to believe that my I2C protocol is incorrect.
      The scope data is also not what I'm seeing reported in TeraTerm - so I may have data formatting issues too.
      I am seeing my UART test reported in TeraTerm, so that seems to be fine.

         

      Any guidance would be greatly appreciated!  Thank you.

         
           #include <MCP9808.h>
      #include <stdio.h>
         
         
           #define MCP_I2C_ADDRESS 0x18
      #define MCP_REGISTER 0x05
      uint32 MCP_temp[2];
         
         
           void Get_Temp(void);   
         
           int main()
      {   
          /* Initialization of Variables */
              char OutputString[2];
          
          /* Initialization / Startup */
              I2C_Start();
              UART_Start();
         
          /* Enabling the Global Interrupt */ 
              CyGlobalIntEnable;
                            
          /* Application code */
              UART_UartPutString("\r\nGet Temp: CONNECTED \r\n");     //Check UART/Terminal connection
          
          for(;;)
          {
              /* Call the function to get the current temp via I2C */        
              Get_Temp();
              
              /* Store formatted data as string */
              sprintf(OutputString, "%lu", MCP_temp);
              
              /* Print the received temp to Hyperterminal  */ 
              UART_UartPutString(OutputString);  
              UART_UartPutString("\r\n");
              
              CyDelay(1000);
          }
         
      } /* END MAIN() */
         
         
           /*******************************************************************************
      * Function Name : Get_Temp
      ********************************************************************************
      * Summary:
      *   It receives the current temp from the MCP9808 in the Current_temp array. 
      *
      * Parameters:
      *   None
      *
      * Return Value:
      *   None
      *******************************************************************************/
         
         
           void Get_Temp(void)
      {  
          //Initialize Transaction for Writing
          I2C_I2CMasterSendStart(MCP_I2C_ADDRESS, I2C_I2C_WRITE_XFER_MODE);
          
          //Indicate Register to Write to
          I2C_I2CMasterWriteByte(MCP_REGISTER);
          I2C_I2CMasterSendRestart(MCP_I2C_ADDRESS, I2C_I2C_READ_XFER_MODE);
          
          //Read from Register (2 Bytes, last byte NAKed)
          MCP_temp[0] = I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA);    
          MCP_temp[1] = I2C_I2CMasterReadByte(I2C_I2C_NAK_DATA);
          
          //End Transaction
          I2C_I2CMasterSendStop();
          
      } /* END GET_TEMP */    
         
         
           /* END FILE */   
        • 1. Re: I2C Get Byte, Print over UART
          user_1377889

          Welcome in the forum.

             

          At first sight: You are overwriting your OutputString which is only 2 bytes in length when you call sprintf().

             

          Next time better post your complete project, so that we all can have a look at all of your settings. To do so, use
          Creator->File->Create Workspace Bundle (minimal)
          and attach the resulting file.

             

           

             

          Bob

          • 2. Re: I2C Get Byte, Print over UART
            vkaiser_1860311

            Hi Bob,

               

            Thank you for that.  I have attached the bundle as requested.

               

            I apologize - I don't think I'm clear on what you mean though regarding the sprintf function.  
            My intent was to convert the two-byte read from the sensor (MCP_temp) into characters (OutputString) to output into TeraTerm. I see that it is throwing warnings.  My interpretation was that the format is sprintf(output_buffer, "%format", data_to_convert), is that incorrect?  

               

            Thank you for helping me to understand, I appreciate your assistance.  

            • 3. Re: I2C Get Byte, Print over UART
              user_1377889

              Archive is not compilable, lots(!!) of projects and missing .h-files.

                 

               

                 

              uint32 MCP_temp[2]; This makes MCP_temp an array, thus the reference to MCP_temp is the address of that array.

                 

                      char OutputString[2]; This is a two-byte array. As a string, the last byte needs to carry the string terminator 0x00.

                 

                      sprintf(OutputString, "%lu", MCP_temp); This will fill OutputString with more than one character(!!!) thus clobbering your stack

                 

              I2C: set byte mode.

                 

              See attaced project. Take care not to overwrite your original.

                 

               

                 

              Bob

              • 4. Re: I2C Get Byte, Print over UART
                vkaiser_1860311

                Bob,

                   

                Thank you - I see that's a much more efficient way to get multiple bytes out.

                   

                Thank you also for your help and comments in the data types for the variables, and the functions.  I did try to use pointers while I was trying to figure this out, piecing together different examples.

                   

                I'm happy to share that thanks to your help and explanations, I am reporting correct temperatures.  I look forward to expanding the project (and also possibly not putting as many projects into a workspace?)

                   

                Cheers!

                • 5. Re: I2C Get Byte, Print over UART
                  user_1377889

                  You are always welcome!

                     

                   

                     

                  Bob

                  • 6. Re: I2C Get Byte, Print over UART
                    mfarkas_1728531

                    okeee, i downloaded the code and copied it and it worked once, after i powered on and off the slave i'm trying to talk to... but once i stop the program (Psoc creator 4) and restart i get strange errors of "master not ready" from the sendstart command; upon trying it again, sometimes get a 1 ("master lost arbitration")... i don't understand how the "master" can not be ready when the only commands are:

                       

                       I2C_2_Start();    
                        CyGlobalIntEnable;

                       

                    errStat = I2C_2_I2CMasterSendStart(0x77,I2C_2_I2C_WRITE_XFER_MODE); // this is where i get a 4 or a 1 for errStat

                       

                    errStat = I2C_2_I2CMasterWriteByte(0xE0);        // register with device ID

                       

                    errStat = I2C_2_I2CMasterSendRestart(0x77,I2C_2_I2C_READ_XFER_MODE);

                       

                    byteRead = I2C_2_I2CMasterReadByte(I2C_2_I2C_ACK_DATA) & 0x00ff;    
                    byteRead |= (I2C_2_I2CMasterReadByte(I2C_2_I2C_NAK_DATA) <<8) & 0x00ff;    

                       

                    thanks for your posts

                    • 7. Re: I2C Get Byte, Print over UART
                      user_1377889

                      @mfarkas: Welcome in the forum.

                         

                      Can you please post your complete project, so that we all can have a look at all of your settings. To do so, use
                      Creator->File->Create Workspace Bundle (minimal)
                      and attach the resulting file. Additionally a link to the datasheet of the device you want to talk to.

                         

                       

                         

                      Bob

                      • 8. Re: I2C Get Byte, Print over UART
                        mfarkas_1728531

                        wow... fast response...

                           

                        the data sheet has a watermark that reads "confidential", so i reckon i shouldn't attach it... 

                           

                        btb, i re-ran it again, and even after resetting the device i got the "master lost arbitration" (a 1) error when trying to execute the restart

                           

                        thanks for your help

                        • 9. Re: I2C Get Byte, Print over UART
                          mfarkas_1728531

                          it mentions this to perform a read:

                             

                          1. Write the slave address followed by the Write flag 1’b0
                          2. Write the register address followed by a Stop instruction
                          3. Write the slave address followed by the Read flag 1’b1
                          4. Read as many data bytes while the internal sub-address is auto-incremented

                             

                          i assume 1. is sendstart, 2. is writebyte, sendrestart (have tried a stop as well here) 3. is readbyte

                          • 10. Re: I2C Get Byte, Print over UART
                            user_1377889

                            Set I2C to byte mode.

                               

                            Insert an infinite loop at end of main() to hinder a restart of the project.

                               

                            The error can be caused by bad hardware / pullup resistors / wrong I2C address. Best is to use a logic analyzer to watch the communication.

                               

                             

                               

                            Bob

                            • 11. Re: I2C Get Byte, Print over UART
                              mfarkas_1728531

                              thanks very much... i checked byte mode; i'll investigate the hardware... if i reset (unplug and plug) the psoc and power off and on the slave, the thing seems to read from it, but not expected data...

                                 

                              thanks again

                                 

                              matt