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.

CCS/TM4C1294NCPDT: master_receive_interrupte i2c on tm4c1294ncpdt tiva board

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

Tool/software: Code Composer Studio

 how can i recive data on master in i2c mode with interrupt  fast data transfer.

  • Here is an example project. Use CCS "File" -> "Import" to add this project to your workspace. This was created with CCS version 10.

    /cfs-file/__key/communityserver-discussions-components-files/908/4087.ektm4c129_5F00_i2c_5F00_master_5F00_hs.zip

  • There is additional information in this application note:

    https://www.ti.com/lit/an/spma073/spma073.pdf

  • thank you for valuable response .


          now how can i see every ms data read and store in buffer.
    please suggest any reference code.

     

  • Your questions are a bit vague, so I made some assumptions trying to answer them. I assume you have the TM4C1249 as a master device connected to a slave by I2C bus. You want to request and receive data from the slave every 1ms.

    Look at the TivaWare example in: C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timers

    This example shows how to setup the hardware timers to generate interrupts. You will need only one timer, not both. Change the interrupt interval to 1ms by the line: 

        MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, g_ui32SysClock / 1000u);
    

    Now I suggest you combine the methods of the timer example and the methods of the I2C example I gave above. In the timer interrupt routine, start the I2C sequence by:

    	//
    	// Trigger the Transfer using Software Interrupt
    	//
    	IntTrigger(INT_I2C2);
    

    Then at the end of your main routine include an infinite loop that processes the received data:

    	while(1)
    	{
            if(g_ui8MasterCurrState == I2C_HS_STOP)
            {
                // Do something with the data in g_ui8MasterRxData here
                g_ui8MasterCurrState = I2C_HS_IDLE;
            }
    	}
    

  • Thank you bob

    I am new one in tiva board its deficalt to understand this if possible can you share this type of example for  better understanding

  • I suggest you start with the second example I mentioned, the timer example:

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timers

    Try to import and run this example on the EK-TM4C129xl board without modifications first. Then ask me questions about the example if you do not understand it.

  • thank you bob

    i see that code its work  and understand this code but in that i can't understand int trigger point how can i set this point for get every ms data

  • timmer code imort and working fine ...now  next

  • The answer on how to make the interrupt occur every 1mS and how to start the I2C transfer are in my first response of Dec 1st. However, before you try that, you should get I2C communication working with your hardware. Have you imported the first CCS project I gave you? It will need to be modified to use the I2C pins connected to your hardware, the I2C slave device of the device you are reading and the proper sequence to get the data you want. That information will be in the datasheet of your I2C slave device.

  • i am try every ms led blink it working fine now i am also interface i2c but somewhere i am understand how can get data every ms i try to write to some of refrance i2c code. this is my ..now which parameter add in this code to get data every ms data which line i am modified

    #include <stdint.h>
    #include <stdbool.h>
    #include <math.h>
    #include "inc/hw_ints.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/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    void ConfigureTimer0(void);
    void ConfigureGPIO(void);
    void Timer0IntHandler(void);
    void calculation_pressure(void);
    void ConfigureI2C7(void);
    
    //*****************************************************************************
    // Define AMS5812 I2C Address.
    //
    //*****************************************************************************
    #define SLAVE_ADDRESS 0x78
    //*****************************************************************************
    //
    // Counter to count the number of interrupts that have been called.
    //
    //*****************************************************************************
    static volatile uint32_t g_ui32Counter = 0;
    //****************************************************************************
    //
    // System clock rate in Hz.
    //
    //****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // Flags that contain the current value of the interrupt indicator as displayed
    // on the UART.
    //
    //*****************************************************************************
    //uint32_t g_ui32Flags;
    volatile uint_fast8_t g_ui32Flags;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The interrupt handler for the first timer interrupt.
    //
    //*****************************************************************************
    void Timer0IntHandler(void)
    {
    
        //
        // Clear the timer interrupt.
        //
        MAP_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    
        // Update the periodic interrupt counter.
        //
        g_ui32Flags=1;
        g_ui32Counter++;
    
        //
        // Toggle the flag for the first timer.
        //
        // HWREGBITW(&g_ui32Flags, 0) ^= 1;
        //HWREGBITW(&g_ui32Flags, 1) ^= 1;
        // HWREGBITW(&g_ui32Flags, 4) ^= 1;
        //
        // Use the flags to Toggle the LED for this timer
        //
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0,g_ui32Flags);
        /*GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, ~g_ui32Flags);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0,g_ui32Flags);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, ~g_ui32Flags);
        */
    
    
        // UARTprintf("16-Bit Timer Interrupt %d->\n",g_ui32Flags);
    
        // MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, 60000);
        // uint32_t g_ui32Counter = 0;
    }
    //*****************************************************************************
    //
    // Configure the UART and its pins. This must be called before UARTprintf().
    //
    //*****************************************************************************
    void ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
        MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, g_ui32SysClock);
    }
    //*****************************************************************************
    //
    // This example application demonstrates the use of the timers to generate
    // periodic interrupts.
    //
    //*****************************************************************************
    int main(void)
    {
        uint32_t ui32PrevCount = 0;
        //
        // Run from the PLL at 120 MHz.
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
        SYSCTL_OSC_MAIN |
        SYSCTL_USE_PLL |
        SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Initialize the UART and write status.
        //
        ConfigureUART();
        ConfigureTimer0();
        ConfigureGPIO();
        ConfigureI2C7();
    
        g_ui32Counter = 0;
    
        // Enable processor interrupts.
        //
    
        MAP_IntMasterEnable();
    
    
        // Loop forever while the timers run.
        //
        while(1)
        {
            while(!g_ui32Flags)
            {
    
                //UARTprintf("Number of interrupts: %d\r", g_ui32Counter);
                calculation_pressure();
    
            }
    
        }
    }
    //*****************************************************************************
    //
    // calculation of pressure data
    //
    //*****************************************************************************
    void calculation_pressure(void)
    {
        float fpressure;
        int32_t i32IntegerPart;
        int32_t i32FractionPart;
        uint32_t pui32DataRx[4] = {0};
    
        ///
        // Read the pressure measurements
        //
    
        I2CReadCommand(&pui32DataRx[0]);//
        // Process the raw measurement and convert it to physical
        // pressure percentage. Refer to the AMS datasheet for the
        // conversion formula.
        //
        pui32DataRx[0] = ((pui32DataRx[0] << 8) + (pui32DataRx[1]));
        fpressure =(float)((pui32DataRx[0]-3277 )/(float)(26214/100));
    
        //
        // Convert the floats to an integer part and fraction part for easy
        // print. pressure is returned as 0.0 to 1.0 so multiply by 100 to get
        // percent pressure.
        //
    
        i32IntegerPart = (int32_t) fpressure;
        i32FractionPart = (int32_t) (fpressure*1000.0f);
        i32FractionPart = i32FractionPart - (i32IntegerPart*1000);
    
    
        if(i32FractionPart < 0)
        {
            i32FractionPart *= -1;
        }
        
        //
        // Print the pressure value using the integers we just converted.
        //
        UARTprintf("pressure :- %d.%d = psi\n", i32IntegerPart, i32FractionPart);
    
    
        //MAP_SysCtlDelay(g_ui32SysClock / (11 * 3)); // Here we will wait for approximately 90ms.
    
    
    }
    //*****************************************************************************
    //
    // Configures Timer 0 as a general purpose, periodic timer
    //
    //*****************************************************************************
    void ConfigureTimer0(void)
    {
        //
        // Enable the peripherals used by this example.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
        //
        // Configure the two 32-bit periodic timers.
        //
        MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
        MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, 600);
    
    
        //
        // Setup the interrupts for the timer timeouts.
        //
        MAP_IntEnable(INT_TIMER0A);
        MAP_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        MAP_TimerEnable(TIMER0_BASE, TIMER_A);
    
    }
    //*****************************************************************************
    //
    // Configures GPIO port N
    //
    //*****************************************************************************
    void ConfigureGPIO(void)
    {
        //
        // Enable the GPIO port that is used for the on-board LEDs.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LEDs (PN0 & PN1).
        //
        MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 |GPIO_PIN_1);
        MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 |GPIO_PIN_4);
    
    }
    
    //*****************************************************************************
    //
    // Configures I2C port
    //
    //*****************************************************************************
    
    void ConfigureI2C7(void)
    {
        //
        // The I2C7 peripheral must be enabled before use.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);//
    
        // Configure the pin muxing for I2C7 functions on port D0 and D1.
        // This step is not necessary if your part does not support pin muxing.
        //
        MAP_GPIOPinConfigure(GPIO_PD0_I2C7SCL);
        MAP_GPIOPinConfigure(GPIO_PD1_I2C7SDA);
    
        //
        // 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.
        //
        MAP_GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
        MAP_GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1); //
    
    
        // Enable interrupts to the processor.
        //
        MAP_IntMasterEnable();
    
        //
        // Enable and initialize the I2C7 master module. Use the system clock for
        // the I2C7 module. The last parameter sets the I2C data transfer rate.
        // If false the data rate is set to 100kbps and if true the data rate will
        // be set to 400kbps. For this example we will use a data rate of 100kbps.
        //
        MAP_I2CMasterInitExpClk(I2C7_BASE, g_ui32SysClock, false);
    
    }
    
    
    //*****************************************************************************
    //
    // This function will read three 8-bit data from the I2C slave. The first
    // two 8-bit data forms the pressure data while the last 8-bit data is the
    // checksum. This function illustrates three different I2C burst mode
    // commands to read the I2C slave device.
    //
    //*****************************************************************************
    void I2CReadCommand(uint32_t * pui32DataRx)
    {
        //
        // Modify the data direction to true, so that seeing the address will
        // indicate that the I2C Master is initiating a read from the slave.
        //
        MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SLAVE_ADDRESS, true);
    
        //
        // Setup for first read. Use I2C_MASTER_CMD_BURST_RECEIVE_START
        // to start a burst mode read. The I2C master continues to own
        // the bus at the end of this transaction.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    
        //
        // Wait until master module is done transferring.
        // The I2C module has a delay in setting the Busy flag in the register so
        // there needs to be a delay before checking the Busy bit. The below loops
        // wait until the Busy flag is set, and then wait until it is cleared to
        // indicate that the transaction is complete. This can take up to 633 CPU
        // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock. Therefore, a
        // while loop is used instead of SysCtlDelay.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Read the first byte data from the slave.
        //
        pui32DataRx[0] = MAP_I2CMasterDataGet(I2C7_BASE);
    
        //
        // Setup for the second read. Use I2C_MASTER_CMD_BURST_RECEIVE_CONT
        // to continue the burst mode read. The I2C master continues to own
        // the bus at the end of this transaction.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    
        //
        // Wait until master module is done transferring.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Read the second byte data from the slave.
        //
        pui32DataRx[1] = MAP_I2CMasterDataGet(I2C7_BASE);
    
    
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    
        //
        // Wait until master module is done transferring.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Read the third byte data from the slave.
        //
        pui32DataRx[2] = MAP_I2CMasterDataGet(I2C7_BASE);
    
        //
        // Setup for the third read. Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH
        // to terminate the I2C transaction. At the end of this transaction,
        // the STOP bit will be issued and the I2C bus is returned to the
        // Idle state.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
        //
        // Wait until master module is done transferring.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Note the third 8-bit data is the checksum byte. It will be
        // left to the users as an exercise if they want to verify if the
        // checksum is correct.
        pui32DataRx[3] = MAP_I2CMasterDataGet(I2C7_BASE);
    }
    

  • First, I edited your post by replacing your code with a version using the </> button shown in the picture below. When posting code snippets, using this option adds line numbers and C language formatting.

    If your function to read the pressure is working correctly, you are close. The idea is the timer interrupt sets a flag every 1mS. Then the main routine checks for the flag. If set, it reads the pressure and then clears the flag. Your while loop in main should look more like this:

        // Loop forever while the timers run.
        //
        while(1)
        {
            if(g_ui32Flags == 1)
            {
                calculation_pressure();
                g_ui32Flags = 0;
    
            }
        }
    

    Another issue is that your timer load value is not correct. Line 248 should be:

        MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, 12000);
    

    (At 120MHz there are 120000000 system clock ticks every second, or 12000 clocks every millisecond.)

    The next issue is that you are trying to print the results out the UART in the calculation_pressure() function. At 115200 baud, you can only print 11 characters in 1mS. You need to reduce the number of characters you are trying to print, or increase the time between timer interrupts. 

    If your final output is printing to a display, the human eye cannot perceive a display that is updated every millisecond. Even at 10 times per second, the low order changing digit will be an unreadable blur. 

  • thank you bob i got it your point now how can set i2c read commond to improve data rate 

    in function of i2c read commond  i want to just get float data and store  in any varible  

    void I2CReadCommand(uint32_t * pui32DataRx)
    {
    //
    // Modify the data direction to true, so that seeing the address will
    // indicate that the I2C Master is initiating a read from the slave.
    //
    MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SLAVE_ADDRESS, true);

    //
    // Setup for first read. Use I2C_MASTER_CMD_BURST_RECEIVE_START
    // to start a burst mode read. The I2C master continues to own
    // the bus at the end of this transaction.
    //
    MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    //
    // Wait until master module is done transferring.
    // The I2C module has a delay in setting the Busy flag in the register so
    // there needs to be a delay before checking the Busy bit. The below loops
    // wait until the Busy flag is set, and then wait until it is cleared to
    // indicate that the transaction is complete. This can take up to 633 CPU
    // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock. Therefore, a
    // while loop is used instead of SysCtlDelay.
    //
    while(!MAP_I2CMasterBusy(I2C7_BASE))
    {
    }
    while(MAP_I2CMasterBusy(I2C7_BASE))
    {
    }

    //
    // Read the first byte data from the slave.
    //
    pui32DataRx[0] = MAP_I2CMasterDataGet(I2C7_BASE);

    //
    // Setup for the second read. Use I2C_MASTER_CMD_BURST_RECEIVE_CONT
    // to continue the burst mode read. The I2C master continues to own
    // the bus at the end of this transaction.
    //
    MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

    //
    // Wait until master module is done transferring.
    //
    while(!MAP_I2CMasterBusy(I2C7_BASE))
    {
    }
    while(MAP_I2CMasterBusy(I2C7_BASE))
    {
    }

    //
    // Read the second byte data from the slave.
    //
    pui32DataRx[1] = MAP_I2CMasterDataGet(I2C7_BASE);


    MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

    //
    // Wait until master module is done transferring.
    //
    while(!MAP_I2CMasterBusy(I2C7_BASE))
    {
    }
    while(MAP_I2CMasterBusy(I2C7_BASE))
    {
    }

    //
    // Read the third byte data from the slave.
    //
    pui32DataRx[2] = MAP_I2CMasterDataGet(I2C7_BASE);

    //
    // Setup for the third read. Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH
    // to terminate the I2C transaction. At the end of this transaction,
    // the STOP bit will be issued and the I2C bus is returned to the
    // Idle state.
    //
    MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    //
    // Wait until master module is done transferring.
    //
    while(!MAP_I2CMasterBusy(I2C7_BASE))
    {
    }
    while(MAP_I2CMasterBusy(I2C7_BASE))
    {
    }

    //
    // Note the third 8-bit data is the checksum byte. It will be
    // left to the users as an exercise if they want to verify if the
    // checksum is correct.
    pui32DataRx[3] = MAP_I2CMasterDataGet(I2C7_BASE);
    }

  • I do not understand your question. The time required to read the pressure is a function of the pressure transducer. Does it support 400K baud? To avoid spending time waiting for the I2C module you can use interrupts like in the first example I sent you. It does not reduce the overall time to read the I2C, but it does allow the CPU to do other things instead of just waiting.

  • my question is i am try to get data from i2c device and store in buffer  store data

  • OK, just create an array and each time you read the pressure sensor, store the value read in the array. Then increment your index. Is this what you are asking?

  • Something like this:

    //*****************************************************************************
    //
    // calculation of pressure data
    //
    //*****************************************************************************
    #define NUMBER_SAMPLES 1024
    float pressureSamples[NUMBER_SAMPLES];
    unsigned int sampleIndex = 0;
    
    void calculation_pressure(void)
    {
        float fpressure;
        uint32_t pui32DataRx[4] = {0};
    
        ///
        // Read the pressure measurements
        //
    
        I2CReadCommand(&pui32DataRx[0]);//
        // Process the raw measurement and convert it to physical
        // pressure percentage. Refer to the AMS datasheet for the
        // conversion formula.
        //
        pui32DataRx[0] = ((pui32DataRx[0] << 8) + (pui32DataRx[1]));
        fpressure =(float)((pui32DataRx[0]-3277 )/(float)(26214/100));
        if(sampleIndex < NUMBER_SAMPLES)
        {
            pressureSamples[sampleIndex++] = fpressure;
        }
    }
    

  • its working fine.

    thank so much your response Bob Crosby