Добавил сообщения об ошибках, функция write теперь повторяет функцию update, put и get теперь принимают не указатели, а данные

This commit is contained in:
EgorShin committed 2024-10-15 12:21:55 +07:00
1 parent 52adac2b59
commit f33566cb41
7 files changed
+53 -105

No files matched your search

@@ -6,9 +6,6 @@
Running this sketch is not necessary, this is Running this sketch is not necessary, this is
simply highlighting certain programming methods. simply highlighting certain programming methods.
Written by Christopher Andrews 2015
Released under MIT licence.
***/ ***/
#include <EEPROM.h> #include <EEPROM.h>
@@ -9,9 +9,6 @@
the put method will use update semantics. As in a byte the put method will use update semantics. As in a byte
will only be written to the EEPROM if the data is actually will only be written to the EEPROM if the data is actually
different. different.
Written by Christopher Andrews 2015
Released under MIT licence.
***/ ***/
#include <EEPROM.h> #include <EEPROM.h>
@@ -3,7 +3,6 @@
* *
* Reads the value of each byte of the EEPROM and prints it * Reads the value of each byte of the EEPROM and prints it
* to the computer. * to the computer.
* This example code is in the public domain.
*/ */
#include <EEPROM.h> #include <EEPROM.h>
@@ -30,28 +29,10 @@ void loop() {
Serial.print(value, DEC); Serial.print(value, DEC);
Serial.println(); Serial.println();
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduino Duemilanove: 512 B EEPROM storage.
- Arduino Uno: 1 kB EEPROM storage.
- Arduino Mega: 4 kB EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
address = address + 1; address = address + 1;
if (address == EEPROM.length()) { if (address == EEPROM.length()) {
address = 0; address = 0;
} }
/***
As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
EEPROM address is also doable by a bitwise and of the length - 1.
++address &= EEPROM.length() - 1;
***/
delay(500); delay(500);
} }
@@ -7,8 +7,6 @@
If a value has not changed in the EEPROM, it is not overwritten If a value has not changed in the EEPROM, it is not overwritten
which would reduce the life span of the EEPROM unnecessarily. which would reduce the life span of the EEPROM unnecessarily.
Released using MIT licence.
***/ ***/
#include <EEPROM.h> #include <EEPROM.h>
@@ -26,7 +24,7 @@ void loop() {
0 to 1023 and each byte of the EEPROM can only hold a 0 to 1023 and each byte of the EEPROM can only hold a
value from 0 to 255. value from 0 to 255.
***/ ***/
int val = analogRead(0) / 4; int val = analogRead(0) / 16;
/*** /***
Update the particular EEPROM cell. Update the particular EEPROM cell.
@@ -43,29 +41,10 @@ void loop() {
} }
***/ ***/
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduino Duemilanove: 512 B EEPROM storage.
- Arduino Uno: 1 kB EEPROM storage.
- Arduino Mega: 4 kB EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
address = address + 1; address = address + 1;
if (address == EEPROM.length()) { if (address == EEPROM.length()) {
address = 0; address = 0;
} }
/***
As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
EEPROM address is also doable by a bitwise and of the length - 1.
++address &= EEPROM.length() - 1;
***/
delay(100); delay(100);
} }
@@ -22,7 +22,7 @@ void loop() {
value from 0 to 255. value from 0 to 255.
***/ ***/
int val = analogRead(0) / 4; int val = analogRead(0) / 16;
/*** /***
Write the value to the appropriate byte of the EEPROM. Write the value to the appropriate byte of the EEPROM.
@@ -32,29 +32,10 @@ void loop() {
EEPROM.write(addr, val); EEPROM.write(addr, val);
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduino Duemilanove: 512 B EEPROM storage.
- Arduino Uno: 1 kB EEPROM storage.
- Arduino Mega: 4 kB EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
addr = addr + 1; addr = addr + 1;
if (addr == EEPROM.length()) { if (addr == EEPROM.length()) {
addr = 0; addr = 0;
} }
/***
As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
EEPROM address is also doable by a bitwise and of the length - 1.
++addr &= EEPROM.length() - 1;
***/
delay(100); delay(100);
} }
+22 -25
View File
@@ -16,13 +16,19 @@ void EEPROMClass:: begin()
HAL_EEPROM_CalculateTimings(&heeprom, OSC_SYSTEM_VALUE); HAL_EEPROM_CalculateTimings(&heeprom, OSC_SYSTEM_VALUE);
} }
uint8_t read( int idx ) uint8_t read_byte( int idx )
{ {
// Проверка адекватности адреса idx // Проверка адекватности адреса idx
if (idx < 0) if (idx < 0)
{
idx = -idx; idx = -idx;
ErrorMsgHandler("EEPROM.read(): The eeprom cell address must be non-negative");
}
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
{
idx = (int)((uint32_t)idx % EEPROM_LENGHT); idx = (int)((uint32_t)idx % EEPROM_LENGHT);
ErrorMsgHandler("EEPROM.read(): The address of the eeprom cell goes beyond the eeprom");
}
uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {}; uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {};
@@ -40,45 +46,36 @@ uint8_t read( int idx )
return (uint8_t)(( read_data_buf[word_idx] & (((uint32_t)0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)) ) >> ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)); return (uint8_t)(( read_data_buf[word_idx] & (((uint32_t)0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)) ) >> ((EEPROM_WORD_SIZE - byte_idx - 1) * 8));
} }
void write( int idx, uint8_t val ) void write_byte( int idx, uint8_t val )
{ {
// Проверка адекватности адреса idx // Проверка адекватности адреса idx
if (idx < 0) if (idx < 0)
{
idx = -idx; idx = -idx;
ErrorMsgHandler("EEPROM.write(): The eeprom cell address must be non-negative");
}
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
{
idx = (int)((uint32_t)idx % EEPROM_LENGHT); idx = (int)((uint32_t)idx % EEPROM_LENGHT);
ErrorMsgHandler("EEPROM.write(): The address of the eeprom cell goes beyond the eeprom");
uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; }
update_byte(idx, val);
// Вычисление адреса начала нужной страницы
uint32_t addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_PAGE_SIZE) * EEPROM_PAGE_SIZE;
// Читаем нужную страницу
HAL_EEPROM_Read(&heeprom, (uint16_t)addr, write_data_buf, EEPROM_PAGE_WORDS, EEPROM_OP_TIMEOUT);
// Адрес искомого слова в eeprom: EEPROM_START_ADDR + (uint32_t)idx
uint32_t word_addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_WORD_SIZE) * EEPROM_WORD_SIZE;
// Индекс искомого слова в массиве write_data_buf: адрес слова в eeprom за вычетом адреса начала страницы
uint32_t word_idx = (word_addr - addr) / EEPROM_WORD_SIZE;
// Номер байта в составе слова
uint32_t byte_idx = ((uint32_t)idx) % EEPROM_WORD_SIZE;
// Извлечение нужного байта
uint32_t byte = (((uint32_t)val) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8));
// Вычленение и замена нужного байта из страницы
write_data_buf[word_idx] = (write_data_buf[word_idx] & (~(((uint32_t)0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)))) | byte;
// Очистка нужной страницы
HAL_EEPROM_Erase(&heeprom, (uint16_t)addr, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
HAL_EEPROM_Write(&heeprom, (uint16_t)addr, write_data_buf, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
} }
// Делает то же, что и write, но записывает только если новый байт отличается от уже записанного // Делает то же, что и write, но записывает только если новый байт отличается от уже записанного
void update( int idx, uint8_t val ) void update_byte( int idx, uint8_t val )
{ {
// Проверка адекватности адреса idx // Проверка адекватности адреса idx
if (idx < 0) if (idx < 0)
{
idx = -idx; idx = -idx;
ErrorMsgHandler("EEPROM.update(): The eeprom cell address must be non-negative");
}
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
{
idx = (int)((uint32_t)idx % EEPROM_LENGHT); idx = (int)((uint32_t)idx % EEPROM_LENGHT);
ErrorMsgHandler("EEPROM.update(): The address of the eeprom cell goes beyond the eeprom");
}
uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {};
+29 -13
View File
@@ -16,20 +16,22 @@
void HAL_read(uint16_t addr, uint32_t * data); void HAL_read(uint16_t addr, uint32_t * data);
void HAL_write(uint16_t addr, uint32_t * data); void HAL_write(uint16_t addr, uint32_t * data);
void HAL_erase(uint16_t addr); void HAL_erase(uint16_t addr);
uint8_t read( int idx ); uint8_t read_byte( int idx );
void write( int idx, uint8_t val ); void write_byte( int idx, uint8_t val );
void update( int idx, uint8_t val ); void update_byte( int idx, uint8_t val );
extern void ErrorMsgHandler(const char * msg);
struct EERef{ struct EERef{
EERef( const int index ) EERef( const int index )
: index( index ) {} : index( index ) {}
uint8_t operator*() const { return read( index ); } uint8_t operator*() const { return read_byte( index ); }
operator uint8_t() const { return **this; } operator uint8_t() const { return **this; }
EERef &operator=( const EERef &ref ) { return *this = *ref; } EERef &operator=( const EERef &ref ) { return *this = *ref; }
EERef &operator=( uint8_t in ) { return write( index, in ), *this; } EERef &operator=( uint8_t in ) { return write_byte( index, in ), *this; }
EERef &operator +=( uint8_t in ) { return *this = **this + in; } EERef &operator +=( uint8_t in ) { return *this = **this + in; }
EERef &operator -=( uint8_t in ) { return *this = **this - in; } EERef &operator -=( uint8_t in ) { return *this = **this - in; }
EERef &operator *=( uint8_t in ) { return *this = **this * in; } EERef &operator *=( uint8_t in ) { return *this = **this * in; }
@@ -86,24 +88,31 @@ struct EEPROMClass{
EERef operator[]( const int idx ) { return idx; } EERef operator[]( const int idx ) { return idx; }
uint8_t read( int idx ) { return EERef( idx ); } uint8_t read( int idx ) { return EERef( idx ); }
void write( int idx, uint8_t val ) { (EERef( idx )) = val; } void write( int idx, uint8_t val ) { (EERef( idx )) = val; }
void update( int idx, uint8_t val ) { EERef( idx ).update( val ); } void update( int idx, uint8_t val ) { update_byte(idx, val); }
void begin(); void begin();
EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. EEPtr end() { return length(); } // Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
uint16_t length() { return (uint16_t)EEPROM_LENGHT; } uint16_t length() { return (uint16_t)EEPROM_LENGHT; }
template< typename T > template< typename T >
T& put(int idx, T& dataPointer) T &put(int idx, T &data)
{ {
void* dataPointer = (void*)&data;
// Проверка адекватности адреса idx // Проверка адекватности адреса idx
if (idx < 0) if (idx < 0)
{
idx = -idx; idx = -idx;
ErrorMsgHandler("EEPROM.put(): The eeprom cell address must be non-negative");
}
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
{
idx = (int)((uint32_t)idx % EEPROM_LENGHT); idx = (int)((uint32_t)idx % EEPROM_LENGHT);
ErrorMsgHandler("EEPROM.put(): The address of the eeprom cell goes beyond the eeprom");
}
uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {};
// Размер данных под запись // Размер данных под запись
uint32_t dataSize = sizeof(dataPointer); uint32_t dataSize = sizeof(data);
// Сдвиг начала записи данных // Сдвиг начала записи данных
uint32_t dataShift = 0; uint32_t dataShift = 0;
uint32_t writeSize = dataSize; uint32_t writeSize = dataSize;
@@ -162,21 +171,28 @@ struct EEPROMClass{
HAL_write((uint16_t)addr, write_data_buf); HAL_write((uint16_t)addr, write_data_buf);
dataSize -= writeSize; dataSize -= writeSize;
} }
return dataPointer; return data;
} }
template< typename T > template< typename T >
T& get(int idx, T& dataPointer) T &get(int idx, T &data)
{ {
void* dataPointer = (void*)&data;
// Проверка адекватности адреса idx // Проверка адекватности адреса idx
if (idx < 0) if (idx < 0)
{
idx = -idx; idx = -idx;
ErrorMsgHandler("EEPROM.get(): The eeprom cell address must be non-negative");
}
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
{
idx = (int)((uint32_t)idx % EEPROM_LENGHT); idx = (int)((uint32_t)idx % EEPROM_LENGHT);
ErrorMsgHandler("EEPROM.get(): The address of the eeprom cell goes beyond the eeprom");
}
uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {}; uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {};
// Размер данных // Размер данных
uint32_t dataSize = sizeof(dataPointer); uint32_t dataSize = sizeof(data);
// Сдвиг начала чтения данных // Сдвиг начала чтения данных
uint32_t dataShift = 0; uint32_t dataShift = 0;
uint32_t readSize = dataSize; uint32_t readSize = dataSize;
@@ -230,7 +246,7 @@ struct EEPROMClass{
memcpy((void *)((uint8_t *)dataPointer + dataShift), (void*)(read_data_buf), readSize); memcpy((void *)((uint8_t *)dataPointer + dataShift), (void*)(read_data_buf), readSize);
dataSize -= readSize; dataSize -= readSize;
} }
return dataPointer; // Возвращаем ссылку на переданный объект с прочитанными данными return data; // Возвращаем ссылку на переданный объект с прочитанными данными
} }
}; };