Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 5 gru 2025, o 18:47


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 15 ] 
Autor Wiadomość
PostNapisane: 10 sie 2016, o 09:09 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

Witam

Chciałbym zapytać jak poprawnie przekazać adres początku struktury Bufor1 i Bufor2 do procedury.

Kod:
typedef struct {
   int8 A;                 
   int8 B;               
   int8 C;                   
}TBufor;
TBufor Bufor1, Bufor2;         


main {

   EE_Zapisz(0, &Bufor1, 3);

}

void EE_Zapisz(int8 AdresEE, int8 *AdresBUF, Int8 IloscDanych)
  {
    while (IloscDanych--) EE_Write(AdresEE++,*AdresBUF++);
  }



Przy kompilacji kodu z fragmentem jak wyżej wszystko się kompiluje i działa jednak kompilator daje ostrzeżenie "Undefined Identifier Bufor1" "Undefined Identifier Bufor2". Oczywiście mogę przekazać adres pierwszej danej w strukturze np: "EE_Zapisz(0, &Bufor1.A, 3);" i wtedy już nie ma ostrzeżenia.

W jaki sposób przekazać poprawnie adres struktury używając tylko nazw struktur czyli "Bufor1" "Bufor2".



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 09:20 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

A dlaczego masz zadeklarowane:
zbynex napisał(a):
void EE_Zapisz(int8 AdresEE, int8 *AdresBUF, Int8 IloscDanych)

zamiast np.:
void EE_Zapisz(int8 AdresEE, TBufor *AdresBUF, Int8 IloscDanych)
???

Kompilator oczekuje wskaźnika na int8, a Ty wywołujesz funkcję podając wskaźnik na strukturę:
EE_Zapisz(0, &Bufor1, 3);



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 09:26 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

No faktycznie masz rację ale od razu wynikł kolejny problem mianowicie do procedury "EE_Zapisz" potrzebuję przekazywać adres różnych struktur o różnym rozmiarze.

Przykładowo coś w tym stylu:

Kod:
typedef struct {
   int8 A;                 
   int8 B;               
   int8 C;                   
}TBufor;
TBufor Bufor1, Bufor2;         

typedef struct {
   int8 A;                 
   int8 B;                       
}TBuforek;
TBuforek Buforek1, Buforek2, Buforek3;   

main {

   EE_Zapisz(0, &Bufor1, 3);
   EE_Zapisz(20, &Buforek3, 2);

}

void EE_Zapisz(int8 AdresEE, int8 *AdresBUF, Int8 IloscDanych)
  {
    while (IloscDanych--) EE_Write(AdresEE++,*AdresBUF++);
  }


Jak to inaczej zapisać aby procedura " EE_Zapisz" była uniwersalna tak aby w dowolnym momencie można zapisać dowolną zawartość struktury do EEprom. Dodam że w/w zapis działa prawidłowo poza warningiem kompilatora



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 09:40 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

zbynex napisał(a):
Jak to inaczej zapisać aby procedura " EE_Zapisz" była uniwersalna. Dodam że w/w zapis działa prawidłowo poza warningiem kompilatora

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 09:46 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

@squeez nie to jest problemem.

@andrews bingo o to chodziło ale pojawiły się nowe alerty.

Wielkie dzięki za dotychczasową pomoc.


Teraz jeszcze mi daje ten alert na wskażnikach *AdresBUF++ "Pointer types do not math" w procedurach :

Kod:
void EE_Zapisz(int8 AdresEE, void *AdresBUF, Int8 IloscDanych) {
    while (IloscDanych--) EE_Write(AdresEE++,*AdresBUF++);
}

void EE_Czytaj(int8 AdresEE, void *AdresBUF, Int8 IloscDanych) {
    while (IloscDanych--) *AdresBUF++ = EE_Read(AdresEE++);
}



Przykładowy kod wygląda teraz tak:
Kod:
typedef struct {
   int8 A;                 
   int8 B;               
   int16 C;                   
}TBufor;
TBufor Bufor1, Bufor2;         

typedef struct {
   int16 A;                 
   int8 B;                       
}TBuforek;
TBuforek Buforek1, Buforek2, Buforek3;

void EE_Zapisz(int8 AdresEE, void *AdresBUF, Int8 IloscDanych) {
    while (IloscDanych--) EE_Write(AdresEE++,*AdresBUF++);
}

void EE_Czytaj(int8 AdresEE, void *AdresBUF, Int8 IloscDanych) {
    while (IloscDanych--) *AdresBUF++ = EE_Read(AdresEE++);
}

main {

   // Zapis
   EE_Zapisz(0, (void*)&Bufor1, sizeof(TBufor));
   EE_Zapisz(10, (void*)&Buforek1, sizeof(TBuforek));

   // Odczyt
   EE_Czytaj(0, (void*)&Bufor1, sizeof(TBufor));
   EE_Czytaj(10, (void*)&Buforek1, sizeof(TBuforek));

}




Jak to teraz prawidłowo zmodyfikować aby było poprawnie bez warningów "Pointer types do not math".
Już się zaczynam zastanawiać czy to nie błąd kompilatora bo na 2 starszych wersjach nie ma warningów.



Ostatnio edytowano 10 sie 2016, o 14:43 przez zbynex, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 14:31 
Offline
Użytkownik

Dołączył(a): 25 lip 2015
Posty: 140
Zbananowany użytkownik

Pomógł: 18

Kompilator dobrze sugeruje, że typ który masz, czyli void* nie obsługuje arytmetyki wskaźników.

Po za tym struktura, to nie tablica. Skąd pewność, że poszczególne pola zostaną ułożone w pamięci jeden za drugim?

Skoro chcesz zapisywać struktury, to napisz funkcję, która jako argument dostaje wskaźnik na strukturę, i zapisuje poszczególne jej pola, a nie jakieś rzutowanie. Więc albo zastosuj zmienną tablicową, albo napisz dwie funkcje obsługujące dwie różne struktury.



Ostatnio edytowano 10 sie 2016, o 14:40 przez Sparrow-hawk, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 14:35 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

@Sparrow-hawk a mógłbyś napisać jakiś kawałek kodu jak to widzisz w swoim rozwiązaniu ?

Nie wiem czy dobrze zrozumiałem ale z twojej propozycji wynika że do każdej definicji struktury musiałbym pisać taką funkcję bo struktury są w różnym rozmiarze i różne typy zmiennych przechowują.

Powyższy kod jest tylko przykładowym aby przedstawić o co mi chodzi.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 14:45 
Offline
Użytkownik

Dołączył(a): 25 lip 2015
Posty: 140
Zbananowany użytkownik

Pomógł: 18

zbynex napisał(a):
ale z twojej propozycji wynika że do każdej definicji struktury musiałbym pisać taką funkcję

Tak dokładnie, tak ;) I jak tak to widzę.

Chyba, że przechowujesz dane tylko jednego typu, wtedy lepiej użyć będzie tablicy. Jeżeli ilość danych w tej tablicy będzie zmienna, to musisz albo przechowywać ten rozmiar np. w 0 komórce tablicy, albo tworzysz strukturę zawierającą tablicę i w drugiej zmiennej rozmiar tej tablicy.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 15:03 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

Pisanie funkcji do każdej struktury nie wchodzi w grę. Brak ROM :). Każda komórka jest już na wagę złota :)
W sumie ze zmianą typu zmienny na int8 nie będzie problemu.
Może to i będzie najlepsze rozwiązanie założyć kilka tablic int8 o różnym rozmiarze. Zapis tablicy to już nie problem zwłaszcza że rozmiar każdej będzie stały.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2016, o 17:27 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

zbynex napisał(a):
Jak to teraz prawidłowo zmodyfikować aby było poprawnie bez warningów "Pointer types do not math".

Nie byłoby problemu, gdybyś korzystał ze standardowych funkcji zapisu/odczytu do EEPROM:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Te funkcje akceptują właśnie wskaźniki typu void.

Poza tym zamiast używać liczbowych wskaźników proponowałbym deklarować dane w EEPROM za pomocą makra EEMEM:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


PS.
A gdybyś koniecznie chciał napisać własną funkcję, to wystarczy wewnątrz funkcji rzutować wskaźnik na dowolny wskaźnik do typu ośmiobitowego, np.:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Kolejność danych czy też ich rozmieszczenie nie są problemem, bo będą takie same jak w RAM, więc odwołanie &Bufor1_ee.B będzie wskazywało na ten sam element struktury co odwołanie &Bufor1_ram.B Tak samo działają funkcje standardowych bibliotek Atmela eeprom_read_block() i eeprom_read_block() służące właśnie do zapisu struktur i tablic - kopiują dane z RAM do EEPROM bajt bo bajcie w tej samej kolejności. Tak samo działa też np. funkcja standardowa memcpy() do kopiowania bloków danych z RAM do RAM (która również operuje na wskaźnikach void*). Nie trzeba pisać osobnych funkcji dla każdego typu zmiennej. Mankamentem jest tylko to, że nie ma pełnej kontroli nad typami danych i trzeba uważać, by podać właściwy rozmiar danych do skopiowania.

