Skocz do zawartości

Struktury volatile w przerwaniu


Krawi92

Pomocna odpowiedź

Chcę pierwszy raz użyć struktury. I tak, mam np: 2 zmienne pwm1,pwm2 jako programowe kanały i napędzam je w przerwaniu. Wiem, że jeśli zmienną uzywamy pętli głównej i w przerwaniu to trzeba ja opatrzec specyfikatorem volatile. I pytanie odnośnie struktur, jak to robić? 

struct {
  volatile uint8_t pwm1;
  volatile uint8_t pwm2;
}wiatrak;

Czy to jest poprawne ? Pytam, bo w mojej książce są omówione tylko podstawy struktury, jak definiować itp. 

Link do komentarza
Share on other sites

Tak ten sposob jest poprawny...mozna z tego co wiem rowniez zapisac to tak..

wiatrak volatile Wiatrak;

Wtedy dana struktura w calosci jest volatile..czyli kazdy jej element, ale co do tego sposobu to juz niech sie wypowiedza Ci co uzywali, bo mi sie to tylko o oczy obilo...

Link do komentarza
Share on other sites

Zapisuj sobie strukture tak jak ponizej...nie bedziesz musial wszedzie dopisywac slowa "struct"...poprostu tworzysz nowy typ... 

typedef struct {
  volatile uint8_t pwm1;
  volatile uint8_t pwm2;
}wiatrak;

wiatrak mojaS;

mojaS.pwm1
mojaS.pwm2

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

14 godzin temu, farmaceuta napisał:

nie bedziesz musial wszedzie dopisywac slowa "struct"

@farmaceuta co masz na myśli?

@Krawi92 dopóki nie używasz we wnętrzu struktury wskaźników będzie ok. Przy okazji dobrą prraktyką jest dopisywanie _t do nazw dodanych typów danych, bo wiatrak wygląda bardziej na zmienną niż na typ danych 😉 

typedef struct {
  uint8_t pwm1;
  uint8_t pwm2;
} wiatrak_t;

volatile wiatrak_t wiaatrak;

Ewentualnie użyj wersji z C++

struct wiatrak_t{
  uint8_t pwm1;
  uint8_t pwm2;
};

I wtedy możesz sobie poszaleć ze składnią:

struct wiatrak_t{
  uint8_t pwm1;
  uint8_t pwm2;
} volatile wiatrak = {128, 128};

 

Link do komentarza
Share on other sites

13 minut temu, Gieneq napisał:

@farmaceuta co masz na myśli?

Pamietam ze jak zaczalem sie interesowac strukturami to Ja odrazu zaczalem pisac w taki sposob...

typedef struct costam

Ale spotkalem sie tez z...

struct costam

I zaczalem wnikac w czym roznica...wiem ze w wielu miejscach ludzi pisali ze w drugiej opcji trzeba bedzie dopisywac slowo struct, ale nie pamietam juz gdzie...czy przed typem, a moze w przypadku uzycia tej struktury jako argument funkcji? No wiem ze cos w tym musi byc bo wiele razy z tym sie spotkalem...spruboje znalezdz...jak cos to mnie prostuj😉

Link do komentarza
Share on other sites

Chodzilo mi chyba o cos takiego...(cytat z innego forum)

..."Jeśli właśnie powiedziałeś:

struct Foo { 
  ...
}; 
Foo x;

otrzymasz błąd kompilatora, ponieważ Foo jest on zdefiniowany tylko w przestrzeni nazw znaczników.

Trzeba by to zadeklarować jako:

struct Foo x;

Za każdym razem, gdy chcesz odwołać się do Foo, zawsze musisz nazwać to struct Foo . To szybko się denerwuje, więc możesz dodać typedef:

struct Foo { 
  ...
};
typedef struct Foo Foo;

Teraz struct Foo(w przestrzeni nazw znaczników) i po prostu Foo(w przestrzeni nazw zwykłego identyfikatora) oba odnoszą się do tej samej rzeczy i można swobodnie deklarować obiekty typu Foo bez struct słowa kluczowego.

Konstrukt:

typedef struct Foo { 
  ... 
} Foo;

to tylko skrót od deklaracji i typedef .

Wreszcie,

typedef struct { 
  ... 
} Foo;

deklaruje anonimową strukturę i tworzy typedef dla niej....."

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

To teraz parę pytań odnośnie struktur, bo wczoraj w sumie metodą prób i błędów ja tworzyłem i kilka rzeczy jest nie do końca jasnych, albo inne źle rozumiem. Od początku. Zacząłem tworzyć strukturę w pliku main.c i ok, ale pomyślałem, że po co ona tam, więc spróbowałem ją przenieść do pwm.c jednak tam kompilator krzyczał o niezdefiniowanych zmiennych itp. Więc umieściłem ją w pliku nagłówkowym pwm.h. I teraz moje pytanie odnośnie widoczności takich zmiennych. Bo gdy np: stworze zmienne w pliku pwm.c,a będę chciał również się do nich odwoływać w pliku main.c to muszę je zadeklarować w pliku nagłówkowym pwm.h i opatrzec specyfikatorem extern, żeby były widoczne w innych modułach. A tworząc zmienne w strukturze nie musiałem nic takiego robić, a wszystko było widoczne,w pliku main.c i pwm.c 

Link do komentarza
Share on other sites

Dnia 18.09.2021 o 18:42, Krawi92 napisał:

I teraz moje pytanie odnośnie widoczności takich zmiennych.

