Other Parts Discussed in Thread: LAUNCHXL-F28027F, C2000WARE, , ENERGIA
Tool/software:
Can any one help me to work on i2c interface using bmp sensor of C2000 piccolo Launchxl-f28027f i have tried many way not getting please check
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software:
Can any one help me to work on i2c interface using bmp sensor of C2000 piccolo Launchxl-f28027f i have tried many way not getting please check
Hi Kishor,
As a starting point, you can refer to the I2C EEPROM example as a starting point for interfacing with a sensor. If you have any specific questions on the implementation, let me know and I can help.
C:\ti\c2000\C2000Ware_5_04_00_00\device_support\f2802x\examples\structs\i2c_eeprom
Best Regards,
Aishwarya
Hi Aishwarya Rajesh
"I've written the logic to interface the BMP280 sensor with the TMS320F28027F using I2C, but I'm not getting any output. Please take a look at the code and let me know what might be wrong."
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <stdio.h> // For sprintf
#include <stdint.h> // For uint8_t, int16_t, etc.
// BMP280 Definitions
#define BMP280_ADDR 0x76 // BMP280 I2C address (0x76 if SDO is low, 0x77 if SDO is high)
#define BMP280_CALIB_DATA_SIZE 24
// BMP280 Calibration Data
uint16_t dig_T1;
int16_t dig_T2, dig_T3;
uint16_t dig_P1;
int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
// Global variable for fine temperature calculation
int32_t t_fine;
// Function Prototypes
void InitI2C(void);
void BMP280_Init(void);
void I2C_Write(uint8_t slave_addr, uint8_t reg_addr, uint8_t data);
void I2C_Read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
void BMP280_ReadCalibrationData(void);
void BMP280_ReadData(float *temperature, float *pressure);
float compensate_T(int32_t adc_T);
float compensate_P(int32_t adc_P);
void InitSCI(void);
void SCI_Print(char *str);
// Main Function
void main(void)
{
float temperature, pressure;
char buffer[50]; // Buffer to store formatted strings
// Initialize system
InitSysCtrl(); // Initialize the system control
InitI2C(); // Initialize I2C for BMP280 communication
InitSCI(); // Initialize SCI for UART communication
// Test UART communication
SCI_Print("Hello, BMP280!\n");
// Initialize BMP280 sensor
BMP280_Init();
BMP280_ReadCalibrationData(); // Read calibration data from BMP280
while (1)
{
// Read temperature and pressure from BMP280
BMP280_ReadData(&temperature, &pressure);
// Format and send temperature data
sprintf(buffer, "Temperature: %.2f °C\n", temperature);
SCI_Print(buffer);
// Format and send pressure data
sprintf(buffer, "Pressure: %.2f Pa\n", pressure);
SCI_Print(buffer);
DELAY_US(1000000); // Delay for 1 second
}
}
// Initialize I2C module
void InitI2C(void)
{
// Enable I2C peripheral clock
SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1;
// Configure I2C pins (GPIO32 as SDA and GPIO33 as SCL)
EALLOW;
GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0; // Enable pull-up for SDA (GPIO32)
GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0; // Enable pull-up for SCL (GPIO33)
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 as I2C SDA
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 as I2C SCL
EDIS;
// Initialize I2C
I2caRegs.I2CMDR.all = 0x0000; // Put I2C in reset state
I2caRegs.I2CPSC.all = 6; // Prescaler for 12.5 MHz SYSCLK
I2caRegs.I2CCLKL = 10; // Low time = 10 * I2CPSC
I2caRegs.I2CCLKH = 10; // High time = 10 * I2CPSC
I2caRegs.I2CMDR.all = 0x0020; // Master mode, 7-bit address, free data format
}
// Initialize BMP280 sensor
void BMP280_Init(void)
{
// Set oversampling and mode
I2C_Write(BMP280_ADDR, 0xF4, 0x27); // Control measurement register: x1 temp, x1 pressure, normal mode
I2C_Write(BMP280_ADDR, 0xF5, 0x00); // Configuration register: filter off, standby time 0.5ms
}
// Write to BMP280 register
void I2C_Write(uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
I2caRegs.I2CSAR = slave_addr; // Set slave address
I2caRegs.I2CCNT = 2; // Set byte count (register address + data)
I2caRegs.I2CDXR = reg_addr; // Load register address
I2caRegs.I2CDXR = data; // Load data
I2caRegs.I2CMDR.all = 0x6E20; // Start condition, master transmitter mode
uint16_t timeout = 10000; // Timeout counter
while (I2caRegs.I2CSTR.bit.ARDY == 0 && timeout--); // Wait for stop condition
if (timeout == 0) {
SCI_Print("I2C Write Timeout!\n");
}
}
// Read from BMP280 register
void I2C_Read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length)
{
I2caRegs.I2CSAR = slave_addr; // Set slave address
I2caRegs.I2CCNT = 1; // Set byte count for register address
I2caRegs.I2CDXR = reg_addr; // Load register address
I2caRegs.I2CMDR.all = 0x6E20; // Start condition, master transmitter mode
uint16_t timeout = 10000; // Timeout counter
while (I2caRegs.I2CSTR.bit.ARDY == 0 && timeout--); // Wait for stop condition
if (timeout == 0) {
SCI_Print("I2C Read Address Timeout!\n");
}
I2caRegs.I2CCNT = length; // Set byte count for data
I2caRegs.I2CMDR.all = 0x2C20; // Start condition, master receiver mode
unsigned char i; // Declare loop variable
for (i = 0; i < length; i++) {
timeout = 10000; // Reset timeout for each byte
while (I2caRegs.I2CSTR.bit.RRDY == 0 && timeout--); // Wait for receive ready
if (timeout == 0) {
SCI_Print("I2C Read Data Timeout!\n");
break;
}
data[i] = I2caRegs.I2CDRR; // Read data
}
}
// Read BMP280 calibration data
void BMP280_ReadCalibrationData(void)
{
uint8_t calib_data[BMP280_CALIB_DATA_SIZE];
I2C_Read(BMP280_ADDR, 0x88, calib_data, BMP280_CALIB_DATA_SIZE);
dig_T1 = (calib_data[1] << 8) | calib_data[0];
dig_T2 = (calib_data[3] << 8) | calib_data[2];
dig_T3 = (calib_data[5] << 8) | calib_data[4];
dig_P1 = (calib_data[7] << 8) | calib_data[6];
dig_P2 = (calib_data[9] << 8) | calib_data[8];
dig_P3 = (calib_data[11] << 8) | calib_data[10];
dig_P4 = (calib_data[13] << 8) | calib_data[12];
dig_P5 = (calib_data[15] << 8) | calib_data[14];
dig_P6 = (calib_data[17] << 8) | calib_data[16];
dig_P7 = (calib_data[19] << 8) | calib_data[18];
dig_P8 = (calib_data[21] << 8) | calib_data[20];
dig_P9 = (calib_data[23] << 8) | calib_data[22];
}
// Read temperature and pressure data from BMP280
void BMP280_ReadData(float *temperature, float *pressure)
{
uint8_t data[6];
I2C_Read(BMP280_ADDR, 0xF7, data, 6); // Read pressure and temperature data
int32_t adc_P = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
int32_t adc_T = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
*temperature = compensate_T(adc_T);
*pressure = compensate_P(adc_P);
}
// Temperature compensation formula
float compensate_T(int32_t adc_T)
{
int32_t var1, var2;
var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
t_fine = var1 + var2; // Update t_fine for pressure compensation
return (t_fine * 5 + 128) >> 8; // Return temperature in °C
}
// Pressure compensation formula
float compensate_P(int32_t adc_P)
{
int64_t var1, var2, p;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)dig_P6;
var2 = var2 + ((var1 * (int64_t)dig_P5) << 17);
var2 = var2 + ((int64_t)dig_P4 << 35);
var1 = ((var1 * var1 * (int64_t)dig_P3) >> 8) + ((var1 * (int64_t)dig_P2) << 12);
var1 = (((int64_t)1 << 47) + var1) * ((int64_t)dig_P1) >> 33;
if (var1 == 0) return 0; // Avoid division by zero
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = ((int64_t)dig_P9 * (p >> 13) * (p >> 13)) >> 25;
var2 = ((int64_t)dig_P8 * p) >> 19;
p = ((p + var1 + var2) >> 8) + ((int64_t)dig_P7 << 4);
return (float)p / 256.0; // Return pressure in Pa
}
// Initialize SCI for UART communication
void InitSCI(void)
{
// Enable SCI peripheral clock
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1;
// Configure SCI pins
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0; // Enable pull-up for SCITXDA (GPIO28)
GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0; // Enable pull-up for SCIRXDA (GPIO29)
GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; // Configure GPIO28 as SCITXDA
GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; // Configure GPIO29 as SCIRXDA
EDIS;
// Initialize SCI
SciaRegs.SCICCR.all = 0x0007; // 1 stop bit, no parity, 8-bit data, idle-line protocol
SciaRegs.SCICTL1.all = 0x0003; // Enable TX and RX, internal SCICLK
SciaRegs.SCIHBAUD = 0x0001; // Baud rate = 9600 (for 12.5 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x00E7;
SciaRegs.SCICTL1.all = 0x0023; // Relinquish SCI from reset
}
// Print a string via SCI
void SCI_Print(char *str)
{
while (*str) {
while (SciaRegs.SCICTL2.bit.TXRDY == 0); // Wait for TX ready
SciaRegs.SCITXBUF = *str++; // Send character
}
}
Kishor,
While I can't review code, let me know if you are seeing any output on the GPIOs or nothing at all? If there is no output on the pins, please take a look at the GPIO configurations and the physical connections between MCU and EEPROM. If there is output, then we can look at code configurations further. Please point me towards the specific portion of your code there may be an issue.
Here is a thread that could be relevant: (+) TMS320F28027F: I2C sets Stop condition without being commanded to - C2000 microcontrollers forum - C2000︎ microcontrollers - TI E2E support forums. There could be other E2Es as well on the forum that could be helpful.
Best Regards,
Aishwarya
Hi Aishwarya Rajesh,
Referred the I2C EEPROM example instead of using external EEPROM i used BMP280 sensor and changed the slave address in the code. And also implemented the sci for debug prints. in that code just i implemented the i2c scanner code to found the i2c device connected by checking the loop from 0 to 128 devices. As bmp sensor, if i connected the SDO pin to ground it should get the 0x76 or if i connect to VCC it should get 0x77. it is not founding. why this actually all the initialization is done in the code.
https://github.com/ebrezadev/BMP280-Barometric-Pressure-and-Temperature-Sensor-C-Driver/tree/main
https://github.com/kiranj26/C2000-Piccolo-F28027F-Projects/tree/main/examples/I2C/I2C_Master
The device is not found properly
This is my bmp_low_level.c contains the read and write function.
/*BMP280 barometric pressure and temperature sensor C Driver*/
/*Reza Ebrahimi - https://github.com/ebrezadev */
/*Version 1.0*/
#include "bmp280.h"
#include "sci.h"
#include "i2c.h"
//#include "DSP28x_Project.h"
/* Writes an array (data[]) of arbitrary size (dataLength) to I2C address (deviceAddress),
starting from an internal register address (startRegisterAddress) */
void bmp280_write_array(uint8_t deviceAddress, uint8_t startRegisterAddress, uint8_t *data, uint8_t dataLength)
{
uint8_t i;
EALLOW;
// Enable I2C0 for writing
I2caRegs.I2CMDR.bit.IRS = 1; // Set to idle state
I2caRegs.I2CSAR = deviceAddress; // Set I2C device address
I2caRegs.I2CCNT = dataLength + 1; // Set number of bytes to send (register + dataLength)
// Write start register address
I2caRegs.I2CDXR = startRegisterAddress;
for (i = 0; i < I2caRegs.I2CCNT; i++) {
I2caRegs.I2CDXR = data[i]; // Write the data byte
}
// Start the I2C communication
I2caRegs.I2CMDR.bit.IRS = 0; // Initiate the transfer
if (I2caRegs.I2CSTR.bit.BB == 1) {
}
if (I2caRegs.I2CSTR.bit.SCD == 1) {
}
EDIS;
}
void bmp280_read_array(uint8_t deviceAddress, uint8_t startRegisterAddress, uint8_t *data, uint8_t dataLength)
{
uint8_t i;
uint32_t timeout = 200000; // Set a higher timeout for read operation
EALLOW;
// Step 1: Write the register address (e.g., 0xD0 for chip ID)
bmp280_write_array(deviceAddress, startRegisterAddress, NULL, 0); // Write operation to select the register
// Step 2: Perform a repeated start (restart the I2C bus to prepare for reading)
I2caRegs.I2CMDR.bit.STT = 1; // Initiate a restart condition (repeated start)
// Wait for the I2C communication to complete
timeout = 10000; // Set timeout for wait after start condition
while (I2caRegs.I2CSTR.bit.BB == 1 && timeout > 0) { // Wait for the bus to be free (BB = bus busy)
timeout--;
}
if (timeout == 0) {
scia_msg("\r\nI2C bus busy, cannot start read operation.\0");
EDIS;
return;
}
// Step 3: Set up the I2C communication for reading data
I2caRegs.I2CSAR = deviceAddress; // Set I2C device address
I2caRegs.I2CCNT = dataLength; // Set number of bytes to read
I2caRegs.I2CMDR.bit.IRS = 0; // Start I2C communication for read operation
// Step 4: Wait for the data to be ready and read the data byte by byte
for (i = 0; i < dataLength; i++) {
timeout = 200000; // Adjust timeout limit as needed
// Wait for data to be ready
while (I2caRegs.I2CSTR.bit.RRDY != 1 && timeout > 0) {
timeout--;
}
if (timeout == 0) {
scia_msg("\r\nRead operation timeout.\0");
EDIS;
return;
}
// Read the data from the I2C data register
data[i] = I2caRegs.I2CDRR;
}
// Step 5: End of I2C read operation
scia_msg("\r\nRead operation successful.\0");
EDIS;
}
/* A delay function for milliseconds delay */
void delay_function(uint32_t delayMS)
{
uint32_t i;
for (i = 0; i < delayMS; i++) {
asm(" NOP"); // No operation (to create a small delay)
}
}
/* Implements a power function (used in altitude calculation) */
float power_function(float x, float y)
{
return power_function(x, y);
}
This is my main.c
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "clk.h"
#include "gpio.h"
#include "sci.h"
#include "i2c.h"
//// Function Prototypes
void scia_echoback_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(char *msg);
void scia_receive_string(char *buf, uint16_t max_len);
// Globals
CLK_Handle myClk;
GPIO_Handle myGpio;
SCI_Handle mySci;
I2C_Handle i2cHandle;
// Main
void main(void)
{
InitSysCtrl();
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
i2cHandle = I2C_init((void *)I2CA_BASE_ADDR, sizeof(I2C_Obj));
mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
// Initialize GPIO
InitI2CGpio();
GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);
GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);
GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);
scia_echoback_init(); // Initialize SCI for echoback
scia_fifo_init(); // Initialize the SCI FIFO
scia_msg("\r\nI2C PROGRAM START: \0");
I2C_Init();
while(1){
bmp280_init(); }
}
/* Initiates the I2C peripheral and sets its speed */
void I2C_Init(void) {
// Initialize I2C module
I2caRegs.I2CMDR.all = 0; // Reset I2C
I2caRegs.I2CPSC.all = 9; // Prescaler, set for 100kHz at 60MHz
I2caRegs.I2CCLKL = 10; // Set SCL low time
I2caRegs.I2CCLKH = 5; // Set SCL high time
I2caRegs.I2CMDR.bit.FREE = 1; // Free run mode
I2caRegs.I2CMDR.bit.MST = 1; // Set as master
I2caRegs.I2CMDR.bit.IRS=1; // Enable I2C
scia_msg("\r\nI2C_INITIALIZATION COMPLETED: \0");
}
//// I2C Scanner Function
//void I2C_Scanner(void)
//{
// uint32_t timeout = 10; // Timeout counter
// uint8_t deviceAddress=100;
// for(deviceAddress;deviceAddress<128;deviceAddress++)
// {
// I2caRegs.I2CSAR = deviceAddress;// Set the slave address
//
// // Send a start condition
// I2caRegs.I2CMDR.bit.STT = 1; // Set start condition bit
//
// // Wait for the start condition to complete
// while (I2caRegs.I2CSTR.bit.BB == 1 && timeout > 0)
// {
// timeout--;
// }
//
// if (timeout == 0)
// {
// // Timeout occurred
// scia_msg("I2C start condition timeout.\r\n");
// return;
// }
//
// // Check if the device responded
// if (I2caRegs.I2CSTR.bit.NACK == 0)
// {
// // Device found
// deviceAddress;
// scia_msg("\r\nDevice found: \0");
// }
//
// // Send a stop condition
// I2caRegs.I2CMDR.bit.STP = 1; // Set stop condition bit
//
// // Wait for the stop condition to complete
// while (I2caRegs.I2CSTR.bit.BB == 1); // Wait for bus to be free
//}
//}
// Initialize SCI for echo-back communication
void scia_echoback_init()
{
CLK_enableSciaClock(myClk);
SCI_disableParity(mySci);
SCI_setNumStopBits(mySci, SCI_NumStopBits_One);
SCI_setCharLength(mySci, SCI_CharLength_8_Bits);
SCI_enableTx(mySci);
SCI_enableRx(mySci);
SCI_enableTxInt(mySci);
SCI_enableRxInt(mySci);
#if (CPU_FRQ_60MHZ)
SCI_setBaudRate(mySci, (SCI_BaudRate_e)194);
#elif (CPU_FRQ_50MHZ)
SCI_setBaudRate(mySci, (SCI_BaudRate_e)162);
#elif (CPU_FRQ_40MHZ)
SCI_setBaudRate(mySci, (SCI_BaudRate_e)129);
#endif
SCI_enable(mySci);
return;
}
//scia_xmit - Transmit a character from the SCI
void scia_xmit(int a)
{
while(SCI_getTxFifoStatus(mySci) != SCI_FifoStatus_Empty)
{
}
SCI_putDataBlocking(mySci, a);
}
// scia_msg - Send a string via SCI
void scia_msg(char *msg)
{
int i = 0;
while(msg[i] != '\0')
{
scia_xmit(msg[i]);
i++;
}
}
// scia_fifo_init - Initialize the SCI FIFO
void scia_fifo_init()
{
SCI_enableFifoEnh(mySci);
SCI_resetTxFifo(mySci);
SCI_clearTxFifoInt(mySci);
SCI_resetChannels(mySci);
SCI_setTxFifoIntLevel(mySci, SCI_FifoLevel_Empty);
SCI_resetRxFifo(mySci);
SCI_clearRxFifoInt(mySci);
SCI_setRxFifoIntLevel(mySci, SCI_FifoLevel_4_Words);
return;
}
// scia_receive_string - Receive a string over SCI
void scia_receive_string(char *buf, uint16_t max_len)
{
uint16_t index = 0;
uint16_t receivedChar;
// Receive characters until we hit max_len or a newline/return character
while(index < (max_len - 1))
{
while(SCI_getRxFifoStatus(mySci) < SCI_FifoStatus_1_Word)
{
// Wait for data to be available in the RX FIFO
}
receivedChar = SCI_getData(mySci); // Get the received character
if(receivedChar == '\r' || receivedChar == '\n') // Newline/return ends the string
{
buf[index] = '\0'; // Null-terminate the string
break;
}
else
{
buf[index] = receivedChar; // Store the character
index++;
}
}
if (index == (max_len - 1)) // Ensure null-termination if max_len is reached
{
buf[index] = '\0';
}
}
Kishor,
Could you confirm if you are seeing any output on the scope and share what you are seeing. I am not clear on that point. Also, make sure you have a pull up resistor connecting SDA and SCL to VDDIO at around 2.2 kOhms. Refer to this App Note for some more information as well: Interfacing EEPROM Using C2000 I2C Module
Please also give me 1-2 days to look into this further and get back to you.
Best Regards,
Aishwarya
HI Aishwarya Rajesh,
I'm using 4.7kOhms pull up resistor connecting SDA and SCL to VCC .
output iam seeing

read operation is timeout in bmp_low_level.c.
Kishor,
Can you send an image of the reading on the oscilloscope.
Best Regards,
Aishwarya
Kishor,
Let me look into this further and get back to you.
Best Regards,
Aishwarya
Kishor,
Try referring to these threads and let me know if you have any further questions:
28027F external control through I2C - motor control
CCS/LAUNCHXL-F28027: How to establish I2C communication between LAUNCHXL-F28027 and MCP9808?
Best Regards,
Aishwarya
Hi Aishwarya Rajesh,
Thanks for this response i have detected bmp280 sensor chip id (i2c detected ) by this thread and now working on get bmp sensor data if any issues i will get back to you.
Kishor,
Glad to hear, let me know if you have any other questions, and/or please mark this thread as resolved accordingly.
Best Regards,
Aishwarya