ESP8266 Remote Controller part. 3

Funkcje zapisu i czytania pamięci EEPROM.

Omówię funkcje potrzebne do czytania i zapisywania pamięci EEPROM.

Zanim omówię program główny muszę omówić funkcje czytania z pamięci EEPROM (readEEProm()) i zapisywania do EEPROM (saveEEProm()). Aby można było zapisać dane w pamięci EEPROM musimy je przetworzyć na typ char, bo do pamięci EEPROM możemy zapisywać tylko pojedyncze bajty. Funkcja int2char() oraz long2char() zamieniają zmienną int i long na char, a funkcje char2int() i char2long() robią odwrotnie z char do int i long. Omówię je kolejno. Można je zrobić na wiele różnych sposobów, ale ja je zrobiłem właśnie tak. Liczby int stosowane w naszym programie są ograniczone do dwóch bajtów. Funkcja int2char(liczba, który_bajt) umożliwia nam odczyt bajtu wyższego 'H’ lub mniejszego 'L’.

uint8_t int2char(uint16_t liczba, uint8_t bytex){
 if (bytex == 'L'){
 return (liczba & 0xFF); //zwraca młodszy bajt
 }else if (bytex == 'H') {
 return (liczba >> 8); //zwraca starszy bajt
 }
 return 0;
}

Funkcja char2int(Lbajt, Hbajt) tworzy liczbę z dwóch bajtów. Bajt wyższy przesuwa 8 bitów w lewo (mnoży przez 256) i dodaje bajt niższy.

uint16_t char2int(uint8_t Lbyte, uint8_t Hbyte){
return ((Hbyte << 8) + Lbyte);
}

Funkcja long2char() zamienia liczbę 4-bajtową na cztery char. Do przetwarzania liczb na char wykorzystana jest zmienna EcodOn0[4].

void long2char(uint32_t liczba ){
 for (uint8_t i = 0; i<4; i++){
 EcodOn0[i] = (uint8_t)(liczba & 0xFF);
 liczba = (uint32_t) (liczba >> 8);
 }
 return ;
}

Funkcja char2long(wskaźnik_do_char)  z czterech bajtów char oblicza liczbę long. Bierze liczbę 0 dodaje bajt najwyższy, potem przesuwa liczbę 8 bitów w lewo i dodaje kolejny bajt, te dwie czynności powtarza dla każdego z pozostałych 3 bajtów i zwraca całą liczbę.

uint32_t char2long(uint8_t * src ){
 uint32_t a = 0;
 for (uint8_t i = 0; i<4; i++){
 a = (a << 8);
 a += src[i];
 }
 return a;
}

Potrzebna będzie jeszcze jedna funkcja, która z kodu załączenia utworzy kod wyłączenia. Dla różnych przekaźników mogą być dwa rodzaje kodów załączenia  0011 lub 0001 (ostatnie cztery bity z prawej strony liczby binarnej), a kody wyłączenia odpowiednio 1100 i 0100. Funkcja sprawdza czy tam są dwa bity (11) czy jeden (01) i w pierwszym przypadku dodaje 9, a w drugim dodaje 3. O liczbach binarnych w Internecie jest dużo informacji. Oto funkcja codOnTocodOff(kod_On).

uint32_t codOnTocodOff(uint32_t cod){
 return cod+((((cod) & 3) > 1)? (9) : (3)); //oblicz kod wyłączenia
}

Teraz omówię funkcję readEEProm(). Czyta ona z EEPROM bajt po bajcie za pomocą funkcji EEPROM.read(pozycja_w_ EEPROM) i odpowiednio je łączy, aby utworzyć poszczególne liczby.

