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.

TM4C123GH6PM: Software (Bitbanged) I2C implementation on TM4C123GH6PM MCU

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: MSP430F5529

Hi All,

I have been trying to implement bit-banged I2C communication protocol on TM4C123GH6PM. My problem is, I am not able to figure-out the right configuration for the GPIO registers in order to get the I2C working in right way. Can you please help me in this regard?

Pins being used for I2C:

Pin PF1 - SDA

Pin PF2 - SCL

Slave device - MSP430F5529 (It uses Hardware I2C)

Master device - TM4C123GH6PM (It uses Software (bitbanged) I2C)

External pull-up resistors for SDA & SCL - 10 KOhm each

The functions written for I2C are,

/* Configure I2C */
void I2C_Configure(void)
{
/* GPIO Initialization and Configuration */

SYSCTL->GPIOHBCTL_b.PORTF = 0; SYSCTL->RCGCGPIO_b.PORTF = 1;

/* Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO) */
SYSCTL->RCGCGPIO |= 0x20; /* Port F */

/* Allow time for clock to stabilize (SYSCTL->PRGPIO) */
while((SYSCTL->PRGPIO & (0x20) ) != (0x20) ){};

// 3. Set Analog Mode Select bits for each Port (GPIO->AMSEL 0=digital, 1=analog)
GPIOF->AMSEL = 0x00;

// 4. Set Port Control Register for each Port (GPIO->PCTL, check the PCTL table)
GPIOF->PCTL = 0x00;

// 5. Set Alternate Function Select bits for each Port (GPIO->AFSEL 0=regular I/O, 1=PCTL peripheral)
GPIOF->AFSEL = 0x00;

// 6. Set Output pins for each Port (Direction of the Pins: GPIO->DIR 0=input, 1=output)
GPIOF->DIR = ~(I2C_SDA | I2C_SCL); // PF2,PF1 for Input

// 8. Set Digital Enable register on all GPIO pins (GPIO->DEN 0=disable, 1=enable)
GPIOF->DEN = I2C_SDA | I2C_SCL; // Enable all digital pins on PortF (PF2,PF1)

/* Set DATA register as 0 always for SDA and SCL */
GPIOF->DATA = ~(I2C_SDA | I2C_SCL);

GPIOF->ODR = I2C_SDA | I2C_SCL;

I2C_SCL_HIGH();
I2C_SDA_HIGH();

/* Small delay */
xdelay(I2C_DELAY_VALUE);
}

/* SDA HIGH */
void I2C_SDA_HIGH(void)
{
/* Data enable disabled to float SDA */
GPIOF->DIR &= ~I2C_SDA;

//GPIOF->ODR &= ~I2C_SDA;

/* Small delay */
xdelay(I2C_DELAY_VALUE);
}

/* SDA LOW */
void I2C_SDA_LOW(void)
{
/* Output */
GPIOF->DIR |= I2C_SDA;

//GPIOF->ODR |= I2C_SDA;

/* Small delay */
xdelay(I2C_DELAY_VALUE);
}

/* SCL HIGH */
void I2C_SCL_HIGH(void)
{
/* Data enable disabled to float SCL */
GPIOF->DIR &= ~I2C_SCL;

//GPIOF->ODR &= ~I2C_SCL;

/* Small delay */
xdelay(I2C_DELAY_VALUE<<1);
}

/* SCL LOW */
void I2C_SCL_LOW(void)
{
/* Output */
GPIOF->DIR |= I2C_SCL;

//GPIOF->ODR |= I2C_SCL;

/* Small delay */
xdelay(I2C_DELAY_VALUE);
}

Are the four functions I2C_SCL_LOW, I2C_SCL_HIGH, I2C_SDA_HIGH and I2C_SDA_LOW are safe to use or have the right configuration when the external pull-up used?

Note: I have already done similar implementation in MSP430 MCU, but I wanted to switch to TIVA series.

Thanks in advAnce,

