Go Down

Topic: I2C communication to external EEPROM via digital pins (Read 8530 times) previous topic - next topic

marthal

There have been occasional questions about the possibility of using digital pins instead of analog pins for I2C communication. Also I myself had the need to save analog pins for other purposes and so I wrote a code which enables any two digital pins to take over I2C communication, in this example with a 24lc256 EEPROM. The sketch shows how to write and to read a number to and from any address of the eeprom.
I'm not a pro so there might be space for improvement. If someone out there wants to transform it into a proper library, please feel free. Now to the sketch. Hope you'll enjoy. Here we go...
Code: [Select]
/*Example code for using two digital pins to establish I2C communication
with a 24LC256 EEPROM
Written by Martin Thalheimer, 2011.
*/

byte data = 4;  //digital pin 4 = data - connect to pin 4 of 24lc256
byte clock = 5;  //digital pin 5 = clock - connect to pin 5 of 24lc256
int address=160;  //address of the 24lc256 with all address pin tied to GND
int i2c_out;
int i;
int number=234;   //put here a number of your choice (0-255) to be stored in the external eeprom
int memory_address=23456; /*put here the address of your choice (0-32767) within the eeprom where
                            you want the number to be stored*/
int adr_hi;
int adr_low;

void setup(){
Serial.begin(9600);
pinMode(clock, OUTPUT);
pinMode(data, OUTPUT);
}

void loop() {
   Serial.println("writing...");
   dig_eeprom_write(); //this function writes the number into the external eeprom
   Serial.println(number);
   Serial.print("to eeprom address ");
   Serial.println(memory_address);
   
   Serial.println("reading...");
   dig_eeprom_read(); //this function reads the number from the external eeprom
   Serial.println(i2c_out);
   Serial.print("from eeprom address ");
   Serial.println(memory_address);
   Serial.println();

   delay(2000);   
   }
     
  void dig_eeprom_write() {
   common_routine();
   i2c_out=number;
   putbyte();   //the number is being sent to the eeprom
   getack();   //get acknowledge
   Stop();
   delay (100); //
   } 
 
  void dig_eeprom_read() {
   common_routine();
   start();
   i2c_out=address+1; //address of 24lc256 in read mode
   putbyte();   //send byte
   getack();   //get acknowledge
   getbyte(); //retrieve content of the memory cell
   givenoack();   //no acknowledge
   Stop();
   delay(10);
   }
   
  void common_routine () {  //this part is common to each writing or reading cycle
    start();    //start signal for eeprom to wake up
    i2c_out=address; //address of 24lc256 in write mode
    putbyte();   //send byte
    getack();   //get acknowledge
    adr_hi=memory_address/256;    //
    adr_low=memory_address % 256; //
    i2c_out=adr_hi; //send the highbyte of the memory-address
    putbyte();   //send byte
    getack();   //get acknowledge
    i2c_out=adr_low; //send the lowbyte of the memory-address
    putbyte();   //send byte
    getack();   //get acknowledge
    }   
           
   void start() {
       digitalWrite (clock, HIGH);
       digitalWrite (data, HIGH);
       digitalWrite (data, LOW);
       digitalWrite (clock, LOW);
       }
   
    void putbyte() {
       for (i=7; i>=0; i--){
       if ((i2c_out &(1<<i))==0) {   
         digitalWrite (data, LOW);
       }
        else {
          digitalWrite (data, HIGH);
       }
       digitalWrite (clock, HIGH);    //pulse clock
       digitalWrite (clock, LOW);
       }
       }
       
void getbyte() {
       pinMode(data, INPUT);
       i2c_out=0;
       for (i=7; i>=0; i--){
       if (digitalRead(data)==HIGH) {   
       i2c_out=(i2c_out + (1<<i));
       delay(10);
       }
       digitalWrite (clock, HIGH);    //pulse clock
       digitalWrite (clock, LOW);
       }     
       pinMode(data, OUTPUT);   
       }
   
  void getack() {
      digitalWrite (data, HIGH);
      pinMode(data, INPUT);
      digitalWrite (clock, HIGH);
      if(digitalRead(data)==LOW) {
      digitalWrite (clock, HIGH); //acknowledge ack
      digitalWrite (clock, LOW);
      }
      pinMode(data, OUTPUT);
      }
     
   void Stop() { 
      digitalWrite (data, LOW);
      digitalWrite (clock, HIGH); 
      digitalWrite (data, HIGH);
      }
   
  void givenoack() {
     digitalWrite (data, HIGH);
     digitalWrite (clock, HIGH);    //pulse clock
     digitalWrite (clock, LOW);
     digitalWrite (data, LOW);
     }
 

JanD

I have also for some time now wondered why there isn't any Software I2C or SPI library. There is a Software library for UART (SoftSerial, NewSoftSerial) so why not for I2C and SPI???

I would really like to make a library, and your code is a good thing to start from, but I think i don't have the time to do that. Perhaps some time the next week.

Jan


robtillaart


Soft I2C => check this blog article  => http://arduino.cc/blog/2010/10/01/softi2cmaster-library-lets-you-add-i2c-to-any-arduino-pin/

As it is work in progress maybe you can add your energy to get this effort on a higher level iso starting a new one?

my 2 cnts,
Rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy