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.

Tiva C TM4C123G i2c with Bosch BMP085 pressure and temeperature sensor communication problem?

Hi,

I want to experience i2c communication and simplly read a value from the sensor. I wrote a code but it seams it does not work. Here is the i2c pice of code;

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

//
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
HWREG(I2C0_BASE + I2C_O_MCR) |= 0x01;
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);


I2CMasterSlaveAddrSet(I2C0_BASE, 0x77, false);//Here slave address configured in write mode of master
I2CMasterDataPut(I2C0_BASE,0xAA);//0xAA put to transmision
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);// and sent
I2CMasterSlaveAddrSet(I2C0_BASE, 0x77, true);//read mode
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);// receive data comes from slave

Register 0xAA refers to a calibration constant, I just want to read to be sure it communicates in proper way.

When I put 0xAA in debuger mod I am checking the MDR register but it contents does not change with 0xAA where is the mistake what should be the right way of doing such thing. 

I already red looked to 3 i2c example files and wrote this, but it doesnt work.

Thansk for reading.

  • Arden Kuyumcu said:
    HWREG(I2C0_BASE + I2C_O_MCR) |= 0x01;

    Sets, the I2C in loopback mode. Do work with your code without this.

    -kel

  • Doesn2T I need to enable the master module somehow? What is actually the loopback mode?

  • Arden,

    What I meant was work with your code without the I2C loopback line. Here below is what is mentioned about I2C loopback in the datasheet. 

    The I2C modules can be placed into an internal loopback mode for diagnostic or debug work by
    setting the LPBK bit in the I2C Master Configuration (I2CMCR) register. In loopback mode, the
    SDA and SCL signals from the master and are tied to the SDA and SCL signals of the slave module to allow internal testing of the device without having to go through I/O.

    -kel

  • I got it. Thanks. But I wonder why after the I2CMasterDataPut(0xAA); line the MDR register doesnt set as 0xAA. Am I doing wrong. I removed the loopback line btw.

    How can I read values from the sensor can you write  a piece of code. It says write 2E to register F4 and it transmits from F6 and F7 as msb and lsb respectively.

    regards

  • Hello Arden

    After the following line

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);// and sent

    you need to put

    while(!I2CMasterBusy(I2C0_BASE); to ensure that the command is sent and then move to the next I2CMasterControl.

    As for the MDR register when it is read it returns the read buffer data which contains the data for I2C Read Operation. MDR register should be treated as Entry point for the Read and Write Data Buffers in I2C Peripheral.

    Regards

    Amit

  • int bmp085ReadInt(unsigned char address)
    {
    unsigned char msb, lsb;

    I2CMasterSlaveAddrSet(I2C0_BASE, BMP085_ADDRESS, false);
    I2CMasterDataPut(I2C0_BASE,address);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterSlaveAddrSet(I2C0_BASE, BMP085_ADDRESS, true);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    msb = I2CMasterDataGet(I2C0_BASE);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    lsb = I2CMasterDataGet(I2C0_BASE);
    return (int) msb<<8 | lsb;
    }

    bmp085ReadInt(0xAA)

    it stucks in the first while loop.

    When I use this function I need to read the value from AA and AB. What can I do to change the code to achive my goal.

    MDR updates when receives (I don't sure it gets right thing) but dosen't update when MasterDataPut is used.

  • Hello Arden,

    Change in the code

    int bmp085ReadInt(unsigned char address)
    {
    unsigned char msb, lsb;

    I2CMasterSlaveAddrSet(I2C0_BASE, BMP085_ADDRESS, false);
    I2CMasterDataPut(I2C0_BASE,address);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    while(!I2CMasterBusy(I2C0_BASE));
    while(I2CMasterBusy(I2C0_BASE));


    I2CMasterSlaveAddrSet(I2C0_BASE, BMP085_ADDRESS, true);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    while(!I2CMasterBusy(I2C0_BASE));
    while(I2CMasterBusy(I2C0_BASE));


    msb = I2CMasterDataGet(I2C0_BASE);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    while(!I2CMasterBusy(I2C0_BASE));
    while(I2CMasterBusy(I2C0_BASE));

     


    lsb = I2CMasterDataGet(I2C0_BASE);
    return (int) msb<<8 | lsb;
    }

    Secondly, do you have Pull Up in the I2C Lines?

    Thirdly, the MDR register when written will access the Write Buffer. When it is read then it will not read the "Write Buffer" but the read buffer.

    Lastly,

    Can you probe the I2C SCL and SDA line on a scope/LA and see if the transaction is happening?

    Regards

    Amit

  • A mít has an interesting point with the first while waiting for the I2C to become busy.

    However, there may be a risk that the condition is never met when single stepping through the code, right?

    As much as I hate fixed delays perhaps few NOPs could do the trick here if there is a small latency before the master becomes busy. Opinion?

    Thanks, Martin

  • Hello Martin

    Yes, adding a SysCtlDelay could do the trick, but it would not scale well with Frequency, when moving the code. A bit larger delay of 100 would be good though.

    Regards

    Amit

  • I add the while loop without "!" it solves my problem. Thank you.