Okay, here is the code that I used to be able to use the SDK's I2C library to communicate with the LM75 on the OM40001 LPCXpresso804 development board.
Create a project and use the ConfigTools to enable the Peripheral Signals to include I2C0. Then setup PIO0_7 with pin identifier I2C_SDA, and PIO0_14 with pin identifier I2C_SCL.
First make sure you include the i2c header file. When you make you project and select the pins for I2C, it may add this already:
#include "fsl_i2c.h" // For I2C calls
After the includes, add this glob:
#define I2C_MASTER_BASE (I2C0_BASE)
#define I2C_MASTER_CLOCK_FREQUENCY (12000000)
#define I2C_MASTER ((I2C_Type *)I2C_MASTER_BASE)
#define I2C_BAUDRATE 100000U
#define I2C_DATA_LENGTH 16U // Used to set the size of the buffers
i2c_master_config_t masterConfig;
uint8_t g_master_txBuff[I2C_DATA_LENGTH];
uint8_t g_master_rxBuff[I2C_DATA_LENGTH];
// The OM40001 documentation says: NXP LM75BDP temperature sensor
// JP4 and JP23 need to be installed, which they are by default
// Temperature sensor (LM75, circuit ref U7)
// The I2C address is 0x1001100.
// From I2C_temperature_main.c
//#define LM75_ADDR (0x90 >> 1) // = 0x48 72d ('H')
#define LM75_ADDR 0x48 // Should be the same as (0x90 >> 1)
#define LM75_CONFIG 0x01
#define LM75_TEMPERATURE 0x00
int32_t init_LM75(void);
uint32_t read_LM75(void);
In main() after BOARD_InitBootPeripherals() you want to add this glob:
BOARD_InitI2CPins(); // Enable the I2C pins
CLOCK_Select(kI2C0_Clk_From_MainClk); // Select the main clock as the source clock for I2C0
I2C_MasterGetDefaultConfig(&masterConfig); // Load the default values into masterConfig
masterConfig.baudRate_Bps = I2C_BAUDRATE; // Change the default baudrate in the configuration to our value
I2C_MasterInit(I2C_MASTER, &masterConfig, I2C_MASTER_CLOCK_FREQUENCY); // Initialize the I2C master peripheral using our masterConfig
init_LM75(); // Initialize the sensor
I created two functions related to the LM75. init_LM75() and read_LM75(). Here they are:
int32_t init_LM75(void)
{
status_t retVal = kStatus_Fail;
// The write only process is done by:
// I2C_MasterStart()
// I2C_MasterWriteBlocking() with kI2C_TransferDefaultFlag flag
// I2C_MasterStop()
if (kStatus_Success == I2C_MasterStart(I2C_MASTER, LM75_ADDR, kI2C_Write))
{
g_master_txBuff[0] = LM75_CONFIG;
g_master_txBuff[1] = 0x00; // Set the default operating mode
retVal = I2C_MasterWriteBlocking(I2C_MASTER, g_master_txBuff, 2, kI2C_TransferDefaultFlag);
if (retVal != kStatus_Success)
{
return -1;
}
retVal = I2C_MasterStop(I2C_MASTER);
if (retVal != kStatus_Success)
{
return -1;
}
retVal = kStatus_Success;
}
return(retVal);
}
uint32_t read_LM75(void)
{
status_t retVal = kStatus_Fail;
uint8_t deviceAddress = LM75_TEMPERATURE;
memset(g_master_rxBuff, 0, I2C_DATA_LENGTH);
// The combination write/read is done by:
// I2C_MasterStart()
// I2C_MasterWriteBlocking() with kI2C_TransferNoStopFlag flag
// I2C_MasterRepeatedStart()
// I2C_MasterReadBlocking() with kI2C_TransferDefaultFlag flag
// I2C_MasterStop()
if (kStatus_Success == I2C_MasterStart(I2C_MASTER, LM75_ADDR, kI2C_Write))
{
// We're writing one byte, the register value of 0x00 to immediately read temperature data from.
// We set the flag to kI2C_TransferNoStopFlag since we're doing a read right after this.
retVal = I2C_MasterWriteBlocking(I2C_MASTER, &deviceAddress, 1, kI2C_TransferNoStopFlag);
if (retVal != kStatus_Success)
{
return -1;
}
retVal = I2C_MasterRepeatedStart(I2C_MASTER, LM75_ADDR, kI2C_Read);
if (retVal != kStatus_Success)
{
return -1;
}
// Now we're reading two bytes of the temperature data from the slave device, into g_master_rxBuff
retVal = I2C_MasterReadBlocking(I2C_MASTER, g_master_rxBuff, 2, kI2C_TransferDefaultFlag);
if (retVal != kStatus_Success)
{
return -1;
}
retVal = I2C_MasterStop(I2C_MASTER);
if (retVal != kStatus_Success)
{
return -1;
}
}
uint32_t temperatureValue = 0;
// NXP's LM75B data sheet shows the format of the data https://www.nxp.com/docs/en/data-sheet/LM75B.pdf
if ((g_master_rxBuff[0] & 0x80) > 0) { // This is the sign bit
temperatureValue = 0xffffff00;
}
temperatureValue |= (g_master_rxBuff[0] & 0x7f) << 1;
temperatureValue |= ((g_master_rxBuff[1] >> 7) & 1);
// Since we're not using the half degrees, just shift right by one and lose that piece of data
temperatureValue = temperatureValue >> 1;
return(temperatureValue);
}
The code we added in main() already called init_LM75() and you just need to call read_LM75() when you want to read the temperature. (You may not need to call init_LM75() as the sensor seems to startup in the correct mode to begin with.) My demo program just calls read_LM75() from a one second interval SysTick_Handler() and uses this code to display the value:
int32_t temperatureReading = read_LM75();
char console_string[128];
// Bit 16 is the sign (1 is negative, 0 is positive) after the temperature conversion
if (temperatureReading & 0x10000) {
snprintf(console_string, 128, "Current temperature is -%d degrees C.\r\n", (temperatureReading & 0xFFFF));
}
else {
uint16_t temperature_farenheit = (temperatureReading * 9 / 5) + 32; // Create the farenheit temperature value for positive temperatures
snprintf(console_string, 128, "Current temperature is %d degrees C and %d degrees F.\r\n", temperatureReading, temperature_farenheit);
}
PutTerminalString(USART0, (unsigned char *)console_string);
I'm not doing much in the way of checking return values, but you should get the idea. The PutTerminalString() function above is just a function that I'm using to send the string out on the USART0 port that I'm using. Replace it with whatever diagnostic print that you're using.
Enjoy!