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...
/*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);
}