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

[AVR][C] - Mnożenie elementów tablicy przez siebie.

xamrex 14 Lip 2011 21:15 4108 33
  • #1 9718980
    xamrex
    Poziom 28  
    Witam,
    Mam tablicę 32 elementową typu uint8_t,
    bufor[32];
    Zawierać ona będzie tylko 0 oraz 1

    Chcę teraz pododawać wszystkie jej wartości w odpowiedni sposób.
    Pierwszy element tablicy mnożę razy 1, drugi razy 2, trzeci razy 4, czwarty razy 8 itd..

    Ja napisałem to w taki sposób:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak to napisać poprawnie?
  • Pomocny post
    #2 9719000
    tmf
    VIP Zasłużony dla elektroda
    Skoro działa to jest to poprawne :) Chcesz to zamienić na pętlę, proszę:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Albo lepiej:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #3 9719012
    xamrex
    Poziom 28  
    tak już właśnie miałem zamier pisać posta, że chyba mi się udało, a widzę mnie uprzedziłeś.
    Masz tu błąd:
    Cytat:
    suma=suma+bufor[i]*i;

    Bo ma być
    suma=suma+bufor[i]*2^i
  • #4 9719023
    michalko12
    Specjalista - Mikrokontrolery
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    O to chodziło, czy coś źle zrozumiałem?
  • #5 9719041
    tmf
    VIP Zasłużony dla elektroda
    xamrex napisał:
    tak już właśnie miałem zamier pisać posta, że chyba mi się udało, a widzę mnie uprzedziłeś.
    Masz tu błąd:
    Cytat:
    suma=suma+bufor[i]*i;

    Bo ma być
    suma=suma+bufor[i]*2^i


    Tak, zauważyłem, że masz tam kolejne potęgi i poprawiłem. Przy czym ^ to nie operwator potęgowania tylko alternatywy rozłącznej :)

    Dodano po 42 [sekundy]:

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


    O to chodziło, czy coś źle zrozumiałem?


    Chcesz zarżnąć biednego AVRka :)
  • #6 9719057
    michalko12
    Specjalista - Mikrokontrolery
    Nie mysl
    tmf napisał:
    Chcesz zarżnąć biednego AVRka :)

    Nie myślę już na poziomie AVRów ;)
    W ARMie to jest jedna instrukcja asemblerowa
  • #7 9719170
    gaskoin
    Poziom 38  
    btw nie jestem pewien ale za pomocą przesunięcia bitowego w lewo << na AVR się chyba nie da otrzymać liczby 32 bitowej. Trzeba albo przesuwać w prawo albo inaczej cudować :)
  • #8 9719187
    michalko12
    Specjalista - Mikrokontrolery
    A to niby z jakiego powodu?
    To nie robota dla AVR tylko dla kompilatora.
    Faktem jest to co napisał TMF, że ta operacja na AVR jest trochę mało optymalna delikatnie mówiąc.
  • #9 9719241
    xamrex
    Poziom 28  
    To teraz pewnie polecą na mnie przekleństwa..
    Bo w mojej głowie zrodził się szatański pomysł.

    Mam taką matrycę:
    [AVR][C] - Mnożenie elementów tablicy przez siebie.

    [AVR][C] - Mnożenie elementów tablicy przez siebie.

    No i chcę napisać sobie funkcję, która będzie oświetlała dany 'pixel'
    Czyli np.
    oswiec(1,5)
    zaświeci 5 diodę w pierwszym rzędzie.
    (na razie nie ma tej funkcji jest tylko tablica)
    Do tego stworzyłem sobie tablicę (256 elementową) bo tyle mam diod.
    No i jeśli w tablicy jest 0 to nie świeci jeśli jest 1 to świeci.
    Powstał taki oto kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod działa (prawie),
    Gdyż nie świeci mi ostatnia dioda w ostatnim rzędzie.

    Problem pewnie leży tu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ale jak dam zamiast i<255 i<256, to na wyświetlaczu nie świeci żadna dioda ;((
    Jak to naprawić?

    Słyszałem, że przerwanie ma być możliwie jak najkrótsze a ja do niego upakowałem cała obsługę multipleksowania..
    Czy może to tak zostać, czy jest inna opcja zrobienia tego
  • #10 9719262
    michalko12
    Specjalista - Mikrokontrolery
    Żadnych ostrzeżeń kompilator nie generował?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #11 9719269
    gaskoin
    Poziom 38  
    Nie analizowałem kodu, ale:

    W Twoim przypadku jest OK, ale tylko i wyłącznie dlatego, że nie używasz innych przerwań ani nic nie robisz w pętli głównej.

    "Normalnie" robi się to tak, że w przerwaniu robisz: minelo1234342Sekund = 1; i nic więcej, a w pętli głównej co obieg sprawdzasz tą flagę i tam wrzucasz procedurę obsługi przerwania.
  • #12 9719298
    xamrex
    Poziom 28  
    michalko12 napisał:
    Żadnych ostrzeżeń kompilator nie generował?
    O dziwo nie

    // Taki błąd aż wstyd.....

    OK jeśli dam
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa.

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

    też działa.

    Ale czemu nie chce działać przy czymś takim:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #13 9719330
    michalko12
    Specjalista - Mikrokontrolery
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    warunek i<=255 daje zawsze true bo po 255 jest 0, czyli masz pętlę nieskończoną.
  • #14 9719349
    xamrex
    Poziom 28  
    Dzięki.
    Jeszcze dwa pytanka
    Przy case 7: mam
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Dlaczego jeśli zostawie
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    To mam warninga:
    large integer implicitly truncated to unsigned type


    A jeśli dodam
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    to już warninga nie ma.
    Mógły mi ktoś to wytłumaczyć
    Czyli rozumiem, że taka obsługa w przerwaniu może zostać?
  • #15 9719372
    gaskoin
    Poziom 38  
    Niby tak, ale ja się zastanawiam, czy ten biedny AVR zdąży to wszystko zrobić w ciągu tej jednej milisekundy jaką mu dałeś :)
  • #16 9719383
    michalko12
    Specjalista - Mikrokontrolery
    xamrex napisał:
    Czyli rozumiem, że taka obsługa w przerwaniu może zostać?

    Bez schematu ciężko powiedzieć o co chodzi w tym kodzie, ale czas pokaże.
    Jesli wystarczy czasu procesora to może być i tak, ale ogólnie mówiąc podejście do rozwiązania problemu jest złe.
  • #17 9719404
    xamrex
    Poziom 28  
    gaskoin napisał:
    Niby tak, ale ja się zastanawiam, czy ten biedny AVR zdąży to wszystko zrobić w ciągu tej jednej milisekundy jaką mu dałeś :)

    Tam nie ma 1ms , pozostał stary komentarz.

    Teraz testy zrobiłem jak dam:
    OCR2 = 100; //Przerwanie porownaiania co 2ms (427HZ)
    to diody słabo świecą.

    Jak dam:
    OCR2 = 1; //Przerwanie porownaiania co 0,0231ms (43200HZ)
    To prawie ich nie widać :D

    Więc chyba nie nadąża ;/

    Żeby dobrze świeciły to muszę w każdym Casi'e usunąć linijkę, która wyłącza rzędy:
    PORTD = 0xff; //wylacz wszystkie rzedy
    Wtedy świeci lepiej, ale pojawia się możliwość powstania duszków (na szczęście ja ich nie mam)

    Dodano po 1 [minuty]:

    michalko12 napisał:
    Bez schematu ciężko powiedzieć o co chodzi w tym kodzie, ale czas pokaże.

    Tu dodałem schemat:
    https://www.elektroda.pl/rtvforum/topic2042597.html#9719241
  • #18 9719415
    michalko12
    Specjalista - Mikrokontrolery
    W ~(1<<r8) 1 (jedynka) jest typu integer, całe te wyrażenie rozwijane jest do największego typu w tym wyrażeniu i następuje próba zapisania do mniejszego typu.

    W PORTD &= ~(1<<r8); nie ma już przypisania tylko wartość PORTD jest zwracana zmodyfikowana o te wyrażenie.

    Dodano po 15 [minuty]:

    Lepiej byłoby gdybyś zrobił programowe wysyłanie danych, pobierając z tablicy bit po bicie bez tego mnożenia.
  • #19 9719510
    tmf
    VIP Zasłużony dla elektroda
    IMHO cały algorytm multipleksowania i sposób przechowywania danych są do kitu. Masz 256 diod, dlaczego ich stanu nie przechowujesz w bitach, tylko całych bajtach? Gdybyś miał to na bitach, to żadne magiczne operacje przesunięć bitowych nie byłyby potrzebne, a cała obsługa multipleksowania byłaby króciutka. Ściągnij przykłady do mojej książki, tam masz gotowca jak zrobić multipleksowanie bez tych całych switch/case. IMHO jest to napisane lepiej ;P
  • #20 9719567
    michalko12
    Specjalista - Mikrokontrolery
    Możesz to jeszcze przyspieszyc w ten sposób
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: text
    Zaloguj się, aby zobaczyć kod

    pod warunkiem, że elementy w tablicy maja tylko wartości 0 i 1,
    i wysyłanie po SPI zrobić w przerwaniu od SPI.


    Oczywiście wszystko powinno byc inaczej zrobione, ale ucz się.
  • #21 9719677
    xamrex
    Poziom 28  
    Skąd masz coś takiego jak sint8_t
    Jaki nagłówek mam dołączyć?
    tmf Twoją książkę mam od 2 dni,ale narazie leży, bo nie mam czasu jej przeczytać ;(
    Jak znajde czas to poczytam :)
  • #22 9719740
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Chodziło zapewne o int8_t.

    A co do meritum - tablica bajtów o wartości tylko 0 i 1 to podstawowe źródło problemu, wszelkie wybiegi omawiane tutaj są tylko maskowaniem przyczyny, takim "leczeniem objawowym".

    4\/3!!
  • #23 9719752
    michalko12
    Specjalista - Mikrokontrolery
    xamrex napisał:
    Skąd masz coś takiego jak sint8_t


    Nie używam tych pseudo typów więc nie jestem przyzwyczajony zamiast sint8_t napisz signed char, być może int8_t będzie dobrze.
  • #24 9719757
    gaskoin
    Poziom 38  
    chodzi o signed int 8 bitowy ale w avr-libc to poprostu int8_t a nie sint8_t, w kodzie jest jeszcze jedna pomylka - w dolnym przykładzie powinno być oczywiście i--.
  • #25 9719772
    michalko12
    Specjalista - Mikrokontrolery
    Freddie Chopin napisał:

    A co do meritum - tablica bajtów o wartości tylko 0 i 1 to podstawowe źródło problemu, wszelkie wybiegi omawiane tutaj są tylko maskowaniem przyczyny, takim "leczeniem objawowym".


    Niestety to jest prawda, ale każdy kto chce się nauczyć musi sam do tego dojść.
    Lepiej dać wędkę niż rybę.

    Dodano po 1 [minuty]:

    gaskoin napisał:
    w kodzie jest jeszcze jedna pomylka - w dolnym przykładzie powinno być oczywiście i--


    No tak, typowy błąd u programistów Ctrl+C Ctrl+V, Poprawiłem.
  • #26 9728454
    xamrex
    Poziom 28  
    Znalazłem dzisiaj czas i postanowiłem wrócić do tematu..
    Ten kod
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nie działa.
    Wystarczy zasymulować sobie np. a AVR STUDIO
    Taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    I zmienna suma5 wynosi 40, a powinna wynosić 10.
    Jak napisać ten kod poprawnie?
  • Pomocny post
    #27 9729353
    michalko12
    Specjalista - Mikrokontrolery
    40 a nie 20?

    Co do kodu, trudno pogłówkować Ci dlaczego tak się dzieje?

    Popraw na
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #28 9731663
    xamrex
    Poziom 28  
    Dzięki :)
    Prawie 5x szybciej na jednym casie :)

    Dodano po 11 [minuty]:

    Aa.
    Chyba za szybko się cieszyłem:
    Taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nie działa dostaję za duży wynik,
    A dzieje się to pewnie dlatego, że tam jeśli i jest w tym wypadku większe od 8, to i tak w pętli jest przesuwany w lewo wynik (mnożony jest razy 2) i dlatego wychodzi za wysoki.
    Bardzo bym cię prosił gdybyś mógł raz jeszcze pobawić się tym kodem.
  • #29 9732001
    michalko12
    Specjalista - Mikrokontrolery
    Jak miała być kolejność?

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


    czy taka:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #30 9732077
    zumek
    Poziom 39  
    michalko12 napisał:
    Jak miała być kolejność?

    No właśnie , kolejność :-P
    Jakoś nikt nie zauważył, że pierwszy element tablicy bufor, ma być najmłodszym bitem liczby docelowej.
    Moja propozycja wygląda następująco:

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