Hi,
If you just want to handle EEPROMs, the attached code might help.
Regards,
Steve
Dietmar Scherhoff wrote:
First- thanks to all for the quick reply!
It is a I2C master I need ( EEPROM, port expander etc.).
Yes please- send me all you have.
One information:
The new F15X, F16X, F161X will have hardware I2C - coming III/2003 and
IV/2003, propably.
// These routines support a single I2C EEPROM attached to
// two pins of a port on an MSP430.
//
//Please note:
//
// These routines have been tested with an Atmel 2401. They
// are intended to work with a range of I2C interface serial
// EEPROMs, but should be thoroughly tested against any
// other EEPROM before serious use.
//
// Since the EEPROM will be operating at a low voltage, when
// connected to the MSP430, this code is designed to operate
// at the worst case timing for the Atmel chips, at their
// lowest recommended supply voltage, and with the MSP430
// running at 8MHz. They could be tuned for faster operation
// in other environments.
//#define EEPROMTYPE 32 // PAGE 32
//#define EEPROMTYPE 16 // PAGE 16
#define EEPROMTYPE 8 // PAGE 8
#define MAX_TRIES 200
#if EEPROMTYPE == 32
#define BYTES_PER_PAGE 32
#elif EEPROMTYPE == 16
#define BYTES_PER_PAGE 16
#else
#define BYTES_PER_PAGE 8
#endif
static void delay(int i)
{
register int j;
for ( ; i; i--)
{
#if defined(__GNUC__) && defined(__MSP430__)
j = 8;
__asm__ __volatile__ (
"1: \n"
" dec %[j] \n"
" jge 1b \n"
: [j] "+r"(j));
#elif defined(__AQCOMPILER__)
for (j = 8; j; j--)
_NOP();
#endif
}
}
static void I_start(void)
{
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
delay(2); //At least ???
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
delay(5); //At least 4.7us
IICEEPROM_PORT_OUT &= ~IICEEPROM_SDA_BIT;
delay(5); //At least 4.7us
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
}
static void I_stop(void)
{
IICEEPROM_PORT_OUT &= ~IICEEPROM_SDA_BIT;
delay(2); //At least ???
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
delay(5); //At least 4.7us
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
delay(5); //At least 4.7us
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
}
static int I_send(uint8_t a)
{
int i;
for (i = 8; i > 0; i--)
{
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
//The data can now change without delay
if (a & 0x80)
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
else
IICEEPROM_PORT_OUT &= ~IICEEPROM_SDA_BIT;
a <<= 1;
delay(5); //At least 4.7us
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
delay(5); //At least 4.7us
}
IICEEPROM_PORT_OUT &= ~(IICEEPROM_SCL_BIT | IICEEPROM_SDA_BIT);
delay(5);
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
IICEEPROM_PORT_DIR &= ~IICEEPROM_SDA_BIT; //Input
delay(5);
i = IICEEPROM_PORT_IN & IICEEPROM_SDA_BIT;
IICEEPROM_PORT_DIR |= IICEEPROM_SDA_BIT; //Output
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
delay(4);
return i;
}
static uint8_t I_receive(void)
{
uint8_t a;
int i;
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
IICEEPROM_PORT_DIR &= ~IICEEPROM_SDA_BIT; //Input
a = 0;
for (i = 8; i > 0; i--)
{
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
delay(5); //At least 4.7us
a <<= 1;
if (IICEEPROM_PORT_IN & IICEEPROM_SDA_BIT)
a |= 0x01;
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
delay(5); //At least 4.7us
}
IICEEPROM_PORT_DIR |= IICEEPROM_SDA_BIT; //Output
return a;
}
static void I_ack(int ok)
{
if (ok)
IICEEPROM_PORT_OUT &= ~IICEEPROM_SDA_BIT;
else
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
delay(4);
IICEEPROM_PORT_OUT |= IICEEPROM_SCL_BIT;
delay(4);
IICEEPROM_PORT_OUT &= ~IICEEPROM_SCL_BIT;
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
}
static int T_SDA(void)
{
int i;
IICEEPROM_PORT_OUT |= IICEEPROM_SDA_BIT;
delay(4);
IICEEPROM_PORT_DIR &= ~IICEEPROM_SDA_BIT; //Input
for (i = 16; i > 0; i--)
{
delay(5);
if (!(IICEEPROM_PORT_IN & IICEEPROM_SDA_BIT))
break;
}
IICEEPROM_PORT_DIR |= IICEEPROM_SDA_BIT; //Output
return i;
}
void testsda(void)
{
I_stop();
while (T_SDA())
/*dummy loop*/;
}
int iicEEPROM_read(uint16_t addr, void *dat, int len)
{
int i;
int j;
uint8_t *p;
for (i = 0; i < MAX_TRIES; ++i)
{
if (i)
{
// Read FALSE, retry
I_stop();
if (T_SDA())
continue;
}
I_start();
#if EEPROMTYPE == 32
if (I_send(0xA0) || I_send(addr/0x100))
continue;
#else
if (I_send(0xA0 | ((uint8_t)(addr/0x100)*2)))
continue;
#endif
if (I_send(addr))
continue;
p = (uint8_t *) dat;
I_start();
#if EEPROMTYPE == 32
if (I_send(0xA1))
continue;
#else
if (I_send(0xA1 | ((uint8_t)(addr/0x100)*2)))
continue;
#endif
for (j = len; j > 0; --j)
{
*p++ = I_receive();
I_ack(TRUE);
}
*p = I_receive();
I_ack(FALSE);
I_stop();
return TRUE;
}
I_stop();
return FALSE;
}
int iicEEPROM_write(uint16_t addr, void *dat, int len)
{
int i;
int j;
uint8_t *p;
//Check for a block crossing a page boundary
if (len > (BYTES_PER_PAGE - (addr%BYTES_PER_PAGE)))
return FALSE;
for (i = 0; i < MAX_TRIES; ++i)
{
if (i)
{
// Write FALSE, retry
I_stop();
if (T_SDA())
continue;
}
I_start();
#if EEPROMTYPE == 32
if (I_send(0xA0) || I_send(addr/0x100))
continue;
#else
if (I_send(0xA0 | ((uint8_t)(addr/0x100)*2)))
continue;
#endif
if (I_send(addr))
continue;
p = (uint8_t *) dat;
for (j = len; j > 0; --j)
{
if (I_send(*p))
break;
p++;
}
if (j == 0)
{
I_stop();
return TRUE;
}
}
I_stop();
return FALSE;
}