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