Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Garbled Data from I2C EEPROM using i2c_t3 with Teensy LC

  1. #1

    Garbled Data from I2C EEPROM using i2c_t3 with Teensy LC

    I'm stumped. I have this EEPROM device (https://datasheet.lcsc.com/szlcsc/Sh...RC_C177778.pdf) hooked up to the SCL/SDA pins (18 & 19) on a Teensy LC using 4.7k external pullup resistors and am using the following test code to attempt a basic read/write operation. I can probe both the SCL and SDA pins and see that I'm getting signal on both pins, but my Serial monitor data coming back is super weird.

    No errors are thrown, but sometimes the retrieved data is blank, sometimes it's garbled. I've tried numerous configurations and also tried a the basic example on the Wire library page (it hangs at while(Wire.read()) {
    num = Wire.receive();
    }). Where else should I look? I am at the end of the road with what I know to try.

    Here's an example of the serial output from the included program:

    Sending to Slave: 'Message #0' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #1' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #2' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #3' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #4' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #5' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #6' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #7' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #8' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #9' OK
    Reading from Slave: '' OK
    Sending to Slave: 'Message #10' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #11' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #12' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #13' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #14' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #15' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #16' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #17' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #18' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #19' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #20' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #21' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #22' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #23' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #24' OK
    Reading from Slave: 'Messaess���������>' OK
    Sending to Slave: 'Message #25' OK


    Code:
    // -------------------------------------------------------------------------------------------
    // Basic Master
    // -------------------------------------------------------------------------------------------
    //
    // This creates a simple I2C Master device which when triggered will send/receive a text 
    // string to/from a Slave device.  It is intended to pair with a Slave device running the 
    // basic_slave sketch.
    //
    // Pull pin12 input low to send.
    // Pull pin11 input low to receive.
    //
    // This example code is in the public domain.
    //
    // -------------------------------------------------------------------------------------------
    
    #include <i2c_t3.h>
    
    // Memory
    #define MEM_LEN 16
    char inbuf[MEM_LEN];
    char outbuf[MEM_LEN];
    int count;
    
    void setup()
    {
      // Setup for Master mode, pins 18/19, external pullups, 400kHz, 200ms default timeout
        Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
        Wire.setDefaultTimeout(200000); // 200ms
    
        // Data init
        count = 0;
    
        Serial.begin(9600);
    }
    
    void loop()
    {
        uint8_t target = 0x50; // target Slave address
    
        // Send string to Slave
        //
    
            // Construct data message
            memset(inbuf, 0, sizeof(inbuf));
            sprintf(inbuf, "Message #%d", count++);
    
            // Print message
            Serial.printf("Sending to Slave: '%s' ", inbuf);
    
            // Transmit to Slave
            Wire.beginTransmission(target);   // Slave address
            Wire.write(inbuf,strlen(inbuf)+1); // Write string to I2C Tx buffer (incl. string null at end)
            Wire.endTransmission();           // Transmit to Slave
    
            // Check if error occured
            if(Wire.getError())
                Serial.print("FAIL\n");
            else
                Serial.print("OK\n");
    
            delay(1000);                       // Delay to space out tests
    
    
        // Read string from Slave
        //
    
            // Print message
            Serial.print("Reading from Slave: ");
    
            memset(outbuf, 0, sizeof(outbuf));
    
            // Read from Slave
            Wire.requestFrom(target, (size_t)MEM_LEN); // Read from Slave (string len unknown, request full buffer)
    
            // Check if error occured
            if(Wire.getError())
                Serial.print("FAIL\n");
            else
            {
                // If no error then read Rx data into buffer and print
                Wire.read(outbuf, Wire.available());
                Serial.printf("'%s' OK\n",outbuf);
    
    
            }
    
            delay(1000);                       // Delay to space out tests
    
    }

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,862
    you might study the data sheet. it looks like for write() and and read() you need to provide a "word" address to the EEPROM to tell it where you want to write/read. For debugging, you might print out Wire.available() before doing the Wire.read. Here is an Arduino example of I2C EEPROM (although the example's EEPROM uses 2-byte addresses)
    https://playground.arduino.cc/code/I2CEEPROM

    The Teensy LC also has 128 bytes of on-board EEPROM, https://www.pjrc.com/teensy/td_libs_EEPROM.html
    Last edited by manitou; 03-07-2019 at 01:54 PM.

  3. #3
    Quote Originally Posted by manitou View Post
    you might study the data sheet. it looks like for write() and and read() you need to provide a "word" address to the EEPROM to tell it where you want to write/read. For debugging, you might print out Wire.available() before doing the Wire.read. Here is an Arduino example of I2C EEPROM (although the example's EEPROM uses 2-byte addresses)
    https://playground.arduino.cc/code/I2CEEPROM

    The Teensy LC also has 128 bytes of on-board EEPROM, https://www.pjrc.com/teensy/td_libs_EEPROM.html
    Ok...I managed to kind of get it working, but still have a thorough lack of understanding of what's really going on. I see in the datasheet that there's a required word address before write/read operations, but I guess I just don't get where in code that address is being sent, even though this example is working.

    Here's what I think is happening:

    for the write:

    Wire.beginTransmission(addr) is writing the device address,
    then:
    Wire.write((int)(eeaddress & 0xFF)); // LSB writes the r/w bit and the word address
    then:
    Wire.write(rdata); writes the actual data
    then:
    Wire.endTransmission(); sends the stop bit and the EEPROM chip performs the write internally.

    What I don't get, is how to form that word address...does an increased address increase the page i'm addressing or the byte i'm addressing?
    For example if I do:

    Code:
        
        int rdata = data;
        int addr = deviceaddress | ((eeaddress & 0x70) >> 7 );
        Wire.beginTransmission(addr);
        Wire.write(2); // LSB
        Wire.write(rdata);
        Wire.endTransmission();
    Code:
    Am I writing to the second byte in the EEPROM chip or the second page? Any good resources on this?
    
    /*
      *  Use the I2C bus with EEPROM 24LC64
      *  Sketch:    eeprom.ino
      *
      *  Author: hkhijhe
      *  Date: 01/10/2010
      *
      *
      */
    
    #include <Wire.h>
    
    
    void setup()
    {
        char somedata[] = "123456789ABCDEFHIJKLMNOPQRSTUV"; // data to write
    
        Wire.begin(); // initialise the connection
        Wire.setClock(400000);
        Serial.begin(9600);
        i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM
    
        delay(100); //add a small delay
    
        Serial.println("Memory written");
    }
    
    void loop()
    {
        int eeaddress=0; //first address
        byte b = i2c_eeprom_read_byte(0x50, 0); // access the first address from the memory
    
        while (b!=0)
        {
            Serial.print((char)b); //print content to serial port
            eeaddress++; //increase address
            b = i2c_eeprom_read_byte(0x50, eeaddress); //access an address from the memory
        }
        Serial.println(" ");
        delay(2000);
    }
    byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
        byte rdata = 0xFF;
        int daddr = deviceaddress | ((eeaddress & 0x70) >> 7 );
    
        Wire.beginTransmission(daddr);
        Wire.write((int)(eeaddress & 0xFF)); // LSB
    
        Wire.endTransmission();
        Wire.requestFrom(deviceaddress,1);
        if (Wire.available()) rdata = Wire.read();
        return rdata;
    }
    
    void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
        int rdata = data;
        int addr = deviceaddress | ((eeaddress & 0x70) >> 7 );
        Wire.beginTransmission(addr);
        Wire.write((int)(eeaddress & 0xFF)); // LSB
        Wire.write(rdata);
        Wire.endTransmission();
    }
    
    // WARNING: address is a page address, 6-bit end will wrap around
    // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
    void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
        
        Wire.beginTransmission(deviceaddress);
        Wire.write((int)(eeaddresspage & 0xFF)); // LSB
        byte c;
        for ( c = 0; c < length; c++)
            Wire.write(data[c]);
        Wire.endTransmission();
    }
    
    
    // maybe let's not read more than 30 or 32 bytes at a time!
    void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
          int addr = deviceaddress | ((eeaddress & 0x70) >> 7 );
    
        Wire.beginTransmission(addr);
        Wire.write((int)(eeaddress & 0xFF)); // LSB
        Wire.endTransmission();
        Wire.requestFrom(deviceaddress,length);
        int c = 0;
        for ( c = 0; c < length; c++ )
            if (Wire.available()) buffer[c] = Wire.read();
    }

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,299
    Pages in this eeprom are organized as blocks of 16bytes...

  5. #5
    Quote Originally Posted by Theremingenieur View Post
    Pages in this eeprom are organized as blocks of 16bytes...
    I get that, I am just unsure how to read/write to specific pages.

    Would this snipped write to block 1 on page 2 or is there some other bit message I need to send to switch the page i'm addressing.
    Code:
    int rdata = data;
        int addr = deviceaddress | ((eeaddress & 0x70) >> 7 );
        Wire.beginTransmission(addr);
        Wire.write(0x11); // LSB
        Wire.write(rdata);
        Wire.endTransmission();

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •