Sunday, April 21, 2013

Stellaris LaunchPad working I2C code example

I tried using Stellaris LaunchPad evaluation board (EK-LM4F120XL) with I2C communication and I had a trouble. I'd like to show you a working I2C code example here to avoid wasting time.

The reason of the difficulty was that the Launch Pad I2C pins for booster pack were shared with other GPIO pins in the default configuration. Therefore you need to configure the pins in right way.

See the function SetupI2C() below.


#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_uart.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_i2c.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "driverlib/rom.h"
#include "driverlib/i2c.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define I2C_SLAVE_ADDRESS       0x60

/*****************************************************************************/
/* This function returns:
 * I2C_MASTER_ERR_NONE, I2C_MASTER_ERR_ADDR_ACK, I2C_MASTER_ERR_DATA_ACK, or
 * I2C_MASTER_ERR_ARB_LOST.
 */
static unsigned long WaitI2CDone( unsigned int long ulBase){
    // Wait until done transmitting
    while( I2CMasterBusy(I2C3_MASTER_BASE));
    // Return I2C error code
    return I2CMasterErr( I2C3_MASTER_BASE);
}

static void SetupI2C(){
    /***
     * Shared Pin Setting
     */
    // You need to set the shared pins as input.
    GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    // Change the pad configuration to WPU
    GPIOPadConfigSet( GPIO_PORTB_BASE, GPIO_PIN_6 | GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);

    /***
     * I2C Setting
     */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0); //  special I2CSCL treatment for M4F devices
    GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

    GPIOPinConfigure(GPIO_PD0_I2C3SCL);
    GPIOPinConfigure(GPIO_PD1_I2C3SDA);

    SysCtlPeripheralEnable( SYSCTL_PERIPH_I2C3);

    I2CMasterInitExpClk( I2C3_MASTER_BASE, SysCtlClockGet(), false);
    SysCtlDelay(10000);
}


int main(void) {
    uint8_t data = 0;
    int16_t i2c_err = I2C_MASTER_ERR_NONE;

    //
    // 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);
    SysCtlDelay(10000);

    SetupI2C();

    /** Send register address.
     */
    I2CMasterSlaveAddrSet( I2C3_MASTER_BASE, I2C_SLAVE_ADDRESS, false);   // false = write, true = read
    // Set register address of AK8963
    I2CMasterDataPut( I2C3_MASTER_BASE, 0x00);
    // Start sending data
    I2CMasterControl( I2C3_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    WaitI2CDone( I2C3_MASTER_BASE);

    /** Set read mode.
     */
    I2CMasterSlaveAddrSet( I2C3_MASTER_BASE, I2C_SLAVE_ADDRESS, true);   // false = write, true = read

    /** Single Read
     */
    I2CMasterControl( I2C3_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    if( (i2c_err = WaitI2CDone( I2C3_MASTER_BASE)))
        data = 0xff;
    else
        data = I2CMasterDataGet(I2C3_MASTER_BASE);

    return 0;
}


6 comments:

  1. Hi,
    We are trying to test this code on a stellaris, and having a few issues with building the example. The I2C3_MASTER_BASE parameter was not recognized so we changed this to I2C3_BASE, this resolved that issue. However the code now has a linker issue. I believe this is something to do with Code Composer Studio, as had issues before copying and pasting examples. It is possible you can upload the entire project as a zip file?

    Thanks for the post,
    Ant

    ReplyDelete
    Replies
    1. Hi Ant,
      Thank you for your comment. I uploaded the project file here:
      https://drive.google.com/file/d/0B1V8jj4AdbrpUDA3dXNzSm9jMkk/edit?usp=sharing
      Please check two things:
      (1) PART_LM4F120H5QR is defined in "Predefined Symbols" at CCS Build > ARM Compiler > Advanced Options
      (2) driverlib-cm4f.lib is included in File Search Path at CCS Build > ARM Linker > File Search Path
      I hope you can solve your problem.

      Delete
    2. I am tring to connect accelerometers to stellaris launchpad .. i saw your coding and tried to compile that .. i am facing errors in that ...can you please help me ,???

      Delete
    3. Just read the Reference Manual and create your own setup routine. It is better that way since you have the whole subject covered.

      Delete
  2. Thanks for very nice information.
    I was a fool who believed the StellarisWare’s sample code!

    Correct answer is this:
    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);

    ReplyDelete
  3. how do I get 2 bytes form the slave at the same time? please help me

    ReplyDelete