Я не смог найти ответ с Google, поэтому я пошел на него и запрограммировал довольно много часов.
Я хочу сохранить 9-битные значения в EEPROM, не тратя впустую другие 7 бит. Я сохраняю значения, которые были бы до 500, и у меня осталось не так много EEPROM.
Тот же принцип может быть применен к массивам, что я и сделал, чтобы не перепутать EEPROM.
ТакЯ сделал эту маленькую программу:
/*
* Write only a certain number of bits to EEPROM.
*
* keeps the other bit in the byte of the eeprom as they are.
*
* Working version with 9 bits:
* 2019-10-03 15:57
* 2019-10-03 22:09 tested with chars too
* 2019-10-04 08:25 works with 7 bit chars also!
* 2019-10-04 12:27 fixed the combining of oldByte and new values in writeBitsToEEPROM(), because chars like 'ö' altered previous bit (left side) that should not have been altered.
*
*/
#include "arduino.h"
#include "EEPROM.h"
#include "math.h"
#define BIT_BLOCKS_COUNT 15
#define BLOCK_BYTE_COUNT 17
#define ARRAY_SIZE BLOCK_BYTE_COUNT+2
//TODO: change back to original value
#define EEPROM_SIZE ARRAY_SIZE
byte fakeEEPROM[ARRAY_SIZE] = {0};
String byteToString(byte value){
char byteChar[9];
byteChar[8] = '\0'; //we need a terminator
for(int i=7; i>=0; i--){
byteChar[7-i] = (value & (1 << i)) ? '1' : '0';
}
return String(byteChar);
}
String byteToString(unsigned long value, byte bytesToRead){
String str1 = byteToString(value >> 8);
String str2 = byteToString(value & 0xFF);
return str1 + " " + str2;
}
int globBlockStartAdress = 0;
byte globNumberOfBits = 0;
int globBlockSizeBytes = 0;
bool initBitBlock(int blockStartAdress, int blockCount, byte numberOfBits) {
globBlockStartAdress = blockStartAdress;
globNumberOfBits = numberOfBits;
// calc needed number of bytes and roud up
int tempBlockSize = blockCount * numberOfBits / 8;
if(blockCount * numberOfBits % 8)
tempBlockSize++;
// make number of bytes even
if(tempBlockSize % 2)
tempBlockSize++;
globBlockSizeBytes = tempBlockSize;
if(blockStartAdress + globBlockSizeBytes > EEPROM_SIZE)
return false;
return true;
}
/*
* Writes 1 to 9 bits to "internalAdress" within a designated block in eeprom
*/
void writeBitsToEEPROM(unsigned int bitsToBeWritten, int internalAdress){
//TODO: check if value is not higher than what can be stored
// if(bitsToBeWritten){
//
// }
int trueEEPROMAdress = globBlockStartAdress + internalAdress * globNumberOfBits / 8;
if(trueEEPROMAdress + 1 >= ARRAY_SIZE || internalAdress * globNumberOfBits / 8 >= globBlockSizeBytes){
Serial.print("globBlockSizeBytes: ");
Serial.println(globBlockSizeBytes);
Serial.println("FEHLER writeBitsToEEPROMWTF: ");
Serial.println(trueEEPROMAdress + 1);
Serial.println(internalAdress * globNumberOfBits / 8 );
}
byte startBitOfEEPROMByte = (internalAdress * globNumberOfBits) % 8;
unsigned int oldIntFromEEPROM = (fakeEEPROM[trueEEPROMAdress] << 8) | fakeEEPROM[trueEEPROMAdress + 1];
//Todo: change to eeprom
//filter out only the bits that need to be kept.
//EEPROM.get(trueEEPROMAdress, oldEEPROMByteBits);
// there might be bits in the byte that we dont want to change. left side and right side
unsigned int mask1KeepFromEEPROM = (0xFFFF << (16 - startBitOfEEPROMByte));
unsigned int mask2KeepFromEEPROM = (0xFFFF >> (startBitOfEEPROMByte + globNumberOfBits));
//if(16 - startBitOfEEPROMByte - numberOfBits > 0)
//mask2KeepFromEEPROM= (0xFFFF >> (startBitOfEEPROMByte + numberOfBits));
// masks combined
unsigned int maskIntToKeepFromEEPROM = mask1KeepFromEEPROM | mask2KeepFromEEPROM;
int newEEPROMInt = (oldIntFromEEPROM & maskIntToKeepFromEEPROM) | ((bitsToBeWritten << (16 - globNumberOfBits - startBitOfEEPROMByte) & ~maskIntToKeepFromEEPROM));
//Todo: change to eeprom
//write
//EEPROM.update(trueEEPROMAdress, newEEPROMByteBitsA);
fakeEEPROM[trueEEPROMAdress] = (newEEPROMInt >> 8);
fakeEEPROM[trueEEPROMAdress + 1] = (byte) newEEPROMInt;
if(trueEEPROMAdress + 1 > BLOCK_BYTE_COUNT){
Serial.println("FEHLER writeBitsToEEPROM");
Serial.println(trueEEPROMAdress + 1);
Serial.println("blockStartAdress");
Serial.println(globBlockStartAdress);
Serial.println("internalAdress");
Serial.println(internalAdress);
Serial.println("numberOfBits");
Serial.println(globNumberOfBits);
}
// Serial.print("trueEEPROMAdress: ");
// Serial.println(trueEEPROMAdress);
//
// Serial.print("internalAdress: ");
// Serial.println(internalAdress);
//
// Serial.print("globNumberOfBits: ");
// Serial.println(globNumberOfBits);
//
// Serial.print("bitsToBeWritten: ");
// Serial.println(byteToString(bitsToBeWritten,2));
//
// Serial.print(" mask1KeepFromEEPROM: ");
// Serial.println(byteToString(mask1KeepFromEEPROM,2));
//
// Serial.print("mask2KeepFromEEPROM: ");
// Serial.println(byteToString(mask2KeepFromEEPROM,2));
//
// Serial.print("maskIntToKeepFromEEPROM: ");
// Serial.println(byteToString(maskIntToKeepFromEEPROM,2));
//
// Serial.print("oldIntFromEEPROM: ");
// Serial.println(byteToString(oldIntFromEEPROM,2));
//
// Serial.print("newEEPROMInt: ");
// Serial.println(byteToString(newEEPROMInt,2));
//
// Serial.print("512: ");
// Serial.println(byteToString(512, 2));
//
// Serial.print("65535: ");
// Serial.println(byteToString(65535, 2));
}
unsigned int ReadBitsFromEEPROM(int internalAdress){
int trueEEPROMAdress = globBlockStartAdress + internalAdress * globNumberOfBits / 8;
byte startBitOfEEPROMByte = (internalAdress * globNumberOfBits) % 8;
if(trueEEPROMAdress + 1 > BLOCK_BYTE_COUNT)
Serial.println("FEHLER readBits");
unsigned int oldIntFromEEPROM = (fakeEEPROM[trueEEPROMAdress] << 8) | fakeEEPROM[trueEEPROMAdress + 1];
//Todo: change to eeprom
//filter out only the bits that need to be kept.
//EEPROM.get(trueEEPROMAdress, oldEEPROMByteBits);
unsigned int mask1KeepFromEEPROM = (0xFFFF << (16 - startBitOfEEPROMByte));
unsigned int mask2KeepFromEEPROM = (0xFFFF >> (startBitOfEEPROMByte + globNumberOfBits));
unsigned int maskIntToKeepFromEEPROM = mask1KeepFromEEPROM | mask2KeepFromEEPROM;
unsigned int valueFromEEPROM = ~maskIntToKeepFromEEPROM & oldIntFromEEPROM;
// Serial.print("trueEEPROMAdress: ");
// Serial.println(trueEEPROMAdress);
//
// Serial.print("internalAdress: ");
// Serial.println(internalAdress);
//
// Serial.print("numberOfBits: ");
// Serial.println(numberOfBits);
//
// Serial.print(" mask1KeepFromEEPROM: ");
// Serial.println(byteToString(mask1KeepFromEEPROM,2));
//
// Serial.print("mask2KeepFromEEPROM: ");
// Serial.println(byteToString(mask2KeepFromEEPROM,2));
////
// Serial.print("maskIntToKeepFromEEPROM: ");
// Serial.println(byteToString(maskIntToKeepFromEEPROM,2));
////
// Serial.print("oldIntFromEEPROM: ");
// Serial.println(byteToString(oldIntFromEEPROM,2));
return (valueFromEEPROM >> (16 - globNumberOfBits - startBitOfEEPROMByte));
}
void setup() {
Serial.begin(57600);
Serial.print(F("\n# Programversion: "));
Serial.print(__TIME__);
Serial.print(" ");
Serial.println(__DATE__);
Serial.println("Setup finished");
delay(1000);
}
void printEEPROM(){
for(int i = 0; i < ARRAY_SIZE; i++){
byte b;
//Todo: change to eeprom
//EEPROM.get(i, b);
b = fakeEEPROM[i];
Serial.print(byteToString(b));
Serial.print(" ");
}
Serial.println();
}
void testNumbers() {
Serial.println("bits?");
while( ! Serial.available());
String input = Serial.readString();
unsigned int value = input.toInt();
initBitBlock(1, 15, 9);
// Serial.print("value: ");
// Serial.println(byteToString(value));
for(int i = 0; i < BIT_BLOCKS_COUNT;i++){
for(int j = 0; j < BLOCK_BYTE_COUNT; j++){
fakeEEPROM[j] = 0xFF;
if(j > BLOCK_BYTE_COUNT)
Serial.println("FEHLER testNumbers");
}
// Serial.print("EEPROM before: ");
// printEEPROM();
writeBitsToEEPROM(value, i);
Serial.print("Returned: ");
Serial.println(ReadBitsFromEEPROM(i));
// Serial.print("EEPROM after: ");
// printEEPROM();
// Serial.println();
}
delay(1000);
}
#define CHAR_COUNT 16
void testChars() {
// Serial.println("bits?");
// while( ! Serial.available());
// String input = Serial.readString();
//
// unsigned int value = input.toInt();
initBitBlock(1, CHAR_COUNT, 7);
Serial.println("string?");
while( ! Serial.available());
String input = Serial.readString();
Serial.println(input);
char testString[CHAR_COUNT] = {'\0'};
input.toCharArray(testString, CHAR_COUNT, 0);
for(int j = 0; j < ARRAY_SIZE; j++){
fakeEEPROM[j] = 0;//xFF;
}
for(int i = 0; i < CHAR_COUNT; i++){
Serial.print("EEPROM before: ");
printEEPROM();
writeBitsToEEPROM(testString[i], i);
Serial.print("EEPROM after: ");
printEEPROM();
Serial.println();
}
Serial.println("Returned: ");
for(int i = 0; i < CHAR_COUNT; i++){
Serial.print((char) ReadBitsFromEEPROM(i));
}
Serial.println();
delay(1000);
}
void loop(){
testChars();
testNumbers();
}
, которая, конечно, не завершена. Это просто для сохранения этих 9-битных значений.
Мой вопрос: кто-нибудь еще запрограммировал такую функцию - или знает, где ее найти - которая не ограничена 9 битами (10 бит будет охватывать 3байт)