wtorek, 26 grudnia 2017

Zapis tablicy struktur do EEPROMa - nauka C przy budowie routera 433 MHz

Zaciekawił mnie temat struktury w języku C. Dziś więc na warsztacie coś z przedszkola (nie)młodego programisty.

Zapisywanie wielobajtowych informacji w EEPROMie (a tak naprawdę we FLASHu) mojego D1 MINI jest mocno upierdliwe. Trzeba stworzyć kawałek programu, który będzie wgrywał zmienną bajt po bajcie do pamięci. Odczytanie danej wymaga procedury odwrotnej z zachowaniem właściwej kolejności pakowania bajtów do odtwarzanych zmiennych. Zabawa przydatna na kursie z programowania a nie w hobbystycznym programowaniu. Toteż informacja iż procedury put/get zapisu/odczytu pamięci przyjmują bardzie złożone typy danych (np. struktury) wydaje się z tego punktu widzenia mocno interesująca.
Z tego co rozumiem struktura to typ zmiennej (jak int, char, float) tylko taki zdefiniowany przez użytkownika. I składa się z typów podstawowych i innych typów wcześniej zdefiniowanych w programie.
Zdefiniuję sobie nowy typ danych związanych z kodami urządzeń współpracujących z routerem 433MHz - tadres. Typ składa się z dwu zmiennych niezbędnych do prawidłowego wysterowania urządzeń bezprzewodowych tj kodu i impulsu.
struct tadres{long kod;int impusl;};
Teraz zdefiniowanie zmiennych o typie tadres i nakarmienie ich przykładowymi wartościami
tadres adres1 = {555555 , 300}
tadres adres2 = {7654321 , 321}
Wydrukować całej struktury nie mogłem, chyba trzeba więc po kawałku
  Serial.println(adres1.kod);   Serial.println(adres1.impuls);
mogę też kawałkami wprowadzić nowe wartości
adres1.kod = 123456;   adres1.impuls = 123;
I pobierałem te dane
long kod =  adres1.kod;   int impuls = adres1.impuls;
Kodów będę miał sporo, powiedzmy 50 szt. Zamiast tworzyć 50 zmiennych spróbuję stworzyć tablicę zmiennych o typie tadres
tadres tablica_adres[50]; 
ładowanie wartości do kolejnych pozycji tablicy będzie wyglądać tak
tablica_adres[1] = {555555 , 300};
tablica_adres[2] = {7654321 , 321};
działa - jest tylko jedno ALE - takie wpisywanie wartości elementów tablicy struktur MUSI znajdować się w pętli Setup lub Loop. Cholera wie czemu bo wpisywanie wartości do samej struktury działa także poza tymi pętlami.

Pobieranie konkretnej danej z tablicy struktur działa analogicznie do pobierania danych ze struktury
long kod = tablica_adres[1].kod;
int impuls = tablica_adres[1].impuls 

Zaletą zapisu całej tabeli struktur jest też kompletna obojętność na sposób ulokowania danych w pamięci nieulotnej. Wszystkim tym zajmuje się kompilator. Wystarczy mu podać nazwę danej a właściwe adresy wyliczy już sobie sam. Te struktury to fajna rzecz.

Teraz już mogę stworzyć funkcje, których zmienną wejściową lub wyjściową będzie zmienna typu  struktura czyli tadres. Szczególnie dla funkcji zwracających wartość struktura jest bezcenna - można tym sposobem pobrać z funkcji nie jedną a dowolną ilość zmiennych o różnych typach.
void zapisz_adres (tadres ta){}
tadres odczytaj_adres(){}
To na razie wszystkie klocki niezbędne do modyfikacji procedury zapisz_kod()  z poprzedniego wpisu. I procedury readkod() i savekod() tym razem ze strukturą w roli głównej i to w postaci tabeli struktur. 
Na początek program testowy co by sprawdzić, czy wszystko sztymuje


#include <EEPROM.h>

struct stadres { //deklaracja struktury adresu kod+impuls
  long kod;
  int impuls;
};
stadres tablica_adres[3];  //tablica adresów do zapamiętania w EEPROMie

void savetab () {
  int  adres = 10;  //zapis od adresu 10
  EEPROM.begin(512);
  EEPROM.put(adres, tablica_adres);  //zapis całej tablicy do eeprom
  EEPROM.end(); //  EEPROM.commit();
}
void readkod() { // odczyt z eeprom
  int  adres = 10;
  EEPROM.begin(512);
  EEPROM.get(adres, tablica_adres); //odczyt z eeprom do tablicy
  EEPROM.end(); //  EEPROM.commit();
}

void setup() {
  Serial.begin(115200);  delay(100);
  Serial.println();  Serial.println(F(__FILE__)); 

  tablica_adres[0] = {111111, 111};  //wypełnienie tablicy wartością początkową adresów
  tablica_adres[1] = {2222222, 222};
  tablica_adres[2] = {33333, 333};

  Serial.print(tablica_adres[0].kod);  Serial.println("  wartosc poczatkowa");
  readkod(); // odczytuje z eepromu 
  Serial.print(tablica_adres[0].kod);  Serial.println("  wartosc z eeprom");
  tablica_adres[0].kod += 123456;           // zmiana wartości pierwszego elementu tablicy
  Serial.print(tablica_adres[0].kod);  Serial.println("  wartosc zapisana do eeprom");
  savetab();
}

void loop() {
}


A tu widok monitora po kolejnych resetach procesora. Przy odłączeniu zasilania jest identycznie.



Więc działa. Cuda panie po prostu cuda..

Automat skończony do dekodowania kodów 
Zapisywanie kodów do EEPROMu  
typ struktura i zapis tablicy struktur do  EEPROMu  

No cóż ciąg dalszy staje się coraz ciekawszy......

Wcześniejsze odcinki serialu
http://100-x-arduino.blogspot.com/2017/11/router-433-mhz-aczymy-rozne-systemy.html
http://100-x-arduino.blogspot.com/2017/11/router-433-mhz-nauka-czytania-i-pisania.html
http://100-x-arduino.blogspot.com/2017/12/router433-jak-programowac-schematy.html
http://100-x-arduino.blogspot.com/2017/12/esp8266-zapis-do-pamieci-eeprom-kodow.html
107

Brak komentarzy:

Publikowanie komentarza