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.