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.

DK-TIVA4C129x TMP100 sensor I2C

Other Parts Discussed in Thread: TMP100

Hi,

I have Tiva4C129x development kit. It has TMP100 temperature sensor which has I2C.

My purpose is to learn I2C and read the temperature from the sensor.

I have wrote a dummy code which explains the procedure in which one should configure I2C and start the communication.

SCL and SDA is located on PB6 and PB7 on TIVA. Also it uses I2C6 module which is connected to TMP100.

I have read the datasheet of both device and from that what I have understood I wrote the code.

Please note that I'm just focusing on the procedure and dont worry about debugging the code right now. I'm using 25MHz crystal.

I'm bit confused in configuring the TMP100 registers. It has 5 registers in total. Pointer Reg, Configuration Reg, Temperate High and Low Reg, Temperature Register. The last one stores the conversion result.

Also I'm not sure if I'm waiting for acknowledgement correctly or not. Please correct me if I'm wrong.

Here is the code.

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"

#define SLAVE_ADDRESS 0x4A
void main()
{
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_25MHZ);
				   
	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	
	GPIOPinConfigure(GPIO_PB6_I2C6SCL);
    GPIOPinConfigure(GPIO_PB7_I2C6SDA);
	
	GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_6);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);
	
	I2CMasterInitExpClk(I2C6_BASE, SysCtlClockGet(), false);	//initialization of master module
	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);		//sets the slave address and indicate that the master is reading from slave
	
	I2CMasterDataPut(I2C6_BASE, 0x01);					//P1 P0 = 01 = configuration reg. Byte goes to PR
	while(I2CMasterBusy(I2C6_BASE));    //is it correct?
	I2CMasterDataPut(I2C6_BASE, 0xA1);					//sets the bits of configuration reg. A1 = 10 bit, shutdown, OS=1 start conv. Byte goes to Config Reg
	while(I2CMasterBusy(I2C6_BASE));
	
	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);	//selects the pointer reg
	while(I2CMasterBusy(I2C6_BASE));	
	I2CMasterDataPut(I2C6_BASE, 0x03);					//P1P0= 11 = Temp high reg. Byte goes to PR
	while(I2CMasterBusy(I2C6_BASE));	
	I2CMasterDataPut(I2C6_BASE, 0x640);					//sets the Thigh reg = 100C. Byte goes to Thigh
	
	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);	//selects the pointer reg
	while(I2CMasterBusy(I2C6_BASE));	
	I2CMasterDataPut(I2C6_BASE, 0x02);					//P1P0= 10 = Temp low reg. Byte goes to PR
	while(I2CMasterBusy(I2C6_BASE));	
	I2CMasterDataPut(I2C6_BASE, 0x640);					//sets the Tlow reg = -25C. Byte goes to Tlow
	while(I2CMasterBusy(I2C6_BASE));	
	
	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);  //selects the pointer reg
	while(I2CMasterBusy(I2C6_BASE));	
	I2CMasterDataPut(I2C6_BASE, 0x00);					//P1P0= 00 = Temp high reg. Byte goes to PR
	while(I2CMasterBusy(I2C6_BASE));	
	data_low = I2CMasterDataGet(I2C6_BASE);						//receives the bytes from slave
	data_high = I2CMasterDataGet(I2C6_BASE);
	while(I2CMasterBusy(I2C6_BASE));	

}

I hope the I have given enough information, if not please let me know. 

Again I'm more interested to know about the procedure rather than worrying about the code itself.

