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.

I2C Setup

Other Parts Discussed in Thread: TM4C123GH6PM

Hello,

I am having trouble getting my micro-controller (TM4C123GH6PM) to get receive data from my D6T Thermal Sensor through I2C. The micro-controller is the master and the D6T thermal sensor is the slave. I have attached my code. The company who created the D6T thermal sensor gave a sample code, but this code will not work for this micro-controller. So I am trying to translate the sample code to a code that will work on the TM4C123GH6PM. I would really appreciate the help.

2630.D6T thermal sensor example code.pdf

/*
 * Thermal Sensor.c
 *
 *  Created on: Apr 25, 2014
 *      Author: ghadley
 *      ghadley is the ECE computer
 *      Actual Author: Uma Sambasivam
 */
#define PART_TM4C123GH6PM
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include <driverlib/pin_map.h>
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"


int main (void)
{
	//uint32_t ui32SysClock; //will be for the SCL in I2C
	//uint32_t ui32Base = I2C1_BASE; // output data is 35 bytes 0x35; I am setting this value to 35 for temperature recordings...is this right?
	//uint32_t ui32I2CClk;
	//bool bFast = 1; // set up for fast data transfers
	//bool bReceive = 1; // flag indicating the type of communication with the slave
	//uint8_t ui8SlaveAddr = 0x3B; // 7 bit address
	//uint8_t ui8Data = 'Q'; //ui8Data data to be transmitted from the I2C Master.
	//uint8_t ui32Cmd = I2C_MASTER_CMD_SINGLE_RECEIVE; // command to be issued to the I2C Master.


	   // Configure the system frequency.	    //
	    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
	                                           SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
	                                           SYSCTL_CFG_VCO_480), 120000000);

	    //Configure the device pins in this board.

	    // The I2C1 peripheral must be enabled before use.
	    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
	      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	      //GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_1,GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU);
	      //GPIOPadConfigSet(uint32_t ui32Port, uint8_t ui8Pins,GPIO_STRENGTH_8MA, uint32_t ui32PinType);


	      // Select the I2C function for these pins.  This function will also
	      // configure the GPIO pins pins for I2C operation, setting them to
	      // open-drain operation with weak pull-ups.  Consult the data sheet
	      // to see which functions are allocated per pin.


	    //Configure the pin muxing for I2C1 functions on port A6 and A7.

	      GPIOPinConfigure(GPIO_PA7_I2C1SDA);
	      GPIOPinConfigure(GPIO_PA6_I2C1SCL);

	      GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
	      GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);

	      I2CMasterInitExpClk(I2C1_BASE,SysCtlClockGet(),1); // Initializes the I2C Master block.
	      /* This function initializes operation of the I2C Master block by configuring the bus speed for the
	       * master and enabling the I2C Master block. If the parameter bFast is true, then the master block is
	       * set up to transfer data at 400 Kbps; otherwise, it is set up to transfer data at 100 Kbps.
	       */

	      I2CMasterSlaveAddrSet(I2C1_BASE,0x23,1); //Sets the address that the I2C Master places on the bus.
	      /* Sets the address that the I2C Master places on the bus. This function configures the address
	       * that the I2C Master places on the bus when initiating a transaction. When the bReceive parameter
	       * is set to true, the address indicates that the I2C Master is initiating a read from the slave.
	       */


	      //I2CMasterBusy(ui32Base); // Indicates whether or not the I2C Master is busy.
	      /* This function returns an indication of whether or not the I2C Master is busy transmitting or
	       * receiving data. Returns true if the I2C Master is busy; otherwise, returns false.
	       */

	      I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_SINGLE_RECEIVE); //Controls the state of the I2C Master.
	      /* This function is used to control the state of the Master send and receive operations. The
	       * ui8Cmd parameter used for this code is I2C_MASTER_CMD_SINGLE_RECEIVE. The master will be receiving
	       * data from the Thermal sensor.
	       */

	      I2CMasterDataPut(I2C1_BASE,'Q' ); // This function places the supplied data into I2C Master Data Register.



	      while(I2CMasterBusBusy(I2C1_BASE))
	      {
	      }

	      I2CMasterDisable(I2C1_BASE); //Disables the I2C master block.
	 //     while(1) {};
	      //return(0);

}


  • Can you please upload a picture of your setup? Please show pull up resistors, power, and ground connections in the picture. I think this may help discover the source of the problem.

    Also Amit Ashara gave some very useful i2c advice here, please check it out.

  • Thank you David. I have uploaded the pics. I have connected the micro's SCL and SDA to VCC with each 5.1K Ohms and to the sensor's SCL and SDA lines. 

     8304.attachments.zip

  • Hi David,

    I use the code that Amit posted on the forum and I am getting ACK. So it does mean that the micro is receiving data?

    -Uma

  • Hello Umadevi

    You are using the Clock Locking function of a TM4C129 on a TM4C123.

    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                   SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                                   SYSCTL_CFG_VCO_480), 120000000);

    Please change it to

    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);

    Other than that the code looks OK

    Regards

    Amit

  • Hi Amit,

    Thank you for the help! I did use that line that you recommended me to use and I checked it out with the oscilloscope. I attached two pics of it. But I am still not able to get data from my sensor. How do i get the data from my sensor?

    Thanks,

    Uma

      

  • Hello Umadevi,

    Thanks for the scope plot. In the code the address being set is 0x23 for the I2C Slave but in the scope plot it seems that the address is 0x0A. I am a little confused by this so could you elaborate if this is intended or not?

    Regards

    Amit

  • Hi Amit, Yes, I can see how that is confusing. I used this code below (from another forum) with 0x0A. Instead of I2C_MASTER_CMD_QUICK_COMMAND I used I2C_MASTER_CMD_SINGLE_RECEIVE.

        uint32_t addr;
        for (addr = 1; addr < 128; addr++) {
            printf("Scanning Addr 0x%02X:   ", addr);
            I2CMasterSlaveAddrSet(I2C0_BASE, addr, false);
            I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_QUICK_COMMAND);
            while (I2CMasterBusy(I2C0_BASE));
            uint32_t error = I2CMasterErr(I2C0_BASE);
            if (error & I2C_MASTER_ERR_ADDR_ACK) {
                printf("Error: 0x%02X\n", error);
            }
            else {
                printf("ACK.\n");

     thanks,

    uma

  • Hello Umadevi,

    Looking at the App Note for the thermal sensor the following is the operating mode

    I2C Start -> I2C Slave Address + Write Direction + Data 0x4C -> I2C Repeat Start -> I2C Slave Address  + Read Direction + 35 bytes of read -> I2C Stop

    Since I do not have access to the data sheet for this slave device, the above information is what I interpret from the small pdf document you had sent.

    If this is the case, then the sequence you have sent is "highly" insufficient to do the same. What you ould need to d is somewhat like below after i2C Peripheral Configuration is done

    I2CMasterSlaveAddrSet(I2C1_BASE, 0x0A,0);

    I2CMasterDataPut(I2C1_BASE, 0x4C);

    I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_SEND_START);

    while(!I2CMasterBusy(I2C1_BASE));

    I2CMasterSlaveAddrSet(I2C1_BASE, 0x0A,1);

    I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECIEVE_START);

    while(!I2CMasterBusy(I2C1_BASE));

    ui8ByteBuffer[0] = I2CMasterDataGet(I2C1_BASE);

    for(i=0;i<33;i++)

    {

    I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECIEVE_CONT);

    while(!I2CMasterBusy(I2C1_BASE));

    ui8ByteBuffer[i+1] = I2CMasterDataGet(I2C1_BASE);

    }

    I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECIEVE_FINISH);

    while(!I2CMasterBusy(I2C1_BASE));

    ui8ByteBuffer[34] = I2CMasterDataGet(I2C1_BASE);

    Regards

    Amit

  • Hi Amit,

    Thanks for the help! But now I am only seeing this(attached) on the oscilloscope. I am not see all the data. Plus where can I keep the UART in this code to see the temperature data.

    I attached what my current code looks like. I get two warnings ui8ByteBuffer. It says #177-D subscript out of range and #552-D variable "ui8ByteBuffer" was set but never used. How do I initialize this array? Is it with int, ui8Byte? Either of them does not seem to work.

     I also attached the full document of the D6T thermal sensor for more info.

    /*
     * Thermal Sensor.c
     *
     *  Created on: Apr 25, 2014
     *      Author: ghadley
     *      ghadley is the ECE computer
     *      Actual Author: Uma Sambasivam
     */
    #define PART_TM4C123GH6PM
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_uart.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include <driverlib/pin_map.h>
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/uart.c"
    #include "utils/uartstdio.h"
    #include "utils/uartstdio.c"
    
    
    int main (void)
    {
    	//uint32_t ui32SysClock; //will be for the SCL in I2C
    	//uint32_t ui32Base = I2C1_BASE; // output data is 35 bytes 0x35; I am setting this value to 35 for temperature recordings...is this right?
    	//uint32_t ui32I2CClk;
    	//bool bFast = 1; // set up for fast data transfers
    	//bool bReceive = 1; // flag indicating the type of communication with the slave
    	//uint8_t ui8SlaveAddr = 0x3B; // 7 bit address
    	//uint8_t ui8Data = 'Q'; //ui8Data data to be transmitted from the I2C Master.
    	//uint8_t ui32Cmd = I2C_MASTER_CMD_SINGLE_RECEIVE; // command to be issued to the I2C Master.
    
    	int ui8ByteBuffer[33];
    	int i;
    
    	// uint32_t ui32Error = I2CMasterIntStatus(I2C1_BASE,false);
    
    
    	   // Configure the system frequency.	    //
    	//    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    	//                                           SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
    	//                                           SYSCTL_CFG_VCO_480), 120000000);
    	    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
    	                           SYSCTL_OSC_MAIN);
    
    	    //Configure the device pins in this board.
    
    	    // The I2C1 peripheral must be enabled before use.
    	    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    	    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	      //GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_1,GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU);
    	      //GPIOPadConfigSet(uint32_t ui32Port, uint8_t ui8Pins,GPIO_STRENGTH_8MA, uint32_t ui32PinType);
    
    
    	      // Select the I2C function for these pins.  This function will also
    	      // configure the GPIO pins pins for I2C operation, setting them to
    	      // open-drain operation with weak pull-ups.  Consult the data sheet
    	      // to see which functions are allocated per pin.
    
    
    	    //Configure the pin muxing for I2C1 functions on port A6 and A7.
    
    	      GPIOPinConfigure(GPIO_PA7_I2C1SDA);
    	      GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    	      GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    	      GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
    
    	      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	          SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    	          UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    	          UARTStdioConfig(0, 115200, 16000000);
    	          GPIOPinConfigure(GPIO_PB0_U1RX);
    	          GPIOPinConfigure(GPIO_PB1_U1TX);
    	          GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    	          IntMasterEnable();
    
    
    	      I2CMasterInitExpClk(I2C1_BASE,SysCtlClockGet(),1); // Initializes the I2C Master block.
    	      /* This function initializes operation of the I2C Master block by configuring the bus speed for the
    	       * master and enabling the I2C Master block. If the parameter bFast is true, then the master block is
    	       * set up to transfer data at 400 Kbps; otherwise, it is set up to transfer data at 100 Kbps.
    	       */
    
    	      //The code below came from this forum. http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/339516/1186628.aspx#1186628
    	      //Amit Ashara provided the code below from lines 94-123.
    	      I2CMasterSlaveAddrSet(I2C1_BASE,0x0A,0);
    	      I2CMasterDataPut(I2C1_BASE,0x4C);
    	      I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_SEND_START);
    
    	      while(!I2CMasterBusy(I2C1_BASE));
    
    	      I2CMasterSlaveAddrSet(I2C1_BASE, 0x0A,1);
    	      I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECEIVE_START);
    
    	      while(!I2CMasterBusy(I2C1_BASE));
    
    	      ui8ByteBuffer[0] = I2CMasterDataGet(I2C1_BASE);
    
    	      for(i=0;i<33;i++)
    
    	      {
    
    	      I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    
    	      while(!I2CMasterBusy(I2C1_BASE));
    
    	      ui8ByteBuffer[i+1] = I2CMasterDataGet(I2C1_BASE);
    
    	      }
    
    	      I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
    	      while(!I2CMasterBusy(I2C1_BASE));
    
    	      ui8ByteBuffer[34] = I2CMasterDataGet(I2C1_BASE);
    
    	      /*uint32_t TEMP;
    
    	      for(TEMP = 1; TEMP < 10; TEMP++)
    	      {
    	    	  UARTprintf("Scanning TEMPERATURE %3d: ", TEMP);
    	    	  I2CMasterSlaveAddrSet(I2C1_BASE,10,1);
    	    	  I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_SINGLE_RECEIVE);
    
    	    	  if((I2CMasterIntStatus(I2C1_BASE,false) & I2C_MASTER_INT_NACK) == I2C_MASTER_INT_NACK)
    	    	  {
    	    		  UARTprintf("error \n");
    	    	  }
    	    	  else
    	    	  {
    	    		  UARTprintf("ACK\n");
    	    	  }
    	    	  I2CMasterIntClearEx(I2C1_BASE,I2CMasterIntStatus(I2C1_BASE,false));
    	      }*/
    
    	     // I2CMasterSlaveAddrSet(I2C1_BASE,0x23,1); //Sets the address that the I2C Master places on the bus.
    	      /* Sets the address that the I2C Master places on the bus. This function configures the address
    	       * that the I2C Master places on the bus when initiating a transaction. When the bReceive parameter
    	       * is set to true, the address indicates that the I2C Master is initiating a read from the slave.
    	       */
    
    
    	      //I2CMasterBusy(ui32Base); // Indicates whether or not the I2C Master is busy.
    	      /* This function returns an indication of whether or not the I2C Master is busy transmitting or
    	       * receiving data. Returns true if the I2C Master is busy; otherwise, returns false.
    	       */
    
    	     // I2CMasterControl(I2C1_BASE,I2C_MASTER_CMD_SINGLE_RECEIVE); //Controls the state of the I2C Master.
    	      /* This function is used to control the state of the Master send and receive operations. The
    	       * ui8Cmd parameter used for this code is I2C_MASTER_CMD_SINGLE_RECEIVE. The master will be receiving
    	       * data from the Thermal sensor.
    	       */
    
    	 //     I2CMasterDataPut(I2C1_BASE,'Q'); // This function places the supplied data into I2C Master Data Register.
    
    
    
    	   //   while(I2CMasterBusBusy(I2C1_BASE))
    	    //  {
    	     // }
    
    	//      I2CMasterDisable(I2C1_BASE); //Disables the I2C master block.
    	 //     while(1) {};
    	      //return(0);
    
    }
    
    
    

    Thanks,

    Uma

    1070.D6T44L_8L_Appl_Note.pdf 7652.attachments (1).zip

  • Hello Umadevi,

    Can you check the number of elements in the ui8ByteBuffer is equal to the number of bytes expected. As for uninit varaibles you can have a small for loop to init them.

    EDIT--

    Please change ui8ByteBuffer[33] to int ui8ByteBuffer[35]

    The device is rated for 100KHz Max I2C Speed, but your have configured it for 400KHz SCL Rate. Please replace the "1" in the I2CMasterInitExpClk with a "0" to reduce the Baud rate.

    Also can you take a snapshot of the Write I2C Cycle, where the Slave Address with 0x4C command is being sent?

    Regards

    Amit