Wednesday, October 19, 2011

Task 38.1 - using the I2C bus with an EEPROM 24LC64: software edit

/*
 * Project:      eeprom_fromWeb
 * Author:      hkhijhe - tidied even more by Jane-Maree Howard
 * Date:         01/10/2010
 * Platform:   Arduino 22
 * Purpose:    To demonstrate use of the I2C bus with an EEPROM 24LC64
 -             "You were issued with an eeprom 24LC64 IC.
 -              This is a TWI memory that you connect to SCL and SDA on the Arduino.
 -              Run the program from the blog.
 -              Show your code changes and the serial monitor output in your blog".
 * Operation:  Because this chip is I2C,
 -               it only uses Arduino analog pins 4 & 5 (SDA and SCL),
 -               and of course the power (5V) and GND.
 -             Connect as follows:
 -                Arduino pin 4 to EEPROM pin 5
 -                Arduino pin 5 to EEPROM pin 6
 -                Arduino 5V to EEPROM pin 8
 -                Arduino GND to EEPROM pin 1,2,3,4
 -             Be sure to leave pin 7 of the EEPROM open or tie it to GND,
 -               otherwise the EEPROM will be write protected.
 -             Include: Wire.h - the I2C library
 -             Declare: various i2c_eeprom_read.. i2c_eeprom_write.. procedures
 -             Setup(): Opens the Wire connection, the Serial connection,
 -                      writes a char-string to the EEPROM, & prints heading
 -                      NOTE: the char-string has length = 28
 -             Loop():  Reads from the EEPROM, & prints, one byte at a time, & repeats                
 */

#include {Wire.h}               //I2C library-usual brackets warning

  void setup()
  {
    // a char-string of data to write to the EEPROM - 28 characters long!!
    char someData[] = "this is data from the eeprom";
   /*
    char somedata[] = "this is Jane-Maree's eeprom data"; - 32 characters..
     .. & it bombs.  Gibberish - I've tried it!  See WARNING below..
   */
    Wire.begin();                 // Wire connection initialised
    Serial.begin(9600);       // Serial connection @ 9600 baud
    // now write the char-string to the EEPROM
    i2c_eeprom_write_page(0x50, 0, (byte *)someData, sizeof(someData));
    delay(10);                     //add a small delay..
    // ..& print a heading
    Serial.println("\nMemory written");
    Serial.println("\nNow read memory & print to Serial port");
  } //setup()

  void loop()
  {
    int addr=0;               // address parameter, starts @ 0
    // now access the first address (0) from the memory
    byte b = i2c_eeprom_read_byte(0x50, 0);
    // while there are non-zero bytes..
    while (b!=0)
    {
      Serial.print((char)b); //..print content as char to serial port..
      addr++;                      //..next address &..
      //..access next address from the memory.
      b = i2c_eeprom_read_byte(0x50, addr);
    }//while ()
    Serial.println(" ");     // new line..
    delay(2000);               // ..2 second delay, & start again!
  } //loop()


   /*
    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.send((int)(eeAddressPage >> 8));       // MSB
    Wire.send((int)(eeAddressPage & 0xFF));  // LSB
    byte c;
    for ( c = 0; c < length; c++)
      Wire.send(data[c]);
    Wire.endTransmission();
  } //i2c_eeprom_write_page()


  byte i2c_eeprom_read_byte( int deviceAddress, unsigned int eeAddress )
  {
    byte rdata = 0xFF;
  
    //ask device by address for data
    Wire.beginTransmission(deviceAddress);
    Wire.send((int)(eeAddress >> 8));             // MSB
    Wire.send((int)(eeAddress & 0xFF));           // LSB
    Wire.endTransmission();
  
    Wire.requestFrom(deviceAddress,1);
    if (Wire.available())
      rdata = Wire.receive();
    return rdata;
  } //i2c_eeprom_read_byte()

// END

3 comments:

  1. i noticed that two of the functions originally listed were not used..
    ..so i cut them, recompiled, & it was quite ok!

    code's now quite a bit shorter - & now i know exactly how it works!

    ReplyDelete
  2. i also used camel-case to make long variable names more readable..
    ..it's a simple thing: why not do it?

    ReplyDelete
  3. & since i now know how it works, i know what part of the original code to use to avoid i2c buffer over-runs: a function that has its own, reusable, buffer that chops long char-strings into i2c-buffer-sized chunks..

    ..way to go!

    ReplyDelete