mirror of
https://github.com/RobTillaart/I2C_EEPROM.git
synced 2026-07-28 04:16:22 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86a5017fa9 | ||
|
|
86228c599f | ||
|
|
e57418ba44 | ||
|
|
bb84b19faf | ||
|
|
43f4886a91 | ||
|
|
8cb180d081 |
@@ -6,8 +6,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: arduino/arduino-lint-action@v1
|
||||
- uses: actions/checkout@v5
|
||||
- uses: arduino/arduino-lint-action@v2
|
||||
with:
|
||||
library-manager: update
|
||||
compliance: strict
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
|
||||
@@ -5,13 +5,15 @@ on:
|
||||
paths:
|
||||
- '**.json'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.json'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: json-syntax-check
|
||||
uses: limitusus/json-syntax-check@v2
|
||||
with:
|
||||
|
||||
+22
-1
@@ -6,10 +6,31 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [1.9.4] - 2025-08-27
|
||||
- fix #83, update readme.md (thanks to TonyRiddiough)
|
||||
- add calculatePageSize(deviceSize) to replace getPageSize(deviceSize) prep.
|
||||
- update GitHub actions
|
||||
- minor update examples
|
||||
- minor edits
|
||||
|
||||
## [1.9.3] - 2025-08-01
|
||||
- update readme.md
|
||||
|
||||
## [1.9.2] - 2024-11-25
|
||||
- fix #79, wrong default in constructor - kudos to ekinohito
|
||||
|
||||
## [1.9.1] - 2024-10-26
|
||||
- fix #77, updateBlock() returns bytes actually written.
|
||||
- minor edits
|
||||
|
||||
## [1.9.0] - 2024-10-09
|
||||
- Fix #74, memory leak in setBlockVerify() - kudos to cmichailidis
|
||||
|
||||
----
|
||||
|
||||
## [1.8.5] - 2024-04-22
|
||||
- Fix #72, force requestFrom parameters to use int type
|
||||
|
||||
|
||||
## [1.8.4] - 2024-04-20
|
||||
- Fix #70, increase length internal buffer.
|
||||
- add compile time flag **EN_AUTO_WRITE_PROTECT** (thanks to microfoundry)
|
||||
|
||||
+34
-21
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: I2C_eeprom.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 1.8.5
|
||||
// VERSION: 1.9.3
|
||||
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
|
||||
// URL: https://github.com/RobTillaart/I2C_EEPROM
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, TwoWire * wire) :
|
||||
I2C_eeprom(deviceAddress, I2C_PAGESIZE_24LC256, wire)
|
||||
I2C_eeprom(deviceAddress, I2C_DEVICESIZE_24LC256, wire)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, T
|
||||
{
|
||||
_deviceAddress = deviceAddress;
|
||||
_deviceSize = setDeviceSize(deviceSize);
|
||||
_pageSize = getPageSize(_deviceSize);
|
||||
_pageSize = calculatePageSize(_deviceSize);
|
||||
_wire = wire;
|
||||
|
||||
// Chips 16 Kbit (2048 Bytes) or smaller only have one-word addresses.
|
||||
@@ -182,7 +182,7 @@ int I2C_eeprom::updateByte(const uint16_t memoryAddress, const uint8_t data)
|
||||
}
|
||||
|
||||
|
||||
// returns bytes written.
|
||||
// returns bytes actually written <= length
|
||||
uint16_t I2C_eeprom::updateBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length)
|
||||
{
|
||||
uint16_t address = memoryAddress;
|
||||
@@ -194,10 +194,11 @@ uint16_t I2C_eeprom::updateBlock(const uint16_t memoryAddress, const uint8_t * b
|
||||
uint8_t count = I2C_BUFFERSIZE;
|
||||
|
||||
if (count > len) count = len;
|
||||
bytes += _ReadBlock(address, buf, count);
|
||||
_ReadBlock(address, buf, count);
|
||||
if (memcmp(buffer, buf, count) != 0)
|
||||
{
|
||||
_pageBlock(address, buffer, count, true);
|
||||
bytes += count;
|
||||
}
|
||||
address += count;
|
||||
buffer += count;
|
||||
@@ -235,7 +236,11 @@ bool I2C_eeprom::setBlockVerify(const uint16_t memoryAddress, const uint8_t valu
|
||||
if (setBlock(memoryAddress, value, length) != 0) return false;
|
||||
uint8_t * data = (uint8_t *) malloc(length);
|
||||
if (data == NULL) return false;
|
||||
if (readBlock(memoryAddress, data, length) != length) return false;
|
||||
if (readBlock(memoryAddress, data, length) != length)
|
||||
{
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
if (data[i] != value)
|
||||
@@ -261,7 +266,8 @@ bool I2C_eeprom::updateByteVerify(const uint16_t memoryAddress, const uint8_t va
|
||||
// return false if write or verify failed.
|
||||
bool I2C_eeprom::updateBlockVerify(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length)
|
||||
{
|
||||
if (updateBlock(memoryAddress, buffer, length) != length) return false;
|
||||
// zero bytes written means nothing needs to be verified
|
||||
if (0 == updateBlock(memoryAddress, buffer, length)) return true;
|
||||
return verifyBlock(memoryAddress, buffer, length);
|
||||
}
|
||||
|
||||
@@ -290,7 +296,7 @@ bool I2C_eeprom::updateBlockVerify(const uint16_t memoryAddress, const uint8_t *
|
||||
// 24LC01 128 B YES
|
||||
uint32_t I2C_eeprom::determineSize(const bool debug)
|
||||
{
|
||||
// try to read a byte to see if connected
|
||||
// try to read a byte to see if connected
|
||||
if (! isConnected()) return 0;
|
||||
|
||||
uint8_t patAA = 0xAA;
|
||||
@@ -302,7 +308,7 @@ uint32_t I2C_eeprom::determineSize(const bool debug)
|
||||
|
||||
// store old values
|
||||
bool addressSize = _isAddressSizeTwoWords;
|
||||
_isAddressSizeTwoWords = size > I2C_DEVICESIZE_24LC16; // 2048
|
||||
_isAddressSizeTwoWords = size > I2C_DEVICESIZE_24LC16; // 2048
|
||||
uint8_t buf = readByte(size);
|
||||
|
||||
// test folding
|
||||
@@ -332,7 +338,7 @@ uint32_t I2C_eeprom::determineSize(const bool debug)
|
||||
// new 1.8.1 #61
|
||||
// updated 1.8.2 #63
|
||||
//
|
||||
// Returns:
|
||||
// Returns:
|
||||
// 0 if device size cannot be determined or device is not online
|
||||
// 1 if device has default bytes in first dataFirstBytes bytes [0-BUFSIZE]
|
||||
// Write some dataFirstBytes to the first bytes and retry or use the determineSize method
|
||||
@@ -396,14 +402,14 @@ uint32_t I2C_eeprom::determineSizeNoWrite()
|
||||
_isAddressSizeTwoWords = (size >= I2C_DEVICESIZE_24LC16); // == 2048
|
||||
|
||||
// Try to read last byte of the block, should return length of 0 when fails for single byte devices
|
||||
// Will return the same dataFirstBytes as initially read on other devices
|
||||
// Will return the same dataFirstBytes as initially read on other devices
|
||||
// as the data pointer could not be moved to the requested position
|
||||
delay(2);
|
||||
uint16_t bSize = readBlock(size, dataMatch, BUFSIZE);
|
||||
|
||||
if (bSize == BUFSIZE && memcmp(dataFirstBytes, dataMatch, BUFSIZE) != 0)
|
||||
{
|
||||
// Read is performed just over size (size + BUFSIZE),
|
||||
// Read is performed just over size (size + BUFSIZE),
|
||||
// this will only work for devices with mem > size;
|
||||
// therefore return size * 2
|
||||
_isAddressSizeTwoWords = addressSize;
|
||||
@@ -427,7 +433,7 @@ uint8_t I2C_eeprom::getPageSize()
|
||||
}
|
||||
|
||||
|
||||
uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
|
||||
uint8_t I2C_eeprom::calculatePageSize(uint32_t deviceSize)
|
||||
{
|
||||
// determine page size from device size
|
||||
// based on Microchip 24LCXX data sheets.
|
||||
@@ -435,8 +441,15 @@ uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
|
||||
if (deviceSize <= I2C_DEVICESIZE_24LC16) return 16;
|
||||
if (deviceSize <= I2C_DEVICESIZE_24LC64) return 32;
|
||||
if (deviceSize <= I2C_DEVICESIZE_24LC256) return 64;
|
||||
// I2C_DEVICESIZE_24LC512
|
||||
return 128;
|
||||
if (deviceSize <= I2C_DEVICESIZE_24LC512) return 128;
|
||||
// Error.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
|
||||
{
|
||||
return calculatePageSize(deviceSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +476,7 @@ uint32_t I2C_eeprom::setDeviceSize(uint32_t deviceSize)
|
||||
|
||||
uint8_t I2C_eeprom::setPageSize(uint8_t pageSize)
|
||||
{
|
||||
// force power of 2.
|
||||
// force power of 2.
|
||||
if (pageSize >= 128) {
|
||||
_pageSize = 128;
|
||||
}
|
||||
@@ -610,7 +623,7 @@ int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer
|
||||
|
||||
_lastWrite = micros();
|
||||
|
||||
yield(); // For OS scheduling
|
||||
yield(); // For OS scheduling
|
||||
|
||||
// if (rv != 0)
|
||||
// {
|
||||
@@ -621,7 +634,7 @@ int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer
|
||||
// SPRN("\t");
|
||||
// SPRNL(rv);
|
||||
// }
|
||||
// return -(abs(rv)); // error
|
||||
// return -(abs(rv)); // error
|
||||
// }
|
||||
return rv;
|
||||
}
|
||||
@@ -722,9 +735,9 @@ void I2C_eeprom::_waitEEReady()
|
||||
{
|
||||
if (isConnected()) return;
|
||||
// TODO remove pre 1.7.4 code
|
||||
// _wire->beginTransmission(_deviceAddress);
|
||||
// int x = _wire->endTransmission();
|
||||
// if (x == 0) return;
|
||||
// _wire->beginTransmission(_deviceAddress);
|
||||
// int x = _wire->endTransmission();
|
||||
// if (x == 0) return;
|
||||
yield(); // For OS scheduling
|
||||
}
|
||||
return;
|
||||
|
||||
+9
-7
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: I2C_eeprom.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 1.8.5
|
||||
// VERSION: 1.9.4
|
||||
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
|
||||
// URL: https://github.com/RobTillaart/I2C_EEPROM
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define I2C_EEPROM_VERSION (F("1.8.5"))
|
||||
#define I2C_EEPROM_VERSION (F("1.9.4"))
|
||||
|
||||
#define I2C_DEVICESIZE_24LC512 65536
|
||||
#define I2C_DEVICESIZE_24LC256 32768
|
||||
@@ -74,17 +74,17 @@ public:
|
||||
* It will try to guess page size and address word size based on the size of the device.
|
||||
*
|
||||
* @param deviceAddress Byte address of the device.
|
||||
* @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8)
|
||||
* @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8 to get Kbytes)
|
||||
* @param wire Select alternative Wire interface
|
||||
*/
|
||||
I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, TwoWire *wire = &Wire);
|
||||
|
||||
// use default I2C pins.
|
||||
bool begin(int8_t writeProtectPin = -1);
|
||||
bool isConnected();
|
||||
uint8_t getAddress();
|
||||
|
||||
|
||||
// user is responsible that address is in range of the EEPROM used.
|
||||
// writes a byte to memoryAddress
|
||||
// returns I2C status, 0 = OK
|
||||
int writeByte(const uint16_t memoryAddress, const uint8_t value);
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
// updates a block in memory, writes only if there is a new value.
|
||||
// only to be used when you expect to write same buffer multiple times.
|
||||
// test your performance gains!
|
||||
// returns bytes written.
|
||||
// returns bytes actually written <= length
|
||||
uint16_t updateBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length);
|
||||
|
||||
|
||||
@@ -123,11 +123,13 @@ public:
|
||||
|
||||
|
||||
// Meta data functions
|
||||
uint32_t determineSize(const bool debug = false);
|
||||
uint32_t determineSizeNoWrite();
|
||||
uint32_t getDeviceSize();
|
||||
uint8_t getPageSize();
|
||||
uint8_t calculatePageSize(uint32_t deviceSize);
|
||||
[[deprecated("Use calculatePageSize(deviceSize) instead.")]]
|
||||
uint8_t getPageSize(uint32_t deviceSize);
|
||||
uint32_t determineSizeNoWrite();
|
||||
uint32_t determineSize(const bool debug = false);
|
||||
uint32_t getLastWrite();
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// VERSION: 1.0.0
|
||||
// PURPOSE: Supplemental utility class for I2C_EEPROM library
|
||||
//
|
||||
// URL: https://github.com/RobTillaart/I2C_EEPROM
|
||||
|
||||
|
||||
#include <I2C_eeprom.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2011-2024 Rob Tillaart
|
||||
Copyright (c) 2011-2025 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -17,53 +17,90 @@ Arduino Library for external I2C EEPROM - 24LC512, 24LC256, 24LC64/32/16/08/04/0
|
||||
|
||||
## Description
|
||||
|
||||
This library is to access external I2C EEPROM up to 64KB (= 512 Kbit) in size.
|
||||
MicroChip 24LC512, 24LC256, 24LC64, 24LC32, 24LC16, 24LC08, 24LC04, 24LC02, 24LC01 and equivalents.
|
||||
This library is used to access an external I2C EEPROM up to 64KB (= 512 Kbit) in size.
|
||||
The MicroChip 24LC512, 24LC256, 24LC64, 24LC32, 24LC16, 24LC08, 24LC04, 24LC02, 24LC01
|
||||
and equivalents are tested and working.
|
||||
|
||||
Also confirmed working M24512-W, M24512-R, M24512-DF (See #68).
|
||||
Not supported is the identification page functions.
|
||||
Not supported are the identification page functions.
|
||||
|
||||
The **I2C_eeprom_cyclic_store** interface is documented [here](README_cyclic_store.md)
|
||||
|
||||
**Warning**
|
||||
|
||||
#### RP2040
|
||||
The user is responsible to verify the used memoryAddress (range) exists in the used EEPROM. (read / write / verify functions).
|
||||
The library does not check this. If the address is larger than the EEPROM size,
|
||||
the address used will probably be memoryAddress % deviceSize.
|
||||
|
||||
There are at least two boards modules for the RP2040 that use a different Wire libraries.
|
||||
|
||||
### RP2040
|
||||
|
||||
There are at least two boards modules for the RP2040 that use different Wire libraries.
|
||||
One from "Earle F. Philhower" and an "MBED" one. See issues #53 and #55 for details.
|
||||
|
||||
In 1.7.3 defines are checked to select between these two and as far as tested this seems
|
||||
to solve the issue #53 while being backwards compatible.
|
||||
If a better solution is found, it will be implemented.
|
||||
|
||||
|
||||
#### Breaking change
|
||||
### Breaking change 1.9.0
|
||||
|
||||
Version 1.9.0 fixed a memory leak in **verifyBlock()**.
|
||||
|
||||
### Breaking change 1.8.0
|
||||
|
||||
Version 1.8.0 introduced a breaking change.
|
||||
You cannot set the pins in **begin()** any more.
|
||||
This reduces the dependency of processor dependent Wire implementations.
|
||||
You cannot set the I2C pins in **begin()** any more.
|
||||
This reduces the dependency of processor dependent Wire (I2C) implementations.
|
||||
The user has to call **Wire.begin()** and can optionally set the Wire pins
|
||||
before calling **I2C_eeprom.begin()**.
|
||||
(if the board supports this), before calling **I2C_eeprom.begin()**.
|
||||
|
||||
|
||||
#### Links
|
||||
### Related
|
||||
|
||||
- https://github.com/RobTillaart/I2C_24LC1025
|
||||
- https://github.com/RobTillaart/I2C_CAT24M01
|
||||
- https://github.com/RobTillaart/I2C_EEPROM
|
||||
|
||||
|
||||
## Schematic
|
||||
|
||||
```cpp
|
||||
+---U---+
|
||||
A0 | 1 8 | VCC = 1.7V to 5.5V
|
||||
A1 | 2 7 | WP = write protect pin
|
||||
A2 | 3 6 | SCL = I2C clock
|
||||
GND | 4 5 | SDA = I2C data
|
||||
+-------+
|
||||
Verify the datasheet for your specific EEPROM.
|
||||
|
||||
Default address = 0x50 .. 0x57 depending on three address lines (A0, A1, A2).
|
||||
```cpp
|
||||
+---U---+
|
||||
A0 | 1 8 | VCC = 1.7V to 5.5V
|
||||
A1 | 2 7 | WP = write protect pin
|
||||
A2 | 3 6 | SCL = I2C clock
|
||||
(VSS) GND | 4 5 | SDA = I2C data
|
||||
+-------+
|
||||
```
|
||||
|
||||
|
||||
## I2C
|
||||
|
||||
I2C address = 0x50 .. 0x57 depending on three address lines (A0, A1, A2).
|
||||
|
||||
Read the datasheet of your specific EEPROM, section device addressing.
|
||||
|
||||
|
||||
### I2C multiplexing
|
||||
|
||||
Sometimes you need to control more devices than possible with the default
|
||||
address range the device provides.
|
||||
This is possible with an I2C multiplexer e.g. TCA9548 which creates up
|
||||
to eight channels (think of it as I2C subnets) which can use the complete
|
||||
address range of the device.
|
||||
|
||||
Drawback of using a multiplexer is that it takes more administration in
|
||||
your code e.g. which device is on which channel.
|
||||
This will slow down the access, which must be taken into account when
|
||||
deciding which devices are on which channel.
|
||||
Also note that switching between channels will slow down other devices
|
||||
too if they are behind the multiplexer.
|
||||
|
||||
- https://github.com/RobTillaart/TCA9548
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
@@ -73,22 +110,46 @@ Default address = 0x50 .. 0x57 depending on three address lines (A0, A1, A2).
|
||||
The interface is kept quite identical to the I2C_24LC1025 library.
|
||||
https://github.com/RobTillaart/I2C_24LC1025
|
||||
|
||||
Most important difference is 32 bit memory addresses.
|
||||
Most important difference is that the latter uses 32 bit memory addresses.
|
||||
|
||||
|
||||
### Constructor
|
||||
|
||||
- **I2C_eeprom(uint8_t deviceAddress, TwoWire \*wire = &Wire)** constructor,
|
||||
optional Wire interface.
|
||||
- **I2C_eeprom(uint8_t deviceAddress, TwoWire \*wire = &Wire)** constructor, to set the
|
||||
device address and optional Wire interface. The deviceSize == I2C_DEVICESIZE_24LC256 (32KB)
|
||||
is used as it is the most often used I2C_EEPROM size.
|
||||
Be aware that if you use other sized EEPROMs you have to use the next constructor,
|
||||
and name the deviceSize explicitly, otherwise errors might occur.
|
||||
- **I2C_eeprom(uint8_t deviceAddress, uint32_t deviceSize, TwoWire \*wire = &Wire)**
|
||||
constructor, with optional Wire interface.
|
||||
- **bool begin(uint8_t writeProtectPin = -1)** initializes the I2C bus with the default pins.
|
||||
Furthermore it checks if the deviceAddress is available on the I2C bus.
|
||||
Returns true if deviceAddress is found on the bus, false otherwise.
|
||||
Optionally one can set the **WP** writeProtect pin. (see section below).
|
||||
If the **WP** pin is defined the default will be to **not** allow writing.
|
||||
- **bool isConnected()** test to see if deviceAddress is found on the bus.
|
||||
- **uint8_t getAddress()** returns device address set in the constructor.
|
||||
constructor, idem as above, furthermore the deviceSize can be any of the defines in the
|
||||
table below or its number equivalent.
|
||||
The Wire interface is optional, default Wire.
|
||||
- **bool begin(uint8_t writeProtectPin = -1)** Optionally one can set the **WP**
|
||||
writeProtect pin. (see section below).
|
||||
If the **WP** pin is defined, the default behaviour will be to **not** allow writing.
|
||||
Furthermore it checks if the deviceAddress given in the constructor is available
|
||||
on the defined I2C bus.
|
||||
Returns true if deviceAddress is found on the I2C bus, false otherwise.
|
||||
- **bool isConnected()** returns true if the address given in the constructor is
|
||||
available on the defined I2C bus.
|
||||
- **uint8_t getAddress()** returns deviceAddress set in the constructor.
|
||||
Convenience.
|
||||
|
||||
|
||||
Defined device sizes for constructor, more details see below.
|
||||
|
||||
| Define | bytes | Notes |
|
||||
|:-------------------------|--------:|:--------|
|
||||
| I2C_DEVICESIZE_24LC512 | 65536 |
|
||||
| I2C_DEVICESIZE_24LC256 | 32768 | most used
|
||||
| I2C_DEVICESIZE_24LC128 | 16384 |
|
||||
| I2C_DEVICESIZE_24LC64 | 8192 |
|
||||
| I2C_DEVICESIZE_24LC32 | 4096 |
|
||||
| I2C_DEVICESIZE_24LC16 | 2048 |
|
||||
| I2C_DEVICESIZE_24LC08 | 1024 |
|
||||
| I2C_DEVICESIZE_24LC04 | 512 |
|
||||
| I2C_DEVICESIZE_24LC02 | 256 |
|
||||
| I2C_DEVICESIZE_24LC01 | 128 |
|
||||
|
||||
|
||||
### Write functions
|
||||
@@ -106,12 +167,15 @@ Returns I2C status, 0 = OK.
|
||||
|
||||
### Update functions
|
||||
|
||||
Using update instead of write functions does not write if the value is the same.
|
||||
The price is an extra read() call, but if there is no change the gain is performance.
|
||||
|
||||
- **int updateByte(uint16_t memoryAddress, uint8_t value)** write a single byte,
|
||||
but only if changed.
|
||||
but only if the value has changed.
|
||||
Returns 0 if value was same or write succeeded.
|
||||
- **uint16_t updateBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
|
||||
write a buffer starting at the specified memory address, but only if changed.
|
||||
Returns bytes written.
|
||||
Returns bytes actually written <= length.
|
||||
|
||||
|
||||
### Read functions
|
||||
@@ -120,6 +184,7 @@ Returns bytes written.
|
||||
- **uint16_t readBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
|
||||
read length bytes into buffer starting at specified memory address.
|
||||
Returns the number of bytes read, which should be length.
|
||||
The user is responsible that the used buffer can hold length bytes.
|
||||
|
||||
|
||||
### Verify functions
|
||||
@@ -127,6 +192,7 @@ Returns the number of bytes read, which should be length.
|
||||
Since 1.6.0. - experimental, needs extensive testing.
|
||||
|
||||
Same as write and update functions above. Returns true if successful, false indicates an error.
|
||||
The user is responsible that the used buffer can hold length bytes.
|
||||
|
||||
- **bool writeByteVerify(uint16_t memoryAddress, uint8_t value)**
|
||||
- **bool writeBlockVerify(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
|
||||
@@ -134,24 +200,24 @@ Same as write and update functions above. Returns true if successful, false indi
|
||||
- **bool updateByteVerify(uint16_t memoryAddress, uint8_t value)**
|
||||
- **bool updateBlockVerify(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
|
||||
- **bool verifyBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
|
||||
Returns true is buffer equals memoryAddres for length bytes.
|
||||
|
||||
Returns true is buffer equals memoryAddress for length bytes.
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
- **uint32_t getDeviceSize()** idem
|
||||
- **uint8_t getPageSize()** idem
|
||||
- **uint8_t getPageSize(uint32_t deviceSize)** idem
|
||||
- **uint32_t getLastWrite()** idem
|
||||
- **uint32_t getDeviceSize()** returns the current set deviceSize.
|
||||
- **uint8_t getPageSize()** returns the current set pageSize.
|
||||
- **uint8_t calculatePageSize(uint32_t deviceSize)** calculates the pageSize of a device
|
||||
with deviceSize. Note it does not set the pageSize!
|
||||
- **uint8_t getPageSize(uint32_t deviceSize)** deprecated, wrapper around calculatePageSize().
|
||||
- **uint32_t getLastWrite()** returns timestamp in millis since start of program.
|
||||
- **uint32_t determineSizeNoWrite()** function that determines the size of the EEPROM
|
||||
by detecting when a selected memory address is not readable. (new in 1.8.1).
|
||||
- **uint32_t determineSize(bool debug = false)**
|
||||
function that determines the size of the EEPROM by detecting when a memory address
|
||||
is folded upon memory address 0.
|
||||
It is based upon the observation that memory wraps around.
|
||||
The debug flag prints some output to Serial.
|
||||
|
||||
The debug flag prints some output to Serial.
|
||||
**Warning**: this function has changed (again) in 1.4.0
|
||||
|
||||
Test results **determineSize()**
|
||||
@@ -189,7 +255,7 @@ The function **updateBlock()** reads the block of data and compares it with the
|
||||
|
||||
As the function reads/writes the data in blocks with a maximum length of **I2C_TWIBUFFERSIZE**
|
||||
(== 30 AVR limitation; 128 for ESP32)
|
||||
It does this comparison in chunks if the length exceeds this number.
|
||||
It does this comparison in chunks if the length exceeds the length of the I2C buffer.
|
||||
The result is that an **updateBlock()** call can result e.g. in 4 reads and only 2 writes under the hood.
|
||||
|
||||
If data is changed often between writes, **updateBlock()** is slower than **writeBlock()**.
|
||||
@@ -242,13 +308,9 @@ Manual control
|
||||
|
||||
## Limitation
|
||||
|
||||
The library does not offer multiple EEPROMS as one continuous storage device.
|
||||
The library does not offer multiple EEPROMS as one continuous storage device.
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
||||
## Future
|
||||
|
||||
#### Must
|
||||
@@ -257,11 +319,12 @@ See examples
|
||||
|
||||
#### Should
|
||||
|
||||
- investigate multi-EEPROM storage
|
||||
- wrapper class?
|
||||
- improve error handling,
|
||||
- write functions should return bytes written or so.
|
||||
- make deviceSize explicit in examples?
|
||||
- investigate multi-EEPROM storage ==> wrapper class!
|
||||
- improve error handling
|
||||
- address range check in begin
|
||||
- write functions should return bytes written (like Print() does)
|
||||
now they return I2C status... => error / status.
|
||||
- remove uint8_t getPageSize(uint32_t deviceSize) in 0.2.0. now deprecated.
|
||||
|
||||
#### Could
|
||||
|
||||
@@ -269,7 +332,8 @@ See examples
|
||||
=> find first and last changed position could possibly result in less writes.
|
||||
- can **setBlock()** use strategies from **updateBlock()**
|
||||
- **pageBlock()**: incrBuffer is an implementation name, not a functional name.
|
||||
|
||||
- replace defines with const uint8_t / const uint16_t to force type checking?
|
||||
- sync order .h file and readme.md.
|
||||
|
||||
#### Wont
|
||||
|
||||
|
||||
@@ -30,7 +30,12 @@ I2C_eeprom_cyclic_store<SampleData> cs;
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -45,9 +50,9 @@ void setup()
|
||||
sprintf(data.message, "Initialized to %x", data.counter);
|
||||
cs.write(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.println(data.message);
|
||||
|
||||
@@ -18,9 +18,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -58,7 +60,7 @@ void setup()
|
||||
}
|
||||
|
||||
Serial.print("PAGE: ");
|
||||
uint8_t pageSize = ee.getPageSize(size);
|
||||
uint8_t pageSize = ee.calculatePageSize(size);
|
||||
Serial.print(pageSize);
|
||||
Serial.println(" bytes.");
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -66,7 +68,7 @@ void setup()
|
||||
}
|
||||
|
||||
Serial.print("PAGE: ");
|
||||
uint8_t pageSize = ee.getPageSize(size);
|
||||
uint8_t pageSize = ee.calculatePageSize(size);
|
||||
Serial.print(pageSize);
|
||||
Serial.println(" bytes.");
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
//
|
||||
// uses a 24LC256 (32KB) EEPROM
|
||||
// as this test writes a lot it might wear out EEPROMs eventually.
|
||||
//
|
||||
|
||||
|
||||
#include "Wire.h"
|
||||
@@ -29,9 +28,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -39,7 +40,7 @@ void setup()
|
||||
if (! ee.isConnected())
|
||||
{
|
||||
Serial.println("ERROR: Can't find eeprom (stopped)...");
|
||||
// while (1);
|
||||
// while (1);
|
||||
}
|
||||
|
||||
Serial.print("size: \t");
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
// #define SERIAL_OUT SerialUSB
|
||||
|
||||
|
||||
I2C_eeprom ee(0x50);
|
||||
// I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
|
||||
I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
|
||||
|
||||
uint32_t start, diff, totals = 0;
|
||||
|
||||
@@ -28,9 +27,11 @@ void setup()
|
||||
{
|
||||
SERIAL_OUT.begin(115200);
|
||||
while (!SERIAL_OUT); // wait for SERIAL_OUT port to connect. Needed for Leonardo only
|
||||
SERIAL_OUT.println();
|
||||
SERIAL_OUT.println(__FILE__);
|
||||
SERIAL_OUT.print("I2C_EEPROM_VERSION: ");
|
||||
SERIAL_OUT.println(I2C_EEPROM_VERSION);
|
||||
SERIAL_OUT.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -68,7 +69,7 @@ void setup()
|
||||
ee.setBlock(0, 0, 128);
|
||||
dumpEEPROM(0, 128);
|
||||
Serial.println("---");
|
||||
// char data[] = "11111111111111111111";
|
||||
// char data[] = "11111111111111111111";
|
||||
char data[] = "33333333333333333333";
|
||||
ee.writeBlock(60, (uint8_t*) data, 10);
|
||||
dumpEEPROM(0, 128);
|
||||
@@ -155,7 +156,7 @@ void setup()
|
||||
SERIAL_OUT.println(totals);
|
||||
totals = 0;
|
||||
|
||||
// same tests but now with a 5 millisec delay in between.
|
||||
// same tests but now with a 5 millisec delay in between.
|
||||
delay(5);
|
||||
|
||||
SERIAL_OUT.print("\nTEST: timing writeByte()\t");
|
||||
@@ -200,7 +201,7 @@ void setup()
|
||||
SERIAL_OUT.println(totals);
|
||||
totals = 0;
|
||||
|
||||
// does it go well?
|
||||
// did it go well?
|
||||
SERIAL_OUT.println(xx);
|
||||
|
||||
SERIAL_OUT.println("\tDone...");
|
||||
@@ -224,7 +225,7 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||
}
|
||||
SERIAL_OUT.println();
|
||||
|
||||
// block to defined length
|
||||
// block to defined length
|
||||
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -140,7 +142,7 @@ void test()
|
||||
Serial.println(totals);
|
||||
totals = 0;
|
||||
|
||||
// does it go well?
|
||||
// did it go well?
|
||||
Serial.println(xx);
|
||||
}
|
||||
|
||||
@@ -157,7 +159,7 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// block to defined length
|
||||
// block to defined length
|
||||
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
|
||||
@@ -23,9 +23,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
|
||||
@@ -21,9 +21,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@ void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("I2C_EEPROM_VERSION: ");
|
||||
Serial.println(I2C_EEPROM_VERSION);
|
||||
Serial.println();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
@@ -96,5 +98,4 @@ void disrupt(uint8_t location)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//
|
||||
// FILE: I2C_small_eeprom_test.ino
|
||||
// AUTHOR: Tyler Freeman
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.1.2
|
||||
// PURPOSE: show/test I2C_EEPROM library with small EEPROMS
|
||||
// URL: https://github.com/RobTillaart/I2C_EEPROM
|
||||
// HISTORY
|
||||
// 0.1.0 2014-05-xx initial version
|
||||
// 0.1.1 2020-07-14 fix #1 compile for ESP; fix author
|
||||
// 0.1.2 2025-08-27 add print filename and version number of library
|
||||
|
||||
|
||||
#include <Wire.h>
|
||||
@@ -101,7 +102,12 @@ void readAndWritePage(unsigned int pageAddress, int bufferLen) {
|
||||
void setup()
|
||||
{
|
||||
SERIAL_DEBUG.begin(57600);
|
||||
while (!SERIAL_DEBUG); // wait for SERIAL_DEBUG port to connect. Needed for Leonardo only
|
||||
while (!SERIAL_DEBUG); // wait for SERIAL_DEBUG port to connect. Needed for Leonardo only
|
||||
SERIAL_DEBUG.println();
|
||||
SERIAL_DEBUG.println(__FILE__);
|
||||
SERIAL_DEBUG.print("I2C_EEPROM_VERSION: ");
|
||||
SERIAL_DEBUG.println(I2C_EEPROM_VERSION);
|
||||
SERIAL_DEBUG.println();
|
||||
|
||||
SERIAL_DEBUG.println("IT IS BEGINNING");
|
||||
SERIAL_DEBUG.println("WAIT FOR IT");
|
||||
@@ -144,6 +150,6 @@ void setup()
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Nothing to do during loop
|
||||
// Nothing to do during loop
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ determineSize KEYWORD2
|
||||
determineSizeNoWrite KEYWORD2
|
||||
getDeviceSize KEYWORD2
|
||||
getPageSize KEYWORD2
|
||||
calculatePageSize KEYWORD2
|
||||
getLastWrite KEYWORD2
|
||||
|
||||
setDeviceSize KEYWORD2
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/I2C_EEPROM.git"
|
||||
},
|
||||
"version": "1.8.5",
|
||||
"version": "1.9.4",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name=I2C_EEPROM
|
||||
version=1.8.5
|
||||
version=1.9.4
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library for I2C EEPROMS
|
||||
|
||||
Reference in New Issue
Block a user