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;
}

Reply via email to