Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Obsługa lcd z przerwania i main

28 Maj 2017 12:55 1203 11
  • Poziom 11  
    Witam

    Znów mam pytanie dotyczące kodu który pozwala na współbieżną obsługe lcd z main i przerwania

    przedstawiam tylko plik .c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    kod jest łatwy w czytaniu jednak nie bardzo rozumiem tego zapisu
    Kod: c
    Zaloguj się, aby zobaczyć kod

    po co dodajemy 2?
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    Rezerwujesz pamięć na stercie na strukturę LCD_trans - ponieważ zawiera ona pole o wielkości dynamicznie zmienianej, więc musisz zarezerwować miejsce na samą strukturę oraz długość przechowywanego w niej tekstu.
  • Specjalista - Mikrokontrolery
    Jeden dodaje się po to, żeby zmieścił się bajt końca łańcucha. Po co 2 - nie wiem. Ja bym raczej zapytał, po co ta dynamiczna alokacja, gdy dokładnie wiadomo, ile znaków mieści się na wyświetlaczu.
    Parę innych rzeczy w tym kodzie też jest dziwacznych.
  • Poziom 11  
    Dynamiczna alokacja jest po to aby na sztywno nie rezerwować całego obszaru LCD tylko w zależności od potrzeb, jak ci się nie podoba rezerwacja dynamiczna powołaj tablice jako globalna i przekazuj funkcji. Ja nie narzekam na kod wszystko się fajnie analizuje.

    Dodano po 56 [sekundy]:

    czyli jak dam +1 to też zadziała?

    Dodano po 15 [minuty]:

    A jeszcze jedna sprawa czy linia która sprawdza czy już zakończyliśmy wysyłać bufor tj.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    czy jest poprawna przecież seq.pos idzie od 0 .A w kodzie len inicjalizujemy tak
    Kod: c
    Zaloguj się, aby zobaczyć kod

    co daje długość tekstu do której dodajemy 1 według mnie powinno być bez tego +1 bo i tak seq.pos liczy od zera czyli np. jak tekst ma trzy znaki to seq.pos przyjmuje takie wartości 0,1,2,3 czyli 4 indeksy bufora oblecimy, 3 tekst + 1pozycja, a dodając jeden to według mnie ale nie sprawdzałem jeszcze ostatni znak może być dziwny.
  • Specjalista - Mikrokontrolery
    Dynamiczna alokacja w tym przypadku to:
    - min. 4 dodatkowe bajty pamięci RAM przy każdej alokacji
    - zbędny narzut czasu na alokację i dealokację
    - zbędna zajętość pamięci ROM na procedury alokacji i dealokacji
    - niebezpieczeństwo wycieków w przypadku błędów w programie

    Wyświetlacz ma stały rozmiar, np. 2 x 16 znaków. Wystarczy jeden raz zadeklarować strukturę danych zawierającą miejsce na zawartość wyświetlacza. Zwróć uwagę, że jeśli masz na wyświetlaczu np. całą linijkę 16 znaków, to żeby ją zmienić na krótszy komunikat, musisz wyświetlić słowo komunikatu i dalej spacje - do 16 znaków. Dlatego najprostsza i najszybsza obsługa wyświetlacza polega na zapisie do pamięci całej zawartości wyświetlacza, a następnie wywołania aktualizacji całego wyświetlacza (np. przy użyciu przerwania timera). nie ma sensu pisanei "po kawałku" - zajmuje więcej czasu i wymaga dodatkowych poleceń.
  • Poziom 21  
    Funkcja "strlen" nie podlicza znaku "newline" i chyba dlatego programm reserwuje 1 miejsce więcej.
  • Specjalista - Mikrokontrolery
    inot napisał:
    Funkcja "strlen" nie podlicza znaku "newline" i chyba dlatego programm reserwuje 1 miejsce więcej.


    To nie jest prawda.
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    squelch napisał:
    Dynamiczna alokacja jest po to aby na sztywno nie rezerwować całego obszaru LCD tylko w zależności od potrzeb, jak ci się nie podoba rezerwacja dynamiczna powołaj tablice jako globalna i przekazuj funkcji. Ja nie narzekam na kod wszystko się fajnie analizuje.

    Dodano po 56 [sekundy]:

    czyli jak dam +1 to też zadziała?

    Dodano po 15 [minuty]:

    A jeszcze jedna sprawa czy linia która sprawdza czy już zakończyliśmy wysyłać bufor tj.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    czy jest poprawna przecież seq.pos idzie od 0 .A w kodzie len inicjalizujemy tak
    Kod: c
    Zaloguj się, aby zobaczyć kod

    co daje długość tekstu do której dodajemy 1 według mnie powinno być bez tego +1 bo i tak seq.pos liczy od zera czyli np. jak tekst ma trzy znaki to seq.pos przyjmuje takie wartości 0,1,2,3 czyli 4 indeksy bufora oblecimy, 3 tekst + 1pozycja, a dodając jeden to według mnie ale nie sprawdzałem jeszcze ostatni znak może być dziwny.


    +2 jest dlatego, że potrzebujemy jeden bajt na NUL i jeden bajt na pozycję wyświetlanego tekstu. Ponieważ data[0] zawiera pozycję (adres w GRAM), więc znaki są indeksowane od 1, a nie od 0.

    Dodano po 10 [minuty]:

    BlueDraco napisał:
    Dynamiczna alokacja w tym przypadku to:
    - min. 4 dodatkowe bajty pamięci RAM przy każdej alokacji
    - zbędny narzut czasu na alokację i dealokację
    - zbędna zajętość pamięci ROM na procedury alokacji i dealokacji
    - niebezpieczeństwo wycieków w przypadku błędów w programie


    Biorąc pod uwagę, że mamy kilka transakci max. to strata 4 bajtów/transakcję rzeczywiście poraża. Podobnie strata czasu - ile razy na sekundę piszemy na LCD?
    Poza tym nie zauważyłeś, że funkcje są napisane tak, że można użyć alokacji statycznej, jeśli to kogoś boli, co załatwia kolejne punkty.
    Niebezpieczeństwo wycieków, przy poprawnie napisanej aplikacji nie istnieje, równie dobrze możnaby napisać po co np. RTOS, przecież tyle pułapek się w nim czai...

    BlueDraco napisał:
    Wyświetlacz ma stały rozmiar, np. 2 x 16 znaków. Wystarczy jeden raz zadeklarować strukturę danych zawierającą miejsce na zawartość wyświetlacza. Zwróć uwagę, że jeśli masz na wyświetlaczu np. całą linijkę 16 znaków, to żeby ją zmienić na krótszy komunikat, musisz wyświetlić słowo komunikatu i dalej spacje - do 16 znaków. Dlatego najprostsza i najszybsza obsługa wyświetlacza polega na zapisie do pamięci całej zawartości wyświetlacza, a następnie wywołania aktualizacji całego wyświetlacza (np. przy użyciu przerwania timera). nie ma sensu pisanei "po kawałku" - zajmuje więcej czasu i wymaga dodatkowych poleceń.


    Nie do końca tak jest. Masz 80 bajtów GRAM, które musiałbyś zaalokować statycznie. Przy alokacji dynamicznej pamięć zajmowana jest tylko chwilowo, a same transakcje też zajmą jej mniej. Nic nie stoi na przeszkodzie, aby dodać obsługę dodatkowych poleceń, korzystając ze znaków o kodach 0-31 - np. wyczyść ekran lub linię. Przy LCD graficznych jest jeszcze gorzej jeśli chcielibyśmy stworzyć bufor. Oczywiście nie znaczy to, że istnieje tylko jedno rozwiązanie problemu. Podane kody są przykładami z książki mającymi ilustrować pewne techniki rozwiązywania problemów. Rozwiązanie ze stworzeniem pamięci shadow dla GRAM też jest pokazane.
  • Poziom 11  
    dzięki za odpowiedz i wyjaśnienie

    Cytat:
    Ponieważ data[0] zawiera pozycję (adres w GRAM), więc znaki są indeksowane od 1, a nie od 0.


    Tak jest istotnie indeks 0 jest odpowiedzialny za pobranie adresu z bufora jednak w takim razie zamiast >= wystarczy ==(ale to nnie ma najmniejszego znaczenia takie szczegóły)
    buf->len=strlen(txt) + 1; //Długość tekstu + pozycji + NULL - 1
    [/syntax]
    zarezerwuje 4 bajty(3 na tekst i 1 na pozycje)
    i kiedy wysyłamy po kolei tetrady transakcji do LCD to seq.pos przyjmuje następujące wartości
    0-wysyłamy pozycję
    1-wysyłamy a
    2-wysyłamy l
    3-wysyłamy a(wysłanie ostatniej tetrady zwiększy seq.pos o 1 czyli będzie równe 4)
    więc
    Kod: c
    Zaloguj się, aby zobaczyć kod

    jest poprawne ale wystarczyłoby tylko równy przy warunku
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 1 [godziny] 39 [minuty]:

    mam jeszcze jedno pytanie odnośnie main
    Kod: c
    Zaloguj się, aby zobaczyć kod

    while(strlen(bufstr)<6) strcat(bufstr, " "); dlaczego 6 przecież strlen(bufstr) da maks.5 dla 65536 a linia strcat(bufstr, " "); dla 65536 dopisze spacje do bufstr i nadpiszemy przypadkowo zero. Chyba powinno być 5

    Pozdrawiam
  • Moderator Mikrokontrolery Projektowanie
    Nic nie nadpisze. strlen zwraca długość łańcucha bez znaku NUL. Pętla uzupełnia łańcuch spacjami do maksymalnej długości 5 znaków - bufor jest na 6 znaków, także jest miejsce na NUL.
  • Poziom 11  
    Jak to przecież powiedzmy że dla 65500 strlen zwróci 5 jako że 5<6 to na pozycję indeksu 5 wpiszemy spację bo
    indeks 0-6
    indeks 1-5
    indeks 2-5
    indeks 3-0
    indeks 4-0
    indeks 5-spacja(ostatni)

    zmieniałem kod i dla 5 działa na LCD pokazuje liczbę 65500
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Możliwe że zaszedł tutaj fart i po tej tablicy leżało sobie 0

    Dodano po 1 [minuty]:

    dlatego dla 6 działało

    Dodano po 3 [minuty]:

    A jeszcze jedna kwestia o co chodzi z tym
    typedef enum {LCD_Text} LCD_Cmd; //Lista poleceń realizowanych przez sterownik
    jak tej komendy nigdzie nie wysyłamy po co ona jest?