void readEEProm(void){
 int offset = 1; //licznik pozycji w pamięci EEPROM
 //po odczytaniu kolejnej pozycji jest zwiększany o 1
 //kody przekaźników
 //odczytaj kolejne 4 bajty przekaźnika nr 1
 EcodOn1[0] = EEPROM.read(offset++);
 EcodOn1[1] = EEPROM.read(offset++);
 EcodOn1[2] = EEPROM.read(offset++);
 EcodOn1[3] = EEPROM.read(offset++);
 //oblicz i zapamiętaj kod przekaźnika nr 1
 RFrelay1.setCodOn(char2long(EcodOn1));
 //zrób to samo dla przekaźnika nr 2
 EcodOn2[0] = EEPROM.read(offset++);
 EcodOn2[1] = EEPROM.read(offset++);
 EcodOn2[2] = EEPROM.read(offset++);
 EcodOn2[3] = EEPROM.read(offset++);
 RFrelay2.setCodOn(char2long(EcodOn2));
 /zrób to samo dla przekaźnika nr 3
 EcodOn3[0] = EEPROM.read(offset++);
 EcodOn3[1] = EEPROM.read(offset++);
 EcodOn3[2] = EEPROM.read(offset++);
 EcodOn3[3] = EEPROM.read(offset++);
 RFrelay3.setCodOn(char2long(EcodOn3));
 //lengthLH przekaźników
 Eval1[0] = EEPROM.read(offset++);
 Eval1[1] = EEPROM.read(offset++);
 //oblicz i zapamiętaj czas impulsu HIGH
 //dla przekaźnika nr 1
 RFrelay1.lengthLH = char2int(Eval1[1],Eval1[0]);
 Eval1[0] = EEPROM.read(offset++);
 Eval1[1] = EEPROM.read(offset++);
 //zrób to samo dla przekaźnika nr 2
 RFrelay2.lengthLH = char2int(Eval1[1],Eval1[0]);
 Eval1[0] = EEPROM.read(offset++);
 Eval1[1] = EEPROM.read(offset++);
 //zrób to samo dla przekaźnika nr 3
 RFrelay3.lengthLH = char2int(Eval1[1],Eval1[0]);
 //protokoły
 //pobierz i zapamiętaj protokół dla każdego przekaźnika
 RFrelay1.protocol = EEPROM.read(offset++);
 RFrelay2.protocol = EEPROM.read(offset++);
 RFrelay3.protocol = EEPROM.read(offset++);
 //stany przekaźników
 //załącz lub wyłącz przekaźniki zwykłe
 (EEPROM.read(offset++)==1)? r1.setOn(): r1.setOff();
 (EEPROM.read(offset++)==1)? r2.setOn(): r2.setOff();
 (EEPROM.read(offset++)==1)? r3.setOn(): r3.setOff();
 //odczytaj i zapisz stany przekaźników radiowych
 RFrelay1.writeRF(EEPROM.read(offset++));
 RFrelay2.writeRF(EEPROM.read(offset++));
 RFrelay3.writeRF(EEPROM.read(offset++));
 //ustaw kody Off
 //oblicz i zapamiętaj kody wyłączenia każdego przekaźnika
 RFrelay1.setCodOff(codOnTocodOff(RFrelay1.getCodOn()));
 RFrelay2.setCodOff(codOnTocodOff(RFrelay2.getCodOn()));
 RFrelay3.setCodOff(codOnTocodOff(RFrelay3.getCodOn()));
 //zależnie od stanu odczytanego, załącz lub wyłącz przekaźniki RF
 (RFrelay1.RF==1)? RFrelay1.sendOn() : RFrelay1.sendOff();
 (RFrelay2.RF==1)? RFrelay2.sendOn() : RFrelay2.sendOff();
 (RFrelay3.RF==1)? RFrelay3.sendOn() : RFrelay3.sendOff();
 return;
}

Ostatnią funkcją dotyczącą EEPROM jest funkcja saveEEProm(). Musi ona zapisywać poszczególne bajty w tej samej kolejności co w funkcji readEEProm(). Zapisuje ona tylko kody załączenia, bo kody wyłączenia można obliczyć z kodu załączenia. Funkcja EEPROM.write(pozycja, wartość) zapisuje ona w miejsce pozycja bajt wartość.

void saveEEProm(void){
 int offset = 1; //licznik pozycji w EEPROM
 //kody przekaźników
 //zamień kod przekaźnika nr 1 na bajty
 long2char(RFrelay1.getCodOn());
 //zapisz je kolejno od najwyższego do EEPROM
 EEPROM.write(offset++,EcodOn0[3]);
 EEPROM.write(offset++,EcodOn0[2]);
 EEPROM.write(offset++,EcodOn0[1]);
 EEPROM.write(offset++,EcodOn0[0]);
 //zrób to samo z kodem przekaźnika nr 2
 long2char(RFrelay2.getCodOn());
 EEPROM.write(offset++,EcodOn0[3]);
 EEPROM.write(offset++,EcodOn0[2]);
 EEPROM.write(offset++,EcodOn0[1]);
 EEPROM.write(offset++,EcodOn0[0]);
 //zrób to samo z kodem przekaźnika nr 3
 long2char(RFrelay3.getCodOn());
 EEPROM.write(offset++,EcodOn0[3]);
 EEPROM.write(offset++,EcodOn0[2]);
 EEPROM.write(offset++,EcodOn0[1]);
 EEPROM.write(offset++,EcodOn0[0]);
 //lengthLH przekaźników
 //dla przekaźnika nr 1
 EEPROM.write(offset++,int2char(RFrelay1.lengthLH,'H'));
 EEPROM.write(offset++,int2char(RFrelay1.lengthLH,'L'));
 //dla przekaźnika nr 2
 EEPROM.write(offset++,int2char(RFrelay2.lengthLH,'H'));
 EEPROM.write(offset++,int2char(RFrelay2.lengthLH,'L'));
 //dla przekaźnika nr 3
 EEPROM.write(offset++,int2char(RFrelay3.lengthLH,'H'));
 EEPROM.write(offset++,int2char(RFrelay3.lengthLH,'L'));
 //protokoły przekaźników
 EEPROM.write(offset++,RFrelay1.protocol);
 EEPROM.write(offset++,RFrelay2.protocol);
 EEPROM.write(offset++,RFrelay3.protocol);
 //stany przekaźników zwykłych
 EEPROM.write(offset++,r1.read());
 EEPROM.write(offset++,r2.read());
 EEPROM.write(offset++,r3.read());
 //stany przekaźników RF
 EEPROM.write(offset++,RFrelay1.readRF());
 EEPROM.write(offset++,RFrelay2.readRF());
 EEPROM.write(offset++,RFrelay3.readRF());

 EEPROM.commit(); //zapisz pamięć EEPROM
 return;
}

W tej części to już wszystko.

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *