kamil2234 Temat założony przez niniejszego użytkownika |
Przenoszenie pola struktury jako argument funkcji » 2017-02-02 19:17:22 Obecnie mam bardzo nieelegancki kod do wyliczania wartości offsetof dla każdego pola w strukturze. Za każdym razem kiedy dodaje nowe pole do struktury muszę definiować dodatkowo offsetof co jest trudne w utrzymaniu kodu. #include <Wire.h> #include <I2C_EEPROM.h> AT24C32 < 0x57 > eep; #define offsetof(s,m) (size_t)&(((s *)NULL)->m)
struct MySetingsTab { char struct_start[ 10 ]; char wifi_ssid[ 255 ]; char wifi_password[ 255 ]; int svrport; int dhcp; int ip_0; int ip_1; int ip_2; int ip_3; int nm_0; int nm_1; int nm_2; int nm_3; int gw_0; int gw_1; int gw_2; int gw_3; int dns_p0; int dns_p1; int dns_p2; int dns_p3; int dns_s0; int dns_s1; int dns_s2; int dns_s3; char system_login[ 255 ]; char system_password[ 255 ]; int active_time; int sleep_time; int remote_raporting; int frequency_sec; char remote_url[ 255 ]; char struct_end[ 10 ]; } mysetingstab, setingsfromdb;
size_t offset_struct_start = offsetof( MySetingsTab, struct_start ); size_t offset_wifi_ssid = offsetof( MySetingsTab, wifi_ssid ); size_t offset_wifi_password = offsetof( MySetingsTab, wifi_password ); size_t offset_svrport = offsetof( MySetingsTab, svrport ); size_t offset_dhcp = offsetof( MySetingsTab, dhcp ); size_t offset_ip_0 = offsetof( MySetingsTab, ip_0 ); size_t offset_ip_1 = offsetof( MySetingsTab, ip_1 ); size_t offset_ip_2 = offsetof( MySetingsTab, ip_2 ); size_t offset_ip_3 = offsetof( MySetingsTab, ip_3 ); size_t offset_nm_0 = offsetof( MySetingsTab, nm_0 ); size_t offset_nm_1 = offsetof( MySetingsTab, nm_1 ); size_t offset_nm_2 = offsetof( MySetingsTab, nm_2 ); size_t offset_nm_3 = offsetof( MySetingsTab, nm_3 ); size_t offset_gw_0 = offsetof( MySetingsTab, gw_0 ); size_t offset_gw_1 = offsetof( MySetingsTab, gw_1 ); size_t offset_gw_2 = offsetof( MySetingsTab, gw_2 ); size_t offset_gw_3 = offsetof( MySetingsTab, gw_3 ); size_t offset_dns_p0 = offsetof( MySetingsTab, dns_p0 ); size_t offset_dns_p1 = offsetof( MySetingsTab, dns_p1 ); size_t offset_dns_p2 = offsetof( MySetingsTab, dns_p2 ); size_t offset_dns_p3 = offsetof( MySetingsTab, dns_p3 ); size_t offset_dns_s0 = offsetof( MySetingsTab, dns_s0 ); size_t offset_dns_s1 = offsetof( MySetingsTab, dns_s1 ); size_t offset_dns_s2 = offsetof( MySetingsTab, dns_s2 ); size_t offset_dns_s3 = offsetof( MySetingsTab, dns_s3 ); size_t offset_system_login = offsetof( MySetingsTab, system_login ); size_t offset_system_password = offsetof( MySetingsTab, system_password ); size_t offset_active_time = offsetof( MySetingsTab, active_time ); size_t offset_sleep_time = offsetof( MySetingsTab, sleep_time ); size_t offset_remote_raporting = offsetof( MySetingsTab, remote_raporting ); size_t offset_frequency_sec = offsetof( MySetingsTab, frequency_sec ); size_t offset_remote_url = offsetof( MySetingsTab, remote_url ); size_t offset_struct_end = offsetof( MySetingsTab, struct_end );
Przypadek użycia kodu jest potem taki jak poniżej. Pozwala zapisać do pamięci eeprom we wskazane miejsce dane dotyczące tylko konkretnego pola w strukturze. Dzięki czemu mogę sobie oszczędzić ograniczoną ilość cyki zapisu. Nie zapisuję całej struktury tylko wybrane pola. Kod zapisu do eeprom bazuje na wyliczonym adresie w pamięci. mysetingstab.wifi_password = "mypassword"; eep.put( offset_wifi_password, mysetingstab.wifi_password );
Chciałbym jednak zaoszczędzić sobie pracy podczas utrzymania kodu i wyliczać offsetof dynamicznie dla każdego przypadku użycia.niech jakaś inna funkcja się martwi o to jaki jest adres dla danego pola w określonej strukurze. Potrzebuję więc napisać funkcję, która będzie działać tak ja ta poniżej. Oczywiście poniższy kod to bzdura, ale chyba obrazuje co chcę osiągnąć. Bardzo proszę o pomoc i sugestię. void save_data( mysetingstab.field ) { int offsetof = offsetof( mysetingstab.field ); eep.put( offsetof, mysetingstab.field ); }
save_data( mysetingstab.wifi_password );
|
|
darko202 |
» 2017-02-03 14:19:25 trudno mi się połapać z czym masz problem :( dlatego zadam narzucające mi się -może głupie- pytanie : czy myślałeś nad wykorzystaniem do rozwiązania "switch" ? oczywiście wewnątrz poszukiwanej przez Ciebie funkcji |
|
kamil2234 Temat założony przez niniejszego użytkownika |
» 2017-02-03 14:51:02 Problem jest w tym, że nie chcę wyliczać adresu za każdym razem dla nowego pola, które dodam sobie do struktury. Żeby zapisać dane do pamięci eeprom trzeba wyliczyć adres komórki pamięci dla danego pola. Zauważ, że funkcja put posiada dwa parametry, które pozwalają zapisać dane do pamięci. eep.put( adres pami ę ci, warto ś ć );
Chcę więc umieść funkcję put w ramach innej funkcji. Chciałbym aby ta funkcja posiadała tylko jeden parametr myStruct.field. Kostrukcja mogła by wyglądać tak: void save( struktura.pole ) { int offsetof = offsetof( argument to struktura z polem ); eep.put( offsetof, argument to struktura z polem ); }
save( myStruct.field );
Szukam jakieś rozwiązania, które pozwoli mi osiągnąć taki efekt jw. Korzystam z tej biblioteki. https://github.com/CombiesGit/I2C_EEPROM |
|
1aam2am1 |
» 2017-02-03 16:49:46 Dlaczego niewykorzystasz eeprom_update_block? |
|
mokrowski |
» 2017-02-03 18:02:49 Nie wiem co i jak często robisz z pamięcią EEPROM ale może zacznij od tego że policzysz ile razy wykonujesz te operacje. Jeśli przy wyłączaniu systemu wykonywany jest zapis zmienionych ustawień, to może okazać się że ilość operacji wystarczy Ci na 20 lat... :-) Wtedy określisz czy warto kruszyć kopię. Policzyłeś to? |
|
kamil2234 Temat założony przez niniejszego użytkownika |
» 2017-02-04 13:39:39 1aam2am1 -> Eeprom update? Nie widziałem, że w tej bibliotece była taka funkcja. mokrowski -> Nie chodzi o częstotliwość zapisu tylko o szybkość zapisu i przejrzystość kodu. Nie chcę zapisywać za każdym razem całej struktury. Wczoraj napisałem kod troszkę inaczej, ale dalej nie operuję na polach tylko całych strukturach, co prowadzi do bezsensownego marnowania pamięci. Mimo to załączę ten kod może komuś się przyda do Arduino :) biblioteka jest tutaj: https://github.com/CombiesGit/I2C_EEPROM #include <Wire.h> #include <I2C_EEPROM.h> AT24C32 < 0x57 > eep; #define offsetof(s,m) (size_t)&(((s *)NULL)->m)
struct schema { char f_varchar[ 64 ]; int f_int; float f_float; double f_double; int f_id; };
int rec_id = 0;
void EraseEpprom() { if( eep.ready() ) { Serial.println( "Epprom ready..." ); Serial.println( "Erase epprom..." ); for( int i = 0; i < eep.length(); i++ ) { uint16_t an = i; int vb = 0; eep.put( an, vb ); delay( 10 ); } Serial.println( "DONE -> WAIT TIME 1 sek" ); delay( 1000 ); } else { Serial.println( "EraseEpprom -> conection problem" ); } }
schema InitEepromValue( int rec_id ) { schema instance; instance.f_id = rec_id; strcpy( instance.f_varchar, "" ); return( instance ); }
schema GetFormDB( struct schema instance ) { schema odbior; strcpy( odbior.f_varchar, "er" ); odbior.f_id = 0; odbior.f_float = 0.0; odbior.f_double = 0.0001; size_t offset = sizeof( schema ); offset =( offset * instance.f_id ) - offset; if( eep.ready() ) { eep.fastBlockRead( offset, & instance, sizeof( schema ) ); delay( 2 ); return( instance ); } else { Serial.println( "GetFormDB -> conection problem" ); return( odbior ); } }
void SaveToDB( struct schema instance ) { size_t offset = sizeof( schema ); offset =( offset * instance.f_id ) - offset; if( eep.ready() ) { eep.put( offset, instance ); delay( 2 ); } else { Serial.println( "InsertToDB -> conection problem" ); } }
void setup() { Serial.begin( 9600 ); delay( 3000 ); Wire.begin(); delay( 3000 ); delay( 1000 ); struct schema sample_instance; struct schema login_wifi = InitEepromValue( rec_id ); rec_id++; struct schema haslo_wifi = InitEepromValue( rec_id ); rec_id++; struct schema port = InitEepromValue( rec_id ); rec_id++; struct schema last_temp = InitEepromValue( rec_id ); rec_id++; strcpy( login_wifi.f_varchar, "admin" ); strcpy( haslo_wifi.f_varchar, "Mojetajnehaslo" ); port.f_int = 80; last_temp.f_float = 23.21; SaveToDB( login_wifi ); SaveToDB( haslo_wifi ); SaveToDB( last_temp ); SaveToDB( port ); login_wifi = GetFormDB( login_wifi ); haslo_wifi = GetFormDB( haslo_wifi ); last_temp = GetFormDB( last_temp ); port = GetFormDB( port ); Serial.print( "haslo_wifi.f_varchar to: " ); Serial.println( haslo_wifi.f_varchar ); Serial.print( "login_wifi.f_varchar to: " ); Serial.println( login_wifi.f_varchar ); Serial.print( "last_temp float to: " ); Serial.println( last_temp.f_float ); Serial.print( "port.int to: " ); Serial.println( port.f_int ); }
void loop() { }
|
|
Gibas11 |
» 2017-02-04 14:04:24 Nie jestem pewny czy dobrze rozumiem, ale chodzi Ci po prostu o różnicę między adresem jakiegoś pola a początkiem obiektu/struktury? Jeśli tak to nie wystarczy ten kod? long offset_of( char * object, char * field ) { return field - object; } |
|
kamil2234 Temat założony przez niniejszego użytkownika |
» 2017-02-04 18:24:12 Jak wywołać tą funkcję? Co się wyliczy jako wartość różnicy? Nie kumam tego. |
|
« 1 » 2 |