@Krawi92 tu musisz wyjść od znajomości pojęć deklaracja i definicja. Deklaracja jest takim wstępem do utworzenia czegoś, np. plik .h ma prototypy/deklaracje funkcji. Może też mieć deklarację zmiennej - czyli poinformowanie co to za zwierz ale nie wiemy jeszcze jakiego koloru i gdzie gniazduje 🙂 Deklarację możesz skojarzyć z deklaracjami wyborczymi czy czymś raczej niespełnionym 😅 

Jeżeli napiszesz sobie w pliku:

int zmienna;

To masz deklaracje i definicję. Jak to? Jest to zmienna globalna, której dane trafiają do obszaru pamięci statycznej i domyślnie są inicjowane 0.

Jak napiszesz:

// .h
extern int zmienna;

To jest to sama deklaracja - mówisz niejako: zmiennajest typu int i jest zdefiniowana gdzieś indziej.

Wiec w pliku .c spełniasz to życzenie i tam definiujesz zmienną:

// .c
int zmienna = 5;

A jakby korciło Cię upiec 2 pieczenie na jednym ogniu:

// .h
extern int zmienna = 6;

To się to źle skończy, bo kompilator uprości to do definicji zmiennej,

  • Lubię! 2
Link do komentarza
Share on other sites

1 godzinę temu, Gieneq napisał:

Deklaracja jest takim wstępem do utworzenia czegoś

Chyba raczej na odwrót, jeśli się nie mylę. Deklaracja jest wtórna do definicji, to jest taka "zapowiedź", że "gdzieś" istnieje ciało funkcji. Deklaracja bez ciała (w ostatecznym rozrachunku) nie ma sensu.

Trochę filozofuję, ale dobrze jest poprawnie definiować zależności między tymi pojęciami

Link do komentarza
Share on other sites

26 minut temu, Gieneq napisał:

czy nie tak?

Co oznacza w tym przykładzie "obiekt". Definicji i deklaracji funkcji nie można przekładać 1:1 do zmiennej.

Gdy zmienną tylko zadeklarujesz to możesz jej użyć w uruchomionym programie, nadać wartość, zainicjować. Deklaracja funkcji jest bezużyteczna jeśli nie jest powiązana z ciałem funkcji na etapie kompilacji. Tak mi przychodzi na szybko różnica dla obu "tworów", ale mogę się mylić, nie upieram się, porządkuję wiedzę.

Edytowano przez Zealota
Link do komentarza
Share on other sites

Jeśli zmienna jest tylko zadeklarowana, ale nie została zdefiniowana, to możesz ją użyć w programie, który ze swej istoty jest też tyko deklaracją, ale już wykonanie nie jest możliwe. To trochę tak jak pisanie listu do Świętego Mikołaja, obiekt zadeklarowany, (wszyscy wiedzą kto to) ale nie "ukonkretniony" (przez ostatnie kilka setek lat nikt go nie spotkał).

Link do komentarza
Share on other sites

@Zealota obiekt tyczy się typów prostych, typów dodanych w tym struktur i najpewniej instancji klas.

Faktycznie jest pewna różnica jak porówna się tę terminologię dla zmiennych i funkcji. Zmienne zazwyczaj są definiowane (czyli to bardziej złożone pojęcie), bo dostają adres w pamięci i domyślną wartość. Jeżeli piszemy o tym externie to oznacza, że zmienna jest zadeklarowana czyli mamy informację dla linkera, że poszukaj sobie zmiennej o takiej nazwie i przyporządkuj jej adres, stąd: extern może być użyty wiele razy, czyli wiele razy definiujesz, ale tylko raz możesz zadeklarować zmienną. 

extern int aww;
extern int aww;
extern int aww;
int aww = 6;
int aww = 1; // błąd!

Oczywiście nie piszemy tego przykładu jawnie w kodzie linia pod linią, to tylko sekwencja wystąpień.

Z funkcjami jest podobnie:

void meh(int);

void setup(){
  Serial.gebin(9600);
  meh(2);
};

void loop(){}

void meh(int counter) {
  Serial.println(counter);
}

Mamy tu funkcję meh, która jest zadeklarowana (zadeklarowaliśmy wyborcom, że jak nas wybiorą to zdefiniujemy im konkrety dotyczące funkcji). W deklaracji mamy mniej informacji, tylko tyle żeby linker połapał się co gdzie jest - wzmianka o typie argumentów najpewniej jest po to, aby dało się przeciążyć funkcję a linker nie zgłupiał.

W definicji definiujemy ciało funkcji.

@Krawi92 jeżeli dodasz deklarację struktury w pliku .h to będzie widoczna tam gdzie załadujesz ten plik .h. Żeby ukryć coś jest pewnie wiele metod, ale możesz zrobić tak:

// plik .h

struct some_t;

Teraz w pliku skojarzonym z tym modułem dodajesz deklarację tego typu (stosując terminologię z funkcji deklarujesz ciało struktury), to jest notacja z c++:

// .cpp
 struct some_t {
   int some_x;
   int some_y;
 };

i teraz jak sobie załadujesz ten plik .h np do main.cpp to zobaczysz typ ale nie skompiluje się:

image.thumb.png.d57cf69a6b3d3c8cb609c18ffb89404e.png

Bo na tym etapie nie wiadomo co to jest.

Ale jeżeli w ogóle wyrzucisz to z pliku .h to możesz cieszyć się kodem w pliku .cpp, nikt nie broni trzymać kodu w pliku .cpp, bo po co dodawać w pliku .h coś co ma być widoczne tylko w module cpp?

Edytowano przez Gieneq
  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.