Jump to content
Sign in to follow this  
aBUGSworstnightmare

I2C with Stellaris LM4F120H5QR - working driver API example code

Recommended Posts

Hi,

 

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!

 

Rgds
aBUGSworstnightmare

8311.I2C_Stellaris_API_r02.zip

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.

 

 

 

Hi,

This is very useful. Thank you :)

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

 

TIA

 

Wojtek

 

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

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

  union SPLITINTTOBYTE

  {

    unsigned int ADDRESS;

    struct //SPLIT

    {

      unsigned char LOWBYTE;

      unsigned char HIGHBYTE;

    }SPLIT;

  };

 

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. 

I.e.:

// 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.

 

Rgds

aBUGSworstnightmare

Share this post


Link to post
Share on other sites

@aBUGS...e

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 !

 

Rgds

 

Wojtek

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
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif
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};
SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);



ROM_IntMasterEnable();
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

while(1)
{
// replace with timer for 4.5ms delay
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
I2CReadData(I2C1_MASTER_BASE,LM75B_ADDR,LM75B_Temp,temp_Values,2);
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
a=(int)temp_Values[0];
b=(int)temp_Values[1];
c=(a|b)/256;
SysCtlDelay((ROM_SysCtlClockGet() / SYSTICKHZ) * 5);
asm(" NOP");
}
}



void SysTickIntHandler(void)
{

}



Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×