- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 */
Solved! Go to Solution.
- Labels:
-
BLE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are always welcome!
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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