You are here

I2C Get Byte, Print over UART | Cypress Semiconductor

I2C Get Byte, Print over UART

Summary: 11 Replies, Latest post by mfarkas_1728531 on 16 Nov 2016 01:38 PM PST
Verified Answers: 1
Last post
Log in to post new comments.
vkaiser_1860311's picture
User
3 posts

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 */
user_1377889's picture
User
9572 posts

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

 

vkaiser_1860311's picture
User
3 posts

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.  

user_1377889's picture
User
9572 posts

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

 

 

vkaiser_1860311's picture
User
3 posts

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!

user_1377889's picture
User
9572 posts

You are always welcome!

 

Bob

mfarkas_1728531's picture
User
6 posts

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

 

user_1377889's picture
User
9572 posts

@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

mfarkas_1728531's picture
User
6 posts

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

mfarkas_1728531's picture
User
6 posts

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

user_1377889's picture
User
9572 posts

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

Log in to post new comments.