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.

TM4C123GH6PZ: I2C communication between 2 TIVA board

Part Number: TM4C123GH6PZ

Hi,

I am a student , I was trying to communicate between two tiva board using I2C.I have two doubt, one is related to i2c communication with interrupt and other one is back and forth communication using i2c.

Doubt 1.

I was doing the I2C communication with interrupt and it is working.

The code given below.

#include "stdio.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "inc/hw_nvic.h"
#include "driverlib/timer.c"
#include "driverlib/systick.c"
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/uart.h"
#include "driverlib/rom.h"
#include "inc/hw_ints.h"
#include "driverlib/ssi.h"
#include "driverlib/i2c.h"
#include "inc/hw_i2c.h"
void delay(int a);
 #define SLAVE_ADDRESS 0x20
int main()
{

 SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
 GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
  GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
  GPIOPinConfigure(GPIO_PB2_I2C0SCL);
  GPIOPinConfigure(GPIO_PB3_I2C0SDA);
 I2CMasterEnable(I2C0_BASE);

I2CMasterInitExpClk(I2C0_BASE,SysCtlClockGet(),false);

IntMasterEnable();
 I2CMasterIntEnable(I2C0_BASE);
  IntEnable(INT_I2C0);

while(1)
 {
I2CMasterSlaveAddrSet(I2C0_BASE,SLAVE_ADDRESS,false);  
I2CMasterDataPut(I2C0_BASE,0xBB);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
  SysCtlDelay(1000);

}}

void I2C0_Handler(void){
uint32_t ui32Status;
ui32Status = I2CMasterIntStatus(I2C0_BASE, true); //get interrupt status
I2CMasterSlaveAddrSet(I2C0_BASE,SLAVE_ADDRESS,false);  
I2CMasterDataPut(I2C0_BASE,0xCC);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//while(!I2CMasterBusy(I2C0_BASE));
I2CMasterIntClear(I2C0_BASE);//Clear the interrupt
}

I was using interrupt in master code only. my doubt is,  if I am not giving the highlighted condition inside the while loop or outside the while loop also the interrupt handler function is executing. If I am not using those commands then i2c interrupt handler function wont execute it will stop in IntEnable(INT_I2C0) this command. Please let me know why it is happening. Slave code given below 

Slave code

#include "stdio.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/uart.h"
#include "inc/hw_ints.h"
#include "driverlib/i2c.h"

void InitConsole(void);

int main()
{
 char data, char_rx,receive;

SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN); //seting system clock as 8Mhz
  InitConsole();

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
 //configure the muxing and GPIO settings to bring the SSI functions out to the pins
 GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
  GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
  GPIOPinConfigure(GPIO_PB2_I2C0SCL);
  GPIOPinConfigure(GPIO_PB3_I2C0SDA);
 I2CSlaveAddressSet(I2C0_BASE,0,0x20);
 I2CSlaveInit(I2C0_BASE,0x20);
 I2CSlaveEnable(I2C0_BASE);

while(1) {
  
   char_rx=I2CSlaveDataGet(I2C0_BASE);
while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ));
  
   UARTCharPut(UART0_BASE,char_rx );
  
 }}

void InitConsole(void)
 {
 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
  GPIOPinConfigure(GPIO_PA0_U0RX);
 GPIOPinConfigure(GPIO_PA1_U0TX);
  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
 }

Doubt 2

I want to send data back and forth between 2 tiva board using i2c, without interrupt I am doing this. I was able to achieve master to slave communication but the aim is send back the same data to master and display through UART. In serial monitor I was getting garbage values.

The code is given below

Master code 

#define SLAVE_ADDRESS 0x20
 void InitConsole(void);
 char data;
 
int main()
{

SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN); //seting system clock as 8Mhz
  InitConsole();

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
 //configure the muxing and GPIO settings to bring the SSI functions out to the pins
 GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
  GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
  GPIOPinConfigure(GPIO_PB2_I2C0SCL);
  GPIOPinConfigure(GPIO_PB3_I2C0SDA);
 I2CMasterEnable(I2C0_BASE);

I2CMasterInitExpClk(I2C0_BASE,SysCtlClockGet(),false);

while(1)
 {
I2CMasterSlaveAddrSet(I2C0_BASE,SLAVE_ADDRESS,false);  
I2CMasterDataPut(I2C0_BASE,0xBB);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//while(!I2CMasterBusy(I2C0_BASE));
while(I2CMasterBusy(I2C0_BASE));
I2CMasterSlaveAddrSet(I2C0_BASE,SLAVE_ADDRESS,true); 
 I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
  data= I2CMasterDataGet(I2C0_BASE);
 while(I2CMasterBusy(I2C0_BASE));
 UARTCharPut(UART0_BASE,data);

}}

void InitConsole(void)
 {
 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
  GPIOPinConfigure(GPIO_PA0_U0RX);
 GPIOPinConfigure(GPIO_PA1_U0TX);
  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
 } 

Slave code

int main()
{
 char data, char_rx,receive;

SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN); 
  InitConsole();

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
 GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
  GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
  GPIOPinConfigure(GPIO_PB2_I2C0SCL);
  GPIOPinConfigure(GPIO_PB3_I2C0SDA);
 I2CSlaveAddressSet(I2C0_BASE,0,0x20);
 I2CSlaveInit(I2C0_BASE,0x20);
 I2CSlaveEnable(I2C0_BASE);

while(1) {

char_rx=I2CSlaveDataGet(I2C0_BASE);
 while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ));
  I2CSlaveDataPut(I2C0_BASE,char_rx);
  
 }}

Please let me know what are the Issues and how I can make it as a working code. I am a student and not having that much experience with embedded C and Tiva also. so please help me. I am hoping some one can help me to solve these issues.