vksalian

  • Vijay Salian said:
    I have been trying to implement bit-banged I2C communication protocol

    May it be asked, "Why have you been so trying?"    Unless this is a 'course requirement' - this quest makes (little) sense!   (and if it IS a course requirement - course staff should assist...)

    You know - or should know - that these MCUs include multiple, fully implemented I2C Ports.    And a potent software API - which, 'speeds, eases & enhances' the I2C implementation.

    Yet - you propose, 'Avoiding this full & complete 'body of work' - and commit (instead) to a demanding challenge - which thus far has proven unsuccessful.    Again ... Why?

    Your effort is further complicated - hugely complicated - by your (near) or exclusive use of Direct Register code.   Vendor agents (quite properly) will not assist such efforts - offering the API - of course.

    A very large part of 'success w/MCUs' revolves around being able, 'To identify and adopt the 'most qualified' of solutions.'    Somehow - your coursework appears to have 'missed' that...

  • First let me comment that there are four I2C modules on this device. Trying to create a fifth by bit-banging is a bit unique, and not very CPU efficient.

    Second, we strongly advise against doing direct register writes like you have in the code you posted above. The TivaWare library provides proven functions that greatly simply the pin configuration you are trying to do. Using the library functions will increase your productivity and make it much easier for anyone on the forum to understand and help you.

    Here is an example:

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    
    #define SDA GPIO_PIN_1
    #define SCL GPIO_PIN_2
    #define SDA_H GPIOPinWrite(GPIO_PORTF_BASE, SDA, SDA);
    #define SDA_L GPIOPinWrite(GPIO_PORTF_BASE, SDA, 0);
    #define SCL_H GPIOPinWrite(GPIO_PORTF_BASE, SCL, SCL);
    #define SCL_L GPIOPinWrite(GPIO_PORTF_BASE, SCL, 0);
    #define CLK {SCL_H; SysCtlDelay(20); SCL_L;}
    #define START {SDA_L; SysCtlDelay(20); SCL_L;}
    #define STOP {SCL_H; SysCtlDelay(20); SDA_H;}
    
    
    //*****************************************************************************
    //
    // Main 'C' Language entry point.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Setup the system clock to run at 50 Mhz from PLL with crystal reference
        //
        SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|
                        SYSCTL_OSC_MAIN);
    
        //
        // Enable and wait for the port to be ready for access
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
        {
        }
        
        //
        // Configure the GPIO port for the Open Drain operation.
        //
        GPIOPinTypeGPIOOutputOD(GPIO_PORTF_BASE, SDA | SCL);
        SCL_H;
        SDA_H;
        SysCtlDelay(200);
    
        START;
        SysCtlDelay(20);
        SDA_L;              // MSb
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // bit 6
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // bit 5
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // bit 4
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_L;              // bit 3
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // bit 2
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // bit 1
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_L;              // bit 0
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        SDA_H;              // ACK
        SysCtlDelay(20);
        CLK;
        SysCtlDelay(20);
        STOP;
    }
    

  • Hi Bob,

    Thank you for the help! 

    Bob Crosby said:
    four I2C modules on this device. Trying to create a fifth by bit-banging is a bit unique, and not very CPU efficient.

    Ya I know that there are I2C modules present in the TM4C123GH6PM MCU. I am new to TIVA Series MCUs and I was trying to be familiar with GPIO configurations. So thought of implementing I2C using GPIOs.

    Bob Crosby said:
    Second, we strongly advise against doing direct register writes like you have in the code you posted above

    Sure, I will refer tivaware libraries in future.

    As suggested by you, I configured SDA and SCL pins (being used for bi-banged I2C) as below,

    1. SDA & SCL as open drive outputs.

    2. SDA & SCL direction as Output.

    3. DEN (Digital Enable) register values reset to 0.

    With the above configuration, I could write the DATA to I2C Slave and could not read from Slave (reading as all bits as "1" ). So, during READ operation, I changed the Direction of SDA as INPUT to read the data from Slave. I hope that is OK.

    Now, I can do Master TX -> Slave RX and Master RX -> Slave TX, both operations.

    Thank you for the kind help.

    --

    Regards,

    Vksalian

  • Hi ,

    Thank you for the response.

    I am new to TIVA C series MCUs. I was trying to understand the GPIO implementation in TM4C123GH6PM MCU since I did not find any schematic of GPIO internals (as it is available for msp430). The idea was to figure out the GPIO configuration needed to implement any protocols using software, as practice.

    --

    Thanks & Regards,

    Vksalian

  • Thank you - your motivation (now) is far more understandable - that's of some importance - is it not?     The conclusion I drew earlier was (unfortunately) based upon (much) experience - often occurring right here.    As my firm's staff is better than half - 'recent graduates & college students' - your desire for (real) learning is substantially shared.

    Vijay Salian said:
    The idea was to figure out the GPIO configuration needed to implement any protocols using software, as practice.

    While 'that' idea has some merit - as you noted - it (really) does not shed great light upon the implementation of the MCU's GPIO 'internals.'    (and - there are better methods to gain such insights...)

    More importantly (staff/I believe) is the 'Problem Solving & Analysis Ability' which the MCU creates.    And - which is far more productively delivered via the API - rather than the endless: 'search, find & selection' of (so many) esoteric MCU Registers.

    Note too - that 'even w/out high understanding of the MCU's GPIO architecture' - (near) total control of the GPIO is possible.

    Perhaps its best to master multiple elements (peripherals) of the MCU - via actual set-up, configuration & execution - rather than 'over-focus' upon  MCU's internal implementation.     Recognizing the 'top/correct' priorities - is always important...

  • Hi cb1_mobile,

    Thank you so much for the suggestions. I learnt so many things in this conversation and your ideas were really outstanding. I will consider your above suggestions in future to practical experience.

    Thank you once again.

    --

    Regards,

    Vksalian

  • Thank you - yours is one of the kindest comments (ever) received here - thus much appreciated.     (hostile comments are welcome as well - especially when 'facts accompany the attack' - and (some) logic prevails...)

    In the attempt to (somewhat) justify your comment - may (my young) Staff & I note that you appear to have, 'Entered the Path of, 'Premature Optimization.'    Indeed one needs to know (some) detail regarding each peripheral (GPIO in your case.)     And most MCU vendors provide that in (near) '1K page' MCU Manuals - which most always are segmented into MCU Peripherals.   

    Vendors are knowledgeable enough to include (most) all that is required in each 'Peripheral Section' of those manuals.    And - that which the manual leaves out - is often 'answered' by the detailed 'Use & Study' of the API's 'highly detailed' Function inventory.    There is even a manual which details (w/examples) each/every one of the API's (many) functions.   (in the past - this manual was titled, 'Peripheral Driver Library' - you would do very well to find this - and give a solid read - it is 'loaded' w/key/critical data.)

    Detailed understanding of 'every element' of an MCU Peripheral's internal implementation (in the attempt to 'optimize') rarely is required - and in fact may 'impede!     (Rather than 'accelerate' one's learning - and is likely best explored 'after' the MCU's API is mastered - which best enables understanding & appreciation of the implementation...)

    While 'optimization' sounds/seems proper - too often it 'detracts from the overall mission' - as it 'absorbs (undue) time & effort.'    (And when 'premature' - may cause the 'wrong' features/functions to be optimized - while the 'more vital' - are (unfortunately) 'time-starved thus shortchanged!')    

    A 'key reality' - it is the 'marketplace' which most always best identifies 'that' - which 'demands optimization/efficiency/clarity!'    Minus such critical 'feedback/intelligence' - most 'optimization' efforts prove 'off-mark' - and succeed (only) in delaying the 'Release of the Product!'    (thus 'missing' the critical (and brief/early) 'Highest Profit Margin' window...)