EDIT (11.08.2016 10:15):
Dodam jeszcze jedną ważną uwagę. Zwykle w mikrokontrolerach o niewielkich zasobach struktury są pakowane (np. avr-gcc ma opcję '-fpack-struct'), jednak jak słusznie zauważył kolega Sparrow-hawk ogólnie (w przypadku niepakowanych struktur) może się zdarzyć, że struktura będzie zawierać tzw. "padding bytes" (nie będę się tutaj wdawał w szczegóły). W takim przypadku struktura będzie miała rozmiar inny, niż by to wynikało ze zsumowania rozmiarów wszystkich jej elementów. Dlatego istotne jest, aby rozmiar struktury wyznaczać za pomocą operatora rozmiaru sizeof, a nie na podstawie własnych obliczeń.


Autor postu otrzymał pochwałę


Ostatnio edytowano 11 sie 2016, o 09:16 przez andrews, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 sie 2016, o 06:22 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

@andrews faktycznie rzutowanie wskaźnika na zmienną typu int8 wewnątrz procedury zapisu i odczytu rozwiązało problem warningów.

Mam tylko nadzieję że kompilator zawsze adresuje dane ze struktury obok siebie. Kolejność jeżeli pozamienia nie ma znaczenia ważne aby dane struktury były w jednym bloku. Na chwilę obecną wygląda że wszystkie struktury są w kupie.

Niestety funkcji zapisu i odczytu bloku nie mogę użyć bo to kompilator na PIC CCS dlatego piszę własne funkcje i jeszcze dodatkowo dane zapisywane są w wewnętrznym eeprom i zewnętrznym I2C

Problem został rozwiązany w 100%.

Jeszcze raz dzięki bo pomoc tutaj jest bezcenna.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 sie 2016, o 06:45 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

zbynex napisał(a):
Niestety funkcji zapisu i odczytu bloku nie mogę użyć bo to kompilator na PIC CCS
Nie sprecyzowałeś tego wcześniej, a wątek umieściłeś w dziale "Język C dla AVR", stąd moje odniesienia do avr-libc.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 sie 2016, o 08:10 
Offline
Nowy

Dołączył(a): 22 wrz 2015
Posty: 24
Pomógł: 0

@andrews i bardzo cieszę się że rozwinąłeś szerzej wątek.
Nie pisałem że chodzi o PIC bo w takich sytuacjach zaraz jest dziesięć postów typu to nie to forum nie ten kompilator itp, a jeden post na temat problemu. Problem dotyczył ogólnie języka C a nie platformy na jaką jest pisany kod.

Moje procedury EE_Czytaj i EE_Zapisz realizują to samo co eeprom_write_block i eeprom_read_block dla AVR.

Dzięki, bardzo mi pomogłeś. Pozdrawiam.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 sie 2016, o 09:31 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Ja nie mam pretensji, ja się tylko chciałem wytłumaczyć :)

zbynex napisał(a):
Nie pisałem że chodzi o PIC bo w takich sytuacjach zaraz jest dziesięć postów typu to nie to forum nie ten kompilator itp, a jeden post na temat problemu. Problem dotyczył ogólnie języka C a nie platformy na jaką jest pisany kod.

Niemniej zestaw pewnych funkcji standardowych/wbudowanych jest zależny od platformy/kompilatora/toolchain'u, więc mimo wszystko łatwiej pomóc wiedząc na jaki mikrokontroler się pisze.

Zwróć proszę jeszcze raz uwagę na mój post powyżej, ponieważ dopisałem jedną ważną informację.

Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 sie 2016, o 10:12 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27445
Lokalizacja: Szczecin
Pomógł: 1045

andrews napisał(a):
więc mimo wszystko łatwiej pomóc wiedząc na jaki mikrokontroler się pisze

ZDECYDOWANIE ... więc takie stwierdzenia

zbynex napisał(a):
Nie pisałem że chodzi o PIC bo w takich sytuacjach zaraz jest dziesięć postów typu to nie to forum nie ten kompilator itp,

... rzekłbym na tym forum, są hmmm no nie na miejscu. Gdzie kolega spotkał się u nas z takimi sytuacjami "dzięsięciu" postów ?

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 15 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO