Jump to content
Sign in to follow this  

I2C with Stellaris LM4F120H5QR - working driver API example code

Recommended Posts



I've uploaded a I2C library to the 'Stellaris Sharing Forum' on TI E2E: http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/235926.aspx


Besides some basic routines for reading/writing (single register and bulk data) it includes a routine for 'sniffing' I2C addresses (also refer to http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/t/235977.aspx).


As mentioned in the posts the Lib is still lacking timeout and error handling, so feel free to contribute!




Edited by bluehash
[ADMIN] - Added file.

Share this post

Link to post
Share on other sites

Very usefull indeed! :-) Have you looked at fast mode plus (FM+) or high speed (HS) modes?

Hi Pny,


yes, I've thought about implementing both modes. But since they need a somewhat different handling/setup, I didn't implement both modes in the first release of the API.





This is very useful. Thank you :)

But have one question - How to modify APIs to operate with AT24C32 Atmel eprom (2 word address) ?






Hi Wojtek,


well, I need to say that I didn't tested this (simply because I don't have a I2C device at hands that needs a 16-bit address), but it should be possible to do it like this:


1.) You should define a new union data type that holds the memory address. Your new data type should give you the possibility to access the address as 16bit int (for ease of use) and as 2 chars.

I.e. like this:


/* ============================================================================

// union to convert integer to two unsigned char or vice versa

// ADDRESS        : 16-bit (integer) address

// LOWBYTE        : lowbyte of integer value

// HIGHBYTE       : highbyte of integer value

// ==========================================================================*/



    unsigned int ADDRESS;

    struct //SPLIT


      unsigned char LOWBYTE;

      unsigned char HIGHBYTE;




Maybe you need to change the position of the LOW/HIGH-Byte in the structure because of the Stellaris memory organization. The code above is tested and verified on MSP430!


Now that you have a new data type available, you can define a new variable which represents the EEPROM address:


// union of type SPLITINTTOBYTE which hold the 16bit EEPROM memory address

static union SPLITINTTOBYTE uat24c32;


2.) You need a local (or global) buffer array were you store the data which you want to write to the EEPROM or were read from the EEPROM. 


// array stores data to write to/read from EEPROM


char EEPROMValues[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00, 0x00};


3.) Using this in the application:


Lets assume:

- The AT24C32 is connected to I2C0

- The I2C-device address is 0b101000 = 0x50 (A2 to A0 tied to GND)

- You want to write the following sequence of data to the EEPROM (more than one byte of data --> page write): 0x01, 0x02, 0x03, 0x04, 0xAA

- The data should be written to page no 100 (the AT24C32 has 128 pages a 32bytes each = 4096 * 8 bit = 32K --> the start address for your data write should be 0x0C80 (if I calculated right)


With these assumptions your code should look like:


// initialize memory address for EEPROM data write

uat24C32.ADDRESS = 0x0C80;


// prepare data buffer

// the EEPROM uses 16bit addressing. Since the High-Byte of the address is part of the 'I2CWriteData' API-function, the first 'data byte' to transfer needs to be the Low-Byte of the address, followed by 'real' data bytes

// get low byte of address from the union

EEPROMValues[0] = uat24C32.SPLIT.LOWBYTE;

// prepare data to be written

EEPROMValues[1] = 0x01;

EEPROMValues[2] = 0x02;

EEPROMValues[3] = 0x03;

EEPROMValues[4] = 0x04;

EEPROMValues[5] = 0xAA;


I2CWriteData(I2C0_MASTER_BASE, 0x50, uat24C32.SPLIT.HIGHBYTE, EEPROMValues, 6);



I need to think a little more about reading from the EEPROM, but I would try to see if the following approach works:


// initialize memory address for EEPROM data write

uat24C32.ADDRESS = 0x0C80;


// prepare the buffer for transfer


// get low byte of address from the union

EEPROMValues[0] = uat24C32.SPLIT.LOWBYTE;


// do a dummy write to the EEPROM to set the memory address to 0x0C80

I2CWriteData(I2C0_MASTER_BASE, 0x50, uat24C32.SPLIT.HIGHBYTE, EEPROMValues, 1);


// don't know if this works! Hopefully the dummy byte 0x00 gets ignored by the EEPROM and reading starts. 


I2CReadData(I2C0_MASTER_BASE, 0x50, 0x00, EEPROMValues, 5);



If this will not work you can write your own extension to the routines to deal with 16-bit addresses.




Share this post

Link to post
Share on other sites


Thanks a lot :)

I shall try to implement your method in my program and let you know about results.

Your description is very clear , thank You once more !





Share this post

Link to post
Share on other sites
i want to interface lm75b temp sensor. i did not receiving the correct value is there any problem in coding 


kindly help me that what changes i have to made

#define SYSTICKHZ 1000
#define SYSTICKMS (1000 / SYSTICKHZ)
#define LM75B_ADDR 0x90

// LM75B registers
#define LM75B_Conf 0x01
#define LM75B_Temp 0x00
#define LM75B_Tos 0x03
#define LM75B_Thyst 0x02
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_ints.h"

#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/interrupt.h"
#include "driverlib/ssi.h"
#include "utils/ustdlib.h"

#include "I2C_Stellaris_API.h"
#ifdef DEBUG
__error__(char *pcFilename, unsigned long ulLine)
void main(void)
int a = 0;
int b = 0;
float c;
int d=3;
char cmd[2]={0x01,0x00};
char temp_Values[2]={2,2};

I2CSetup(I2C1_MASTER_BASE, 0);
// d=I2CRegRead(I2C0_MASTER_BASE, LM75B_ADDR,0x02);
d=I2CRegWrite(I2C1_MASTER_BASE,LM75B_ADDR,0x00,LM75B_Conf);// here returned value is 0, i dont know where is error

// replace with timer for 4.5ms delay
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
asm(" NOP");

void SysTickIntHandler(void)


Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Create New...