mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
+ 1.0.05
+ improved waitEEReady() -> on average far lower write latency + added determineSize -> behind #ifdef to keep base lib small + improved comments + corrected return type readBlock() + updated test sketch
This commit is contained in:
parent
afcb60364c
commit
a8fc6d45e9
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: I2C_eeprom.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 1.0.04
|
||||
// VERSION: 1.0.05
|
||||
// PURPOSE: Simple I2C_eeprom library for Arduino with EEPROM 24LC256 et al.
|
||||
//
|
||||
// HISTORY:
|
||||
@ -14,22 +14,19 @@
|
||||
// 1.0.02 - 2013-11-03 optimize internal buffers, refactor
|
||||
// 1.0.03 - 2013-11-03 refactor 5 millis() write-latency
|
||||
// 1.0.04 - 2013-11-03 fix bug in readBlock, moved waitEEReady() -> more efficient.
|
||||
// 1.0.05 - 2013-11-06 improved waitEEReady(), added determineSize()
|
||||
//
|
||||
// Released to the public domain
|
||||
//
|
||||
|
||||
#include <I2C_eeprom.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PUBLIC
|
||||
//
|
||||
|
||||
I2C_eeprom::I2C_eeprom(uint8_t device)
|
||||
{
|
||||
_deviceAddress = device;
|
||||
Wire.begin();
|
||||
TWBR = 12; // 12 = 400Khz 72 = 100 FCPU/16+(2*TWBR)
|
||||
_lastWrite = 0;
|
||||
// TWBR = 12; // 12=400Khz 32=200 72=100 152=50 F_CPU/16+(2*TWBR)
|
||||
}
|
||||
|
||||
int I2C_eeprom::writeByte(uint16_t address, uint8_t data)
|
||||
@ -56,14 +53,14 @@ int I2C_eeprom::writeBlock(uint16_t address, uint8_t* buffer, uint16_t length)
|
||||
uint8_t I2C_eeprom::readByte(uint16_t address)
|
||||
{
|
||||
uint8_t rdata;
|
||||
_ReadBlock(address, &rdata, 1); // todo check return value..
|
||||
_ReadBlock(address, &rdata, 1);
|
||||
return rdata;
|
||||
}
|
||||
|
||||
// maybe let's not read more than 30 or 32 uint8_ts at a time!
|
||||
int I2C_eeprom::readBlock(uint16_t address, uint8_t* buffer, uint16_t length)
|
||||
|
||||
uint16_t I2C_eeprom::readBlock(uint16_t address, uint8_t* buffer, uint16_t length)
|
||||
{
|
||||
int rv = 0;
|
||||
uint16_t rv = 0;
|
||||
while (length > 0)
|
||||
{
|
||||
uint8_t cnt = min(length, I2C_TWIBUFFERSIZE);
|
||||
@ -75,13 +72,54 @@ int I2C_eeprom::readBlock(uint16_t address, uint8_t* buffer, uint16_t length)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef I2C_EEPROM_EXTENDED
|
||||
// returns 64, 32, 16, 8, 4, 2, 1, 0
|
||||
// 0 is smaller than 1K
|
||||
uint8_t I2C_eeprom::determineSize()
|
||||
{
|
||||
uint8_t rv = 0; // unknown
|
||||
uint8_t orgValues[8];
|
||||
uint16_t addr;
|
||||
|
||||
// remember old values, non destructive
|
||||
for (uint8_t i=0; i<8; i++)
|
||||
{
|
||||
addr = (512 << i) + 1;
|
||||
orgValues[i] = readByte(addr);
|
||||
}
|
||||
|
||||
// scan page folding
|
||||
for (uint8_t i=0; i<8; i++)
|
||||
{
|
||||
rv = i;
|
||||
uint16_t addr1 = (512 << i) + 1;
|
||||
uint16_t addr2 = (512 << (i+1)) + 1;
|
||||
writeByte(addr1, 0xAA);
|
||||
writeByte(addr2, 0x55);
|
||||
if (readByte(addr1) == 0x55) // folded!
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// restore original values
|
||||
for (uint8_t i=0; i<8; i++)
|
||||
{
|
||||
uint16_t addr = (512 << i) + 1;
|
||||
writeByte(addr, orgValues[i]);
|
||||
}
|
||||
return 0x01 << (rv-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
|
||||
// _pageBlock aligns buffer to page boundaries for writing.
|
||||
// and TWI buffer size
|
||||
// and to TWI buffer size
|
||||
// returns 0 = OK otherwise error
|
||||
int I2C_eeprom::_pageBlock(uint16_t address, uint8_t* buffer, uint16_t length, bool incrBuffer)
|
||||
{
|
||||
int rv = 0;
|
||||
@ -102,6 +140,7 @@ int I2C_eeprom::_pageBlock(uint16_t address, uint8_t* buffer, uint16_t length, b
|
||||
}
|
||||
|
||||
// pre: length <= I2C_EEPROM_PAGESIZE && length <= I2C_TWIBUFFERSIZE;
|
||||
// returns 0 = OK otherwise error
|
||||
int I2C_eeprom::_WriteBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
{
|
||||
waitEEReady();
|
||||
@ -119,13 +158,14 @@ int I2C_eeprom::_WriteBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
Wire.send(buffer[cnt]);
|
||||
#endif
|
||||
int rv = Wire.endTransmission();
|
||||
|
||||
_lastWrite = micros();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// pre: buffer is large enough to hold length bytes
|
||||
int I2C_eeprom::_ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
// returns bytes written
|
||||
uint8_t I2C_eeprom::_ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
{
|
||||
waitEEReady();
|
||||
|
||||
@ -137,10 +177,11 @@ int I2C_eeprom::_ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
Wire.send((int)(address >> 8));
|
||||
Wire.send((int)(address & 0xFF));
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
int rv = Wire.endTransmission();
|
||||
if (rv != 0) return 0; // error
|
||||
|
||||
Wire.requestFrom(_deviceAddress, length);
|
||||
int cnt = 0;
|
||||
uint8_t cnt = 0;
|
||||
uint32_t before = millis();
|
||||
while ((cnt < length) && ((millis() - before) < I2C_EEPROM_TIMEOUT))
|
||||
{
|
||||
@ -155,18 +196,16 @@ int I2C_eeprom::_ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length)
|
||||
|
||||
void I2C_eeprom::waitEEReady()
|
||||
{
|
||||
#define I2C_WRITEDELAY 5
|
||||
#define I2C_WRITEDELAY 5000
|
||||
|
||||
// Wait until EEPROM gives ACK again.
|
||||
// this is a bit faster than the hardcoded 5 millis
|
||||
int x = 0;
|
||||
uint32_t start = millis();
|
||||
do
|
||||
// this is a bit faster than the hardcoded 5 milli
|
||||
while ((micros() - _lastWrite) <= I2C_WRITEDELAY)
|
||||
{
|
||||
Wire.beginTransmission(_deviceAddress);
|
||||
x = Wire.endTransmission();
|
||||
int x = Wire.endTransmission();
|
||||
if (x == 0) break;
|
||||
}
|
||||
while ( (x != 0) && ((millis() - start) <= I2C_WRITEDELAY));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -4,7 +4,7 @@
|
||||
// FILE: I2C_eeprom.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Simple I2C_eeprom library for Arduino with EEPROM 24LC256 et al.
|
||||
// VERSION: 1.0.04
|
||||
// VERSION: 1.0.05
|
||||
// HISTORY: See I2C_eeprom.cpp
|
||||
// URL: http://arduino.cc/playground/Main/LibraryForI2CEEPROM
|
||||
//
|
||||
@ -21,18 +21,21 @@
|
||||
#include "Wiring.h"
|
||||
#endif
|
||||
|
||||
#define I2C_EEPROM_VERSION "1.0.04"
|
||||
#define I2C_EEPROM_VERSION "1.0.05"
|
||||
|
||||
// I2C_EEPROM_PAGESIZE must be multiple of 2 e.g. 16, 32 or 64
|
||||
// 24LC256 -> 64 bytes
|
||||
#define I2C_EEPROM_PAGESIZE 64
|
||||
|
||||
// TWI buffer needs 2 bytes for address
|
||||
// TWI buffer needs max 2 bytes for address
|
||||
#define I2C_TWIBUFFERSIZE 30
|
||||
|
||||
// to break blocking read/write
|
||||
#define I2C_EEPROM_TIMEOUT 1000
|
||||
|
||||
// comment next line to keep lib small
|
||||
#define I2C_EEPROM_EXTENDED
|
||||
|
||||
class I2C_eeprom
|
||||
{
|
||||
public:
|
||||
@ -43,14 +46,19 @@ public:
|
||||
int setBlock(uint16_t address, uint8_t value, uint16_t length);
|
||||
|
||||
uint8_t readByte(uint16_t address);
|
||||
int readBlock(uint16_t address, uint8_t* buffer, uint16_t length);
|
||||
uint16_t readBlock(uint16_t address, uint8_t* buffer, uint16_t length);
|
||||
|
||||
#ifdef I2C_EEPROM_EXTENDED
|
||||
uint8_t determineSize();
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint8_t _deviceAddress;
|
||||
uint32_t _lastWrite; // for waitEEReady
|
||||
|
||||
int _pageBlock(uint16_t address, uint8_t* buffer, uint16_t length, bool incrBuffer);
|
||||
int _WriteBlock(uint16_t address, uint8_t* buffer, uint8_t length);
|
||||
int _ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length);
|
||||
uint8_t _ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length);
|
||||
|
||||
void waitEEReady();
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: I2C_eeprom_test.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.00
|
||||
// VERSION: 0.1.05
|
||||
// PURPOSE: show/test I2C_EEPROM library
|
||||
//
|
||||
|
||||
@ -63,7 +63,7 @@ void setup()
|
||||
dumpEEPROM(0, 128);
|
||||
|
||||
Serial.println();
|
||||
Serial.print("\n\tI2C speed:\t");
|
||||
Serial.print("\nI2C speed:\t");
|
||||
Serial.println(16000/(16+2*TWBR));
|
||||
Serial.print("TWBR:\t");
|
||||
Serial.println(TWBR);
|
||||
@ -73,24 +73,28 @@ void setup()
|
||||
uint32_t start = micros();
|
||||
ee.writeByte(10, 1);
|
||||
uint32_t diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
Serial.print("TEST: timing writeBlock(50)\t");
|
||||
start = micros();
|
||||
ee.writeBlock(10, (uint8_t *) &data2, 50);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
Serial.print("TEST: timing readByte()\t\t");
|
||||
start = micros();
|
||||
ee.readByte(10);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
Serial.print("TEST: timing readBlock(50)\t");
|
||||
start = micros();
|
||||
ee.readBlock(10, (uint8_t *) &data2, 50);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
// same tests but now with a 5 millisec delay in between.
|
||||
@ -100,6 +104,7 @@ void setup()
|
||||
start = micros();
|
||||
ee.writeByte(10, 1);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
delay(5);
|
||||
@ -108,6 +113,7 @@ void setup()
|
||||
start = micros();
|
||||
ee.writeBlock(10, (uint8_t *) &data2, 50);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
delay(5);
|
||||
@ -116,6 +122,7 @@ void setup()
|
||||
start = micros();
|
||||
ee.readByte(10);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
delay(5);
|
||||
@ -124,10 +131,24 @@ void setup()
|
||||
start = micros();
|
||||
int xx = ee.readBlock(10, (uint8_t *) &data2, 50);
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
|
||||
// does it go well?
|
||||
Serial.println(xx);
|
||||
|
||||
|
||||
Serial.println("\nTEST: determine size");
|
||||
start = micros();
|
||||
int size = ee.determineSize();
|
||||
diff = micros() - start;
|
||||
Serial.print("TIME: ");
|
||||
Serial.println(diff);
|
||||
Serial.print("SIZE: ");
|
||||
Serial.print(size);
|
||||
Serial.println(" KB");
|
||||
|
||||
|
||||
Serial.println("\tDone...");
|
||||
|
||||
}
|
||||
@ -160,6 +181,3 @@ void dumpEEPROM(uint16_t addr, uint16_t length)
|
||||
Serial.println();
|
||||
}
|
||||
// END OF FILE
|
||||
|
||||
|
||||
|
||||
|
24
libraries/I2C_EEPROM/keywords.txt
Normal file
24
libraries/I2C_EEPROM/keywords.txt
Normal file
@ -0,0 +1,24 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For I2C_EEPROM
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
I2C_eeprom KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
readByte KEYWORD2
|
||||
writeByte KEYWORD2
|
||||
setBlock KEYWORD2
|
||||
readBlock KEYWORD2
|
||||
writeBlock KEYWORD2
|
||||
determineSize KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
Loading…
Reference in New Issue
Block a user