Any help is much appreciated. thanks

  • Hello Ronak,

    Did you have look at the example code in TivaWare? What the issue with your code is that after Putting the slave address and then data you need to issue the START, CONTINUE and FINISH command, so that the I2C controller knows what it needs to do with the data.

    Secondly, the clock function that you are using are not valid for TM4C129. The equivalent function for SysCtlClockSet is SysCtlClockFreqSet, the return value of which is the replacement for SysCtlClockGet

    Regards

    Amit

  • Hi Amit,

    Thanks a lot for getting back to me.

    I have checked the example codes for TM4C129 and they are using SysCtlClockSet. However I will double check this thing.

    According to TIVA peripheral driver guide, I found that I have to write I2CMasterControl() after I use the I2CMasterDataPut() function. I believe I2CMasterControl() will issue the start condition. Did I understand correctly?

    Apart from that, Did you find any error in rest of the code?

  • Hello Ronak,

    Which code example, as it would be an error for the SysCtlClockSet to be used for TM4C129 devices. If the example you are referring to is in C:\ti\TivaWare_C_Series-2.1.0.12573\examples\peripherals\i2c then those will not be a valid example for TM4C129 from Clock Configuration.

    Regarding the second point, you are correct.

    Regards

    Amit

  • Hi Amit,

    It would be better if TI can provide the updated examples as many of beginners like me will do the same mistake by following the examples.

    I have one more question.

    in TMP100 there is one register called Temperature register. It stores the recent value of the conversion. It is read only. It is two bytes long. So i have to read the register two times I guess. My question is how to read it? According to my understanding I did the following

    - Told the Master to initiate Read from the salve.

    I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true)

    - In the example they have mentioned to read a dummy receive. So i did.

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

    - Now I wait for the dummy acknowledgement

    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))

    - Next I dont know what to do? Should I do something like this? Please help me here.

    data_low = I2CMasterDataGet(I2C6_BASE);                        //receives the bytes from slave

    data_high = I2CMasterDataGet(I2C6_BASE);
    while(I2CMasterBusy(I2C6_BASE));   

    Will the salve automatically send the data? or I have to tell it to send the data?

    Once it sends the data, where will it go? i mean somekind of buffer/FIFO? If yes, then will master read it from that buffer/FIFO?

    Since there are two bytes, should I do the same procedure two times?

    Thanks

  • Hello Ronak,

    Now, having an example for the device on board would be a perfect world, but not the case all the time, that is why it is augmented by the driverlib documentation and comments in the driverlib files as well. Anyways the structure of the code would still remain the same. Going by the code you have sent

    1. The first step is correct.

    2. Since you want to read two bytes you should not use the I2C_MASTER_CMD_SINGLE_RECIEVE, but the START only command. This will generate the Start condition, address and prepare the Master for on read data.

    3. You need to the wait for the I2CMasterBusy to become false. The Slave status is for the I2C Slave which is a part of the I2C Controller and not the external slave device.

    4. After getting the data_low once the I2CMasterBusy becomes false, then you would use the FINISH command and read the data after I2CMasterBusy becomes low.

    If the FIFO is not being used, then it will go into a single byte buffer.

    Regards

    Amit

  • Hi Amit,

    As per your suggestions I wrote the code as following.

    I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);   // true indicates that master is initiating the receive.
    
    	I2CMasterDataPut(I2C6_BASE, 0x00);	// selects temp register
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); 
    	while(I2CMasterBusy(I2C6_BASE));
    	
    	data_low = I2CMasterDataGet(I2C6_BASE);						//receives the bytes from slave
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
    	//while(I2CMasterBusy(I2C6_BASE));       //should I put this statement here or not?
    	data_high = I2CMasterDataGet(I2C6_BASE);
     	while(I2CMasterBusy(I2C6_BASE));	
    


    I assume by START condition, you mean I2C_MASTER_CMD_BURST_RECEIVE_START.

    Since I'm using burst receive, should I read the data_high or not? Please help me here.

    Thanks

  • Hello Ronak,

    I would make the code look more like the following.

    I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);   // true indicates that master is initiating the receive.
    I2CMasterDataPut(I2C6_BASE, 0x00);    // selects temp register
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    while(!(I2CMasterBusy(I2C6_BASE)));
    while(I2CMasterBusy(I2C6_BASE));
    data_low = I2CMasterDataGet(I2C6_BASE);
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    while(!(I2CMasterBusy(I2C6_BASE)));
    while(I2CMasterBusy(I2C6_BASE));
    data_high = I2CMasterDataGet(I2C6_BASE);

    Regards

    Amit

  • Hi Amit,

    whats the point of writing 2 while statements?

    while(!(I2CMasterBusy(I2C6_BASE)));
    while(I2CMasterBusy(I2C6_BASE));

    thanks.

  • Hello Ronak,

    On the TM4C129, running at high system frequency like 120MHz, has a known side effect for I2C. When the command is written for I2C, it takes time for the state machine to update the busy flag. This will cause the skip the I2CMasterBusy condition.

    By putting the two conditions, if it is not set then it will wait in the first while loop and then wait in the second while loop before going for the next command

    Regards

    Amit

  • Hi Amit,

    Thanks for sharing the information. I will now go ahead and debug the code. I will let you know if its successful or not. I'm pretty sure that I will find some bug. Thanks again. Really appreciate your help...

    Thanks

  • Hi Amit,

    I had a chance to debug the code and I am really happy that I'm atleast getting the value. Surprisingly enough its not 0. I have seen many posts in which people say they are getting 0 value always. In my case it is 75. Obviously this cant be the temperature.

    I'm not sure what I'm doing wrong. Conceptually I have worked hard to make sure that I'm not missing anything. Please take a look at the code and let me know what I'm doing wrong.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    
    /* OS/ALERT bit will start the conversion. While setting the config register I set the OS/ALERT bit to be 1. So it will start the conversion.
        OR
        We can set the config register later. */
    
    
    
    #define SLAVE_ADDRESS 0x4A
    void main()
    {
    	uint8_t data_low, data_high;
    	uint32_t sys_clock;
    
    	sys_clock = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    	GPIOPinConfigure(GPIO_PB6_I2C6SCL);
    	GPIOPinConfigure(GPIO_PB7_I2C6SDA);
    
    	GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_6);
    	GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);
    
    	I2CMasterInitExpClk(I2C6_BASE, sys_clock, false);
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    
    	/*  Configuration Register */
    	I2CMasterDataPut(I2C6_BASE, 0x01);					//P1 P0 = 01 = configuration reg. Byte goes to PR
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));	//Wait until the slave has received and acknowledged the data.
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0xA1);		//sets the bits of configuration reg. A1 = 10 bit, shutdown, OS=1 start conv. Byte goes to Config Reg
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	/*  T High Register */
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);	//selects the pointer reg
    
    	I2CMasterDataPut(I2C6_BASE, 0x03);					//P1P0= 11 = Temp high reg. Byte goes to PR
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0x32);					//sets the Thigh reg = 50C. Byte goes to Thigh
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	/*  T Low Register */
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);	//selects the pointer reg
    
    	I2CMasterDataPut(I2C6_BASE, 0x02);					//P1P0= 10 = Temp low reg. Byte goes to PR
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0x28);					//sets the Tlow reg = 40C. Byte goes to Tlow
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	/* Start Reading Temperature Register */
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);   // true indicates that master is initiating the receive.
    
    	I2CMasterDataPut(I2C6_BASE, 0x00);	// selects temp register
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	data_low = I2CMasterDataGet(I2C6_BASE);						//receives the bytes from slave
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	data_high = I2CMasterDataGet(I2C6_BASE);
    
    	while(1);
    }
    

    I also have one more question. Last time you mentioned to use 2 while loops as follows.

    while(!(I2CMasterBusy(I2C6_BASE)));
    while(I2CMasterBusy(I2C6_BASE));

    Should I do this everytime in above code? I mean I'm using 2 while loops only at the end of the code and not everywhere.

    Also 75 (decimal) is 4B0 (hex). Now I'm not setting any of the register to this value. So does this mean that temperature sensor is reading the temperature but I'm getting something else?

    Please help...Thanks

  • Hello Ronak,

    Yes, the pair-ed loop should be used for all transactions. When reading the temperature register it should be

        /* Start Reading Temperature Register */
        I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);   // true indicates that master is initiating the receive.

        I2CMasterDataPut(I2C6_BASE, 0x00);    // selects temp register
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_START);
        while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));

        I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);   // true indicates that master is initiating the receive.


        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));
        
        data_low = I2CMasterDataGet(I2C6_BASE);                        //receives the bytes from slave
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));

        data_high = I2CMasterDataGet(I2C6_BASE);

    Also when doing write to a register it should not be a single byte, but START + Slave Address + Register Address + Data Write Byte + STOP. So you would need to have SEND_START with the Slave Address + Register Address and then write the Data Byte and Have SEND_FINISH.

    Regards

    Amit

  • Hi Amit,

    How to wait for the salve's acknowledgement? I earlier wrote the following code believing that I'm waiting for the ack, but when I debug the code it gets stuck there.

    while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));

    What do we mean by I2CSlaveStatus()? I believe it shows the status of the I2C module itself and not the temperature IC salve. I'm confused here. Please clarify these thing. According to datasheets I'm supposed to wait for the ACK.

    Also I notice that one reading the data_low, we are using I2C_MASTER_CMD_BURST_RECEIVE_FINISH. And after that we are again reading data_high. So if we are already finishing the receive then whats the point of reading data_high after that?

    Thanks for your prompt response. Really appreciate your help.

  • Hello Ronak,

    The I2C Controller consists of a Master and Slave Module. The I2CSlaveStatus is meant for the Slave part of the controller. The I2C Master (which is the one being used), will wait for the full frame (data + ACK) to be received before making the I2CMatserBusy 0.

    If there is a ACK or NACK, that will be then given in the I2CMCS register.

    The FINISH command will receive one byte and then put Stop condition. That is why you need to wait for the data after the while loop.

    Regards

    Amit

  • Hi,

    So what should I write for the to check the salve(TMP100) ACK? For example, lets say I'm writing to configuration register as follows.

    I2CMasterDataPut(I2C6_BASE, 0x01);					//P1 P0 = 01 = configuration reg. Byte goes to PR
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	Wait until the slave has received and acknowledged the data. Please shoe me code here. What should I write here?
    	while(I2CMasterBusy(I2C6_BASE));
    

    Thanks

  • Hello Ronak,

    You can replace the while loop with

    ui32Status = HWREG(ui32Base + I2C_O_MCS);

    ui32Err = 0;

    while(ui32Status & I2C_MCS_BUSY)

    {

    if(ui32Status & (I2C_MCS_DATACK) == I2C_MCS_DATACK)

    {

    ui32Err = 1;

    }

    if(ui32Status & (I2C_MCS_ADRACK) == I2C_MCS_ADRACK)

    {

    ui32Err = 2;

    }

    ui32Status = HWREG(ui32Base + I2C_O_MCS);

    }

    And then check if ui32Err is 0 or not.

    Regards

    Amit

  • Hi,

    Is there any other simple way? I mean this looks little complicated to check for the ACK. How do people generally implement I2C communication for any sensor? I tried too look for "how to check for ACK" but couldnt get anything.

    Thanks

  • Hello Ronak,

    If the transaction starts (assuming the slave device does not fail or the Master outs out a wrong Slave Address), the Address will be ACK-ed. For this specific device, it has 4 registers and configuration needs to be done once. After that it is always a read of the converted temperature which will work as expected, since the Slave does not NACK a read request, but sends the last stored temperature data,

    But for a more generic system, this would be the way.

    Regards

    Amit

  • Hi Amit,

    I'm still working on the code. This time just to verify that I'm correctly writing to the TMP100 registers, I wrote to configuration register and then tried to read back. But I wasn't successful.  I tried various things on the code but couldnt get any of them working correctly. Please take a look.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "inc/tm4c129xnczad.h"
    
    #define SLAVE_ADDRESS 0x4A
    
    void main()
    {
    	uint8_t data_low, data_high;
    	uint32_t sys_clock;
    
    	sys_clock = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    	GPIOPinConfigure(GPIO_PB6_I2C6SCL);
    	GPIOPinConfigure(GPIO_PB7_I2C6SDA);
    
    	GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_6);
    	GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);
    
    	I2CMasterInitExpClk(I2C6_BASE, sys_clock, false);
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    	
    	/*  Configuration Register */
    	I2CMasterDataPut(I2C6_BASE, 0x01);					//P1 P0 = 01 = configuration reg. Byte goes to PR
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0xA1);		//sets the bits of configuration reg. A1 = 10 bit, shutdown, OS=1 start conv. Byte goes to Config Reg
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);	// true indicates that master is initiating the receive.
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    
    	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    	data_low = I2CMasterDataGet(I2C6_BASE);
    
    	while(!(I2CMasterBusy(I2C6_BASE)));
    	while(I2CMasterBusy(I2C6_BASE));
    	while(1);
    }
    

    If I use while(!(I2CMasterBusy(I2C6_BASE))) then it gets stuck So I commented it. I again read the datasheet of TMP100 just to make sure that I'm not missing anything. Any suggestions....??

    Thanks

  • Hello Ronak,

    I have restructured the part of the code which should be the correct one. I can only test it out/confirm once I have the DK-TM4C129 connected.

        I2CMasterInitExpClk(I2C6_BASE, sys_clock, false);
        I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
        
        /*  Configuration Register */
        I2CMasterDataPut(I2C6_BASE, 0x01);                  //P1 P0 = 01 = configuration reg. Byte goes to PR
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    //  while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));
        I2CMasterDataPut(I2C6_BASE, 0xA1);      //sets the bits of configuration reg. A1 = 10 bit, shutdown, OS=1 start conv. Byte goes to Config Reg
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    //  while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));
        I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);  // true indicates that master is initiating the receive.
        I2CMasterDataPut(I2C6_BASE, 0x01);                  //P1 P0 = 01 = configuration reg. Byte goes to PR
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_START);
        while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
        while(!(I2CMasterBusy(I2C6_BASE)));
        while(I2CMasterBusy(I2C6_BASE));
        data_low = I2CMasterDataGet(I2C6_BASE);
        while(1);

    Regards

    Amit

  • Hi Amit,


    I just debug your code and it shows me data_low as 0x80. While I was trying different things I noticed that I'm not getting the ACK back from the slave.  Because of that I2CMRIS register bit NACKRIS bit is getting set.

    I tried getting ACK using I2CMasterIntStatus and I2CMasterErr function to check the ACK. But I was not successful.

    Thanks.

  • Hello Ronak,

    As I indicated, the code was untested and based on my understanding of the code (which may be incorrect) and requires me to test it on the DK-TM4C129 as well. I shall test and see why NACK is getting set and data not returned correctly.

    Regards

    Amit

  • Hello Ronak,

    I checked the code and it worked fine on my side. I made some changes to get you going.

    The temp reading works fine and by using hot air on the TMP100, I can get the read value to change as well.

    http://e2e.ti.com/cfs-file.ashx/__key/communityserver-discussions-components-files/908/7266.TM4C129_5F00_I2C_5F00_TMP100.7z

    Regards

    Amit

  • Hi Amit,

    Thanks for the code.

    To my surprise at first when I debug your code, it showed me 1B value for data_low. It should show me A0 as you have set the config register value to A0.

    Second, I tried sending other values to config register and again it showed me 1B value only,

    Third, I tried removing the jumper pin J20 (PB6,PB7) and surprisingly code worked and showed me 1B value.

    I am totally clueless and it looks like there is something wrong with the board. I suspect that I'm not communicating with the temperature sensor at all and some other IC is sending me the reply. I'm attaching the screen shot.

    In the screenshot you can see that I have put a breakpoint at UARTprintf("Data is %x\n",data_low) and the value it showed me is 1B. When I took the screenshot I already have removed the jumper pins.

    I dont have logic analyzer with me so i cant further check the waveforms and all.

    Please help me.

  • Hello Ronak,

    With the jumper removed the code hangs as the external pull up's are disconnected, so it seems that there could be a problem on the board.

    You can first check if the GPIO is fine by removing the jumpers and then toggling it as 1-0-1-0 by having GPIO Pins PB6 and PB7 in GPIO Output Mode. This would require a multimeter to read 3.3V or 0V depending on the Logic Level 1 or 0.

    Without a scope or LA debugging such a failure may be difficult.

    Regards

    Amit

  • Hi Amit,

    I researched lot regarding the I2C_MASTER_CMD_BURST_SEND_START and other similar commands and came to know about many things. 

    I understood that we have to issue start and stop condition only once. In between that, you can write various registers. I modified my code accordingly. One more thing is that, TMP100 doesnt have alert pin. Temp high and temp low register are specially used for alert function. Since we have TMP100 on board, do I really need to set the high and low temperature limit? I dont think so. But please confirm it. 

    It looks like my code is not reliable, in the sense that sometimes it gives me correct reading and sometimes it shows me constant value 1B. I live in toronto and right now its under 10C. Please take a look at the code and any suggestions are welcomed.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    
    #define SLAVE_ADDRESS 0x4A
    
    void main()
    {
    	uint8_t data_low, data_high;
    	uint16_t data;
    	uint32_t sys_clock;
    
    	sys_clock = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
    	while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_I2C6)));
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)));
    
    	GPIOPinConfigure(GPIO_PB6_I2C6SCL);
    	GPIOPinConfigure(GPIO_PB7_I2C6SDA);
    
    	GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_6);
    	GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);
    
    	I2CMasterInitExpClk(I2C6_BASE, sys_clock, false);
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    
    	/*  Configuration Register */
    	I2CMasterDataPut(I2C6_BASE, 0x01);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0xA1);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    	while(I2CMasterBusy(I2C6_BASE));
    
    	/*
    	/  T High Register /
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    	I2CMasterDataPut(I2C6_BASE, 0x02);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    	while(I2CMasterBusy(I2C6_BASE));
    
    	I2CMasterDataPut(I2C6_BASE, 0x28);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    	while(I2CMasterBusy(I2C6_BASE));
    
    	/  T Low Register /
    	I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    	I2CMasterDataPut(I2C6_BASE, 0x03);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    	while(I2CMasterBusy(I2C6_BASE));
    	
    	I2CMasterDataPut(I2C6_BASE, 0x28);
    	I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    	while(I2CMasterBusy(I2C6_BASE));	*/
    
    
    	while(1)
    	{
    		I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, false);
    		I2CMasterDataPut(I2C6_BASE, 0x00);	// selects temp register
    		I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    		while(I2CMasterBusy(I2C6_BASE));
    
    		I2CMasterSlaveAddrSet(I2C6_BASE, SLAVE_ADDRESS, true);  // true indicates that master is initiating the receive.
    	    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    		while(I2CMasterBusy(I2C6_BASE));
    		data_high = I2CMasterDataGet(I2C6_BASE);
    		while(I2CMasterBusy(I2C6_BASE));
    		I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    		data_low = I2CMasterDataGet(I2C6_BASE);
    
    		data = (data_high << 8) | data_low;
    
    	}
    
    }
    

    I also read your sticky post and big thank you to you for sharing the info.