logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Rozwiązano] Różnice w działaniu kodu AVR - obsługa przycisków i migające diody

piwniczne 05 Maj 2019 10:25 948 10
  • #1 17943641
    piwniczne
    Poziom 9  
    Hej,

    mam kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zgodnie z nim, mam obecną wersję, gdzie sprawdzam button podając jego dane.
    Chciałbym to zmienić na mechanizm: rejestrujesz Button, a potem sprawdzasz go po ID.

    Natomiast nowa wersja (po ID) nie działa poprawnie:
    Gdy zmienię (na ten moment) fragment // 'should' be working but doesn't
    na aktywny, płytka zachowuje się tak, jakby przycisk był ciągle wciśnięty.
    Z tego co rozumiem, przy tym kodzie nie powinno być różnicy działania, z czego ona wynika?

    Dzięki
  • #2 17943877
    chudybyk
    Poziom 31  
    Zasadniczo, to trudno się połapać w kodzie o co w nim chodzi, ale pierwszy i pewnie najważniejszy problem: czy pinOfButton w strukturze Button nie powinien być wskaźnikiem do rejestru PINx? A jest zadeklarowany jako unsigned char.
  • #3 17945708
    LED5W
    Poziom 34  
    W pierwszym przypadku odczytujesz stan wejść przy sprawdzeniu bit_is_clear. W drugim przypadku podczas wywołania setButton, i przekazujesz odczytaną wartość. Musisz przekazać adres przez wskaźnik ze słowem volatile.
  • #4 17945743
    piwniczne
    Poziom 9  
    LED5W napisał:
    W pierwszym przypadku odczytujesz stan wejść przy sprawdzeniu bit_is_clear. W drugim przypadku podczas wywołania setButton, i przekazujesz odczytaną wartość. Musisz przekazać adres przez wskaźnik ze słowem volatile.


    setButton: Wydaje mi się, że on jedynie zapisuje informację o tym gdzie znajduje się button, a sprawdzenie nadal ma się odbyć dopiero w bit_is_clear?


    Co do typu, z tutoriala był to unsigned char więc tak zostawiłem.
    Jeżeli to błąd to proszę o wyjaśnienie, dopiero poznaje świat uC

    Dzięki za odpowiedzi
  • Pomocny post
    #5 17946510
    szelus
    Poziom 34  
    piwniczne napisał:
    LED5W napisał:
    W pierwszym przypadku odczytujesz stan wejść przy sprawdzeniu bit_is_clear. W drugim przypadku podczas wywołania setButton, i przekazujesz odczytaną wartość. Musisz przekazać adres przez wskaźnik ze słowem volatile.


    setButton: wydaje mi sie, ze on jedynie zapisuje informacje o tym gdzie znajduje sie button a sprawdzenie nadal ma sie odbyc dopiero w bit_is_clear?


    Co do typu, z tutoriala był to unsogned char wiec tak zostawiłem.

    LED5W słusznie spostrzegł, tylko może trochę zbyt skrótowo to opisał.
    Wyrażenie PINx w AVR zwraca wartość typu uint8_t / unsigned char, ale nie jest taką wartością (hint: to jest makro). Jeżeli podajesz PINx jako argument funkcji setButton, która przyjmuje argument typu unsigned char, to wbudowany w język C mechanizm dopasowania typów wymusza w tym momencie odczyt portu i przekazanie odczytanej wartości do funkcji.
    Polecam zapoznać się z tym i z tym.
  • Pomocny post
    #6 17947581
    LED5W
    Poziom 34  
    piwniczne napisał:
    setButton: wydaje mi sie, ze on jedynie zapisuje informacje o tym gdzie znajduje sie button a sprawdzenie nadal ma sie odbyc dopiero w bit_is_clear?
    Funkcja setButton zapisuje to co jej przekazujesz, a przekazujesz wartość odczytaną z wejść.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    W pierwszym przypadku odczytywana jest wartość zmiennej c i kopiowana do argumentu funkcji foo. Funkcje działają na kopii, więc nawet, jeśli wartość c się zmieni podczas wykonywania foo, ta funkcja nic o tym nie będzie wiedzieć.
    W drugim przypadku kopiowany jest wskaźnik. Działa to tak samo - wartość wskaźnika (czyli adres) się nie zmienia, ale wartość na którą wskazuje może się zmienić.
    Oczywiście funkcja foo dla tych dwóch przypadków powinna być inaczej zadeklarowana. Odpowiednio:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    W przeciwnym razie nastąpi rzutowanie lub kompilator zgłosi błąd.
  • #7 17947805
    piwniczne
    Poziom 9  
    dzieki za odpowiedzi,
    na spokojnie sprawdzę kod i poprawię.

    Co do poszczególnych fragmentów:

    LED5W
    Cytat:
    W pierwszym przypadku odczytywana jest wartość zmiennej c i kopiowana do argumentu funkcji foo. Funkcje działają na kopii, więc nawet, jeśli wartość c się zmieni podczas wykonywania foo, ta funkcja nic o tym nie będzie wiedzieć.
    W drugim przypadku kopiowany jest wskaźnik. Działa to tak samo - wartość wskaźnika (czyli adres) się nie zmienia, ale wartość na którą wskazuje może się zmienić.
    Oczywiście funkcja foo dla tych dwóch przypadków powinna być inaczej zadeklarowana. Odpowiednio:


    Sama kwestia kopiowania/ref/wskaźnika jako mechanizm C++ raczej rozumiem i nie wskazywała ona na problem.

    Zakładałem, ze w zmiennej char jest tak naprawdę adres pamięci (jednobajtowy), wiec kopiowanie adresu niczego nie zmieni.
    To też wysłanie go do funkcji/structury przez kopię nie będzie problemem, ponieważ nadal odwoływac się będziemy do tego samego miejsca.
    W C++ to przecież standard i póki nie chcemy modyfikować samego adresu to nie wysyłamy wskaźnika na wskaźnik ani ref na wskaźnik (w sumie to samo...).


    Więc sama semantyka (kopiowania, referencji, wskaźnika) nie wydawała mi się problemem.

    zgodnie z tym co rozumiałem:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    więc cały czas zmienna, która jest argumentem w tych makrach, jest wskaźnikiem. To też jej kopiowanie nie powinno być problemem.
    Dlatego kod setButton powinien zapisać kopię adresu, a ta kopia potem użyta powinna w pełni działać.
    Tak bym to rozumiał, gdyby to był zwykły wskaźnik w C++.
    Tutaj natomiast w trakcie kopiowania tego chara (który, z tego co rozumiem jest adresem), coś przestaje działać. Mimo, że zgodnie z moją wiedzą, powinien on ciągle wskazywać na ten sam adres.

    Więc może problemem nie jest kwestia kopii/wskaźnika, a optymalizacji/volatile?

    szelus
    Cytat:
    Wyrażenie PINx w AVR zwraca wartość typu uint8_t / unsigned char, ale nie jest taką wartością (hint: to jest makro). Jeżeli podajesz PINx jako argument funkcji setButton, która przyjmuje argument typu unsigned char, to wbudowany w język C mechanizm dopasowania typów wymusza w tym momencie odczyt portu i przekazanie odczytanej wartości do funkcji.

    AAAA czekaj proszę, bo ja nie wiem czy dobrze zrozumiałem.

    PINx to makro, które jest przez preprocessor zamieniane na wartość typu uint8_t (unsigned char). Zakładam, że jest to adres pamięci, powiedzmy "10", w miejscu którego wartość jest bajt 0b00000000.

    I tutaj jest dla mnie magia, więc to powtórzę:
    Cytat:
    Jeżeli podajesz PINx jako argument funkcji setButton, która przyjmuje argument typu unsigned char, to wbudowany w język C mechanizm dopasowania typów wymusza w tym momencie *odczyt portu* i przekazanie odczytanej wartości do funkcji.


    czyli, że argument setButton, nie odbierze adresu "10", tylko wartość 0b00000000?
    Dobrze to rozumiem? Moższ coś więcej powiedzieć o tym mechaniźmie?
  • Pomocny post
    #8 17947843
    szelus
    Poziom 34  
    Nie wniknąłeś w to, co porzuciłem w drugim linku. PINx jest wyłuskaniem spod adresu, a nie adresem. Makra są za sprytne.
  • #9 17947855
    piwniczne
    Poziom 9  
    Tak, jestem w pracy, nie mogłem dokłądnie tego przejrzeć, zakładam, że po pracy siądę do materiałów i kodu. Teraz chciałem jedynie odpisać na to co koledzy napisali.

    Cytat:
    PINx jest wyłuskaniem spod adresu, a nie adresem. Makra są za sprytne.

    Faktycznie, to wszystko zmienia. Rozmowa o kopii/referencji nabiera także sensu.
    Dzięki.
  • #10 17949530
    LED5W
    Poziom 34  
    PINB możesz traktować jak zwykłą zmienną. Stąd przykłady, które podałem.
    Makro po rozwinięciu daje coś takiego
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    Czyli wartość 0x36 jest traktowana jako wartość wskaźnika. Operator wyłuskania daje dostęp do wartości typu volatile uint8_t.
    Kod wygląda na C. W C++ funkcje obsługujące przycisk raczej powinny być metodami klasy Button.
  • #11 18532510
    piwniczne
    Poziom 9  
    Koledzy wyżej mają rację, zamykam temat, dzięki.
REKLAMA