Thank you so much,

Mariya

  • Hello Mariya,

    I am not really understanding your Doubt 1, can you try and explaining further, or just post both the working and non-working versions so I can compare?

    For doubt 2, that is an easy enough fix. You have most of the right logic there, but a couple things are out of order and you are missing one key line for the slave.

    Fixes for the Master side:

    Swap the following lines so you wait first, then get the data:

     data= I2CMasterDataGet(I2C0_BASE);
     while(I2CMasterBusy(I2C0_BASE));

    Fixes for the Slave side:

    Use these 4 lines inside your while(1) loop:

    		while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ));
    		char_rx=I2CSlaveDataGet(I2C0_BASE);
    
    		while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ));
    		I2CSlaveDataPut(I2C0_BASE,char_rx);
    

    That should get the transmit going between the boards.

    Also I'd recommend sending an ASCII character like 0x41 which is an 'A' so you can verify it's actual data being received. As you don't have any error handling yet, when the master is powered and the slave isnt, it is reading in garbage data until the slave is powered and then it will read the actual data.

    By the way this app note may be helpful for you: www.ti.com/.../spma073.pdf

  • Hi,

    Thank you so much for your reply.

    I did those changes whatever you told to do in  back and forth communication in I2C(doubt 2).but still it is not communicating and it was stopping at while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ));  this command in slave.Please let me know what will be the issue.how we can resolve it.

    I am not really understanding your Doubt 1, can you try and explaining further, or just post both the working and non-working versions so I can compare?

    I will explain my doubt again.

    The code whatever I given first is working code only.

    Given below is the non working code.

    #include "stdio.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "hw_memmap.h"
    #include "inc/hw_ints.h"
    #include "driverlib/pin_map.h"
    #include "inc/hw_types.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/systick.h"
    #include "driverlib/timer.h"
    #include "inc/hw_nvic.h"
    #include "driverlib/timer.c"
    #include "driverlib/systick.c"
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/uart.h"
    #include "driverlib/rom.h"
    #include "inc/hw_ints.h"
    #include "driverlib/ssi.h"
    #include "driverlib/i2c.h"
    #include "inc/hw_i2c.h"
    void delay(int a);
     #define SLAVE_ADDRESS 0x20
    int main()
    {

     SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
     while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
     GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
     I2CMasterEnable(I2C0_BASE);

    I2CMasterInitExpClk(I2C0_BASE,SysCtlClockGet(),false);

    IntMasterEnable();

    I2CMasterIntEnable(I2C0_BASE);
      IntEnable(INT_I2C0);

    while(1)
     {

    }

    void I2C0_Handler(void){
    uint32_t ui32Status;
    ui32Status = I2CMasterIntStatus(I2C0_BASE, true); //get interrupt status
    I2CMasterSlaveAddrSet(I2C0_BASE,SLAVE_ADDRESS,false);  
    I2CMasterDataPut(I2C0_BASE,0xCC);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    //while(!I2CMasterBusy(I2C0_BASE));
    I2CMasterIntClear(I2C0_BASE);//Clear the interrupt
    }

    I think this will give a better idea about the difference between working and non working code. My doubt is the highlighted section in the first code, if I am placing inside the while loop then only the interrupt handler function execute. Please explain why it is happening.

    Both slave code is same.

    Thank you so much,

    Mariya

  • Hello Mariya,

    Well the non-working code isn't doing anything because you have nothing triggering any operation after you finish initialization. With your while loop empty, it is just going to sit there.

    Meanwhile the working code gets the first I2C transaction triggered by what is inside the while(1) loop and runs from there.

    Regarding the suggestions I made not working, lets simplify this, I'll post the .c files I had based on your code so you can just download them to get all the code in your project properly.

    Master: 

    i2c_master.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    //*****************************************************************************
    //
    // master_slave.c - Example demonstrating a simple I2C message
    // transmission and reception.
    //
    // Copyright (c) 2010-2018 Texas Instruments Incorporated. All rights reserved.
    // Software License Agreement
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    // Redistributions of source code must retain the above copyright
    // notice, this list of conditions and the following disclaimer.
    //
    // Redistributions in binary form must reproduce the above copyright
    // notice, this list of conditions and the following disclaimer in the
    // documentation and/or other materials provided with the
    // distribution.
    //
    // Neither the name of Texas Instruments Incorporated nor the names of
    // its contributors may be used to endorse or promote products derived
    // from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    #define DEBUG true
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #define SLAVE_ADDRESS 0x20
    //void InitConsole(void);
    unsigned long k=0;
    void InitConsole(void);
    uint32_t n=3,i;
    char char_tx[]="abc";
    char char_rx[3],data;
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Slave: 

    i2c_slave.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    //*****************************************************************************
    //
    // master_slave.c - Example demonstrating a simple I2C message
    // transmission and reception.
    //
    // Copyright (c) 2010-2018 Texas Instruments Incorporated. All rights reserved.
    // Software License Agreement
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    // Redistributions of source code must retain the above copyright
    // notice, this list of conditions and the following disclaimer.
    //
    // Redistributions in binary form must reproduce the above copyright
    // notice, this list of conditions and the following disclaimer in the
    // documentation and/or other materials provided with the
    // distribution.
    //
    // Neither the name of Texas Instruments Incorporated nor the names of
    // its contributors may be used to endorse or promote products derived
    // from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    #define DEBUG true
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    #if DEBUG
    void
    InitConsole(void)
    {
    //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi sir,

    Thank you so much for your clarification. Now I understood the difference and I got a better understanding about interrupts. 

    The code you sent  was similar to my latest code. I rewired everything and again flash both of the board and now it is communicating.

    Thank you so much for your help to resolve my issue.

    Thank you,

    Mariya