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

Atmega 8 - Licznik do14-stu żle działakący kod C

sp5gbw 26 Gru 2015 13:51 1491 27
  • #1 26 Gru 2015 13:51
    sp5gbw
    Poziom 17  

    Witam.
    Korzystając z gotowca, próbuję zrobić licznik LCD zliczający do 14-stu. Do wyświetlania jedynki (dla liczb powyżej 9) wykorzystałem linię 7 portu B. Program się kompiluje i działa inaczej niż oczekiwałem: po włączeniu zasilania licznik działa jak sekundnik wyświetlając liczby w sekwencji co druga:0, 2, 4, 6 itd. do 14 i zaczyna od początku. W założeniu miało być: każde naciśnięcie przycisku (zwarcie 3 PIND do masy) miało spowodować zwiększenie licznika o 1. Oto kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Czy któryś z Kolegów mógłby mi pomóc w rozwiązaniu tego problemu.

    0 27
  • #2 26 Gru 2015 13:55
    excray
    Poziom 39  

    Twój program można wykorzystać do celów akademickich: "znajdź co najmniej 10 błędów w tym kodzie".

    0
  • Pomocny post
    #3 26 Gru 2015 15:49
    szczywronek
    Poziom 27  

    1. Korzystanie z gotowców prawie nigdy dobrze się nie kończy. Szkoda czasu i energii na poprawianie nie swoich kodów ;)
    2. Nie definiuj F_CPU w kodzie programu - to lub podobne zdanie pojawia się tu średnio kilka razy w tygodniu, więc uzasadnienie znajdziesz bez problemu.
    3. Unikaj "magicznych" liczb w kodzie programu. Zapis:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    jest bardziej czytelny i mniej "błędogenny" niż
    Kod: c
    Zaloguj się, aby zobaczyć kod

    4. Chciałeś sprawdzać czy PD3 jest zwarte do masy, a sprawdzasz coś zupełnie odwrotnego :)
    5. Przykładaj większą wagę do wcięć i "przestrzennej organizacji kodu" - po co jest nawias po linii n++?
    6. Jakiś schemat? Trochę łatwiej się analizuje kod, jak wiadomo co gdzie jest.
    7. W opisie stwierdzasz, że "dla liczb powyżej 9 wykorzystałem linię 7 portu B" (pomijając, że nie wiadomo w sumie o co chodzi z wykorzystaniem PB7 dla liczb > 9) w programie - dla n > 9 - robisz coś z portem C. Niestety nie wiadomo o co chodzi - nie ma schematu ;)
    8. Ten switch jest straszny. Zamiast (przykładowo):
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Zastosuj tablicę:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    9. Poczytaj o likwidowaniu drgań styków (np. na blogu).

    0
  • #4 26 Gru 2015 17:16
    2675900
    Użytkownik usunął konto  
  • #5 27 Gru 2015 10:04
    sp5gbw
    Poziom 17  

    Dziękuję za cenne uwagi.
    Z linią 7 portu B jest tak jak zauważył kolega Piotruś zapalam nią "1" potrzebną dla liczb >9 i to mi działa.
    Ponieważ dopiero zaczynam tę zabawę nie rozumiem słów "bałaganiarstwo i niechlujstwo" - jeśli mógłbym prosić o uświadomienie.
    Koledze "szczywronek" bardzo dziękuję za podpowiedzi, odezwę się jak tylko wypróbuję kolegi uwagi.
    Pozdrawiam świątecznie.

    0
  • #6 27 Gru 2015 10:46
    excray
    Poziom 39  

    sp5gbw napisał:
    switch(n&0x0E) //bo liczby większej od 14 nie wyświetlimy

    =>
    sp5gbw napisał:
    licznik działa jak sekundnik wyświetlając liczby w sekwencji co druga

    1
  • #7 27 Gru 2015 10:48
    2675900
    Użytkownik usunął konto  
  • #8 27 Gru 2015 19:03
    sp5gbw
    Poziom 17  

    Dzięki za odpowiedzi i podpowiedzi.
    1. Zmodyfikowałem funkcję "if" wg zaleceń kolegów i jest ok.tzn działa jak poprzednio(zlicza samoczynnie do 14-stu co dwa cały czas, gdy nacisnę przycisk, zliczanie się zatrzymuje, gdy zwolnię przycisk zlicza dalej).
    2. gdy funkcję wpiszę w formie switch(n), jest zmiana polegająca na tym, że teraz po włączeniu zasilania następuje zliczanie od 0~14 co jeden i zatrzymuje się na 14, brak reakcji na przycisk.
    3. Po próbie likwidacji nawiasu po "n++" kompilacja nie następuje.
    4.Chciałbym bardzo skorzystać z dobrodziejstw wykorzystania tablicy, ale jestem za słaby by ją poprawnie umieścić w kodzie (proszę o pomoc).
    5. Sorry, ale nie wiem co w żargonie programistów oznacza zwrot "Magiczne liczby"?
    6. No i na koniec: jak wytłumaczyć, że mimo funkcji "break" pętla nie przestaje działać, no i dla czego opuszcza "case" nieparzyste???
    Pewnie pytania moje wydadzą się trywialne, ale zrozumcie Koledzy, ja z programowaniem miałem do czynienia w latach 70-tych podczas laboratorium ze sterowania obrabiarek przy pomocy papierowych taśm perforowanych...
    PS. Korzystam z WINAVR, bo tylko to środowisko udało mi się uruchomić.
    Pozdrawiam wszystkich i proszę o pomoc.

    0
  • #9 27 Gru 2015 19:27
    excray
    Poziom 39  

    Po każdej poprawce wrzucaj poprawiony kod.

    0
  • #10 27 Gru 2015 19:37
    szczywronek
    Poziom 27  

    Ad 1. Jeżeli masz na myśli wskazówkę z mojego posta (post #3, punkt 3) to zaproponowana zmiana nie zmienia nic w działaniu programu! Chodzi tylko o unikanie magicznych liczb (patrz dalej). Program nie czeka na przycisk z przyczyny o której wspominałem w punkcie 4 ;)

    Ad 3. No a spodziewałeś się czegoś innego?

    Ad 2, 3, 4. Zdecydowanie powinieneś poczytać jakieś kurs języka C! Strzelanie na ślepo jest męczące i frustrujące. Ewentualnie możesz poprosić o to, aby ktoś napisał ten program za Ciebie, ale od tego jest inny dział forum ;)

    Ad 5. (taka subiektywna definicja na szybko) Wszystkie liczby, pojawiające się w kodzie programu, których sens nie jest jasny na pierwszy rzut oka dla kogoś kto pierwszy raz ogląda ten kod. W szczególności, jeśli można zamienić je na odpowiednie definicje. Np. tak jak punkcie 3 w moim poprzednim poście.

    Ad 6. Nie rozumiem jaką pętlę masz na myśli. Switch opuszcza nieparzyste wartości z powodu "wymaskowania" ostatniego bitu w wartości n co zauważył kolega excray. Policz jaki będzie wynik operacji (notabene znowu magiczna liczba się pojawia): n&0x0E gdy n jest nieparzyste (np. dla n = 5).

    0
  • #11 28 Gru 2015 19:13
    sp5gbw
    Poziom 17  

    Dzięki koledzy za cierpliwość i wyrozumiałość
    Po wykonaniu obliczeń n&0x0E dla n=5 wyjaśniła się sprawa opuszczania nieparzystych CASE. Oto kod po przeróbkach i jak myślę uporządkowaniu:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Efekt działania: Po włączeniu zasilania "licznik" zachowuje się jak sekundnik; zlicza od "0" do "14" i zatrzymuje się na "0", wyzerowanie linii D 3 przyciskiem zatrzymuje proces zliczania. Tak więc na pewno mam problem z przyciskiem; co powoduje, że jak przypuszczam, "n" narasta automatycznie "++" a nie zwiększa swej wartości o "1" po naciśnięciu przycisku?
    Pozdrowienia

    0
  • #14 29 Gru 2015 18:59
    sp5gbw
    Poziom 17  

    Po zastosowaniu "if( (PIND & 1<<PD3) == 0)" podrzuconego przez kolegę z Sieradza - dziękuję za zainteresowanie i chęć pomocy, - kod kompiluje się z ostrzeżeniem: :46: warning: suggest parentheses around comparison in operand of &. Wynikiem działania programu jest wyświetlanie "0" i brak reakcji na przycisk. Coś jest jeszcze nie tak...
    Koledze z Łodzi również bardzo dziękuję i rozumiem jego decyzję, choć z drugiej strony bardzo bym chciał, żeby kolega mimo mojej niekompetencji czasem się odezwał. Bardzo zależy mi aby ten licznik uruchomić, gdyż stanowi on istotną część mojego"życiowego" projektu.

    0
  • #15 29 Gru 2015 19:21
    Voodoo16
    Poziom 2  

    Twoje ostrzeżenie sugeruje żebyś ubrał to wyrażenie w nawiasy, gdyż może być niepoprawnie interpretowane przez kompilator. Operatory mogą być lewostronnie albo prawostronnie łączne i od tego będzie zależała kolejność wykonywania działań, więc twój obecny kod może być interpretowany jako

    Kod: c
    Zaloguj się, aby zobaczyć kod
    co nie jest zamierzonym efektem. Tobie zależy na operacji:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    W 90% przypadkach takie ostrzeżenia powodują działania niezamierzone. Dodatkowo poczytaj trochę o podstawach obsługi portów I/O, jaki stan powinien być po wciśnięciu przycisku itp. Możesz też poczytać o łączności operatorów, dzięki czemu rozróżnisz kiedy nawiasy są potrzebne, a kiedy nie. Ja ze swojej strony polecam ubierać w nawiasy i nie martwić się o to czy wyrażenie zostanie poprawnie zinterpretowane.

    Pozdrawiam.

    0
  • #17 30 Gru 2015 10:24
    szydarek
    Poziom 2  

    Czy po poprawieniu linijki z 'if' jak napisał dondu przycisk ci zadziałał? Napisz co ma program zrobić po doliczeniu do 14? Zatrzymać się? Liczyć od nowa od 0?

    0
  • #18 30 Gru 2015 19:09
    sp5gbw
    Poziom 17  

    DZIĘKUJĘ!
    Koledze "szydarek" za zainteresowanie się moim licznikiem.
    Koledze "dondu" za podrzucenie rozwiązania i linków (kolega jest znany wśród programistów, sam korzystam kolegi pomocnych materiałów)
    Koledze "Voodoo16" za pomocną teorię.
    Koledze "excray" za podpowiedzi.
    Kod po wprowadzeniu zmian działa zgodnie z moimi wstępnymi założeniami, krótkie "delay", gdyż impulsy do zliczenia mają częstotliwość ok. 5kHz. Oto kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Efekt działania: po włączeniu zasilania wyświetlane jest "0" każde naciśnięcie przycisku (nowy impuls), podwyższa stan licznika o "1", po osiągnięciu "14" przycisk jest nieaktywny.

    Tylko, że teraz nowy problem; licznik impulsy będzie dostawał drogą radiową, za każdym razem inną ilość do zliczenia od "0". Wymyśliłem, że najprostszym rozwiązaniem będzie zmodyfikowanie kodu tak, aby pierwszy impuls zawsze zerował licznik a pozostałe podwyższały jego stan...
    Tylko, pewnie nadużywam kolegów cierpliwość, może powinienem otworzyć nowy temat - proszę o podpowiedź.
    A może któryś z kolegów odniósł by się jeszcze do tego, czy taki kod na Atmedze 8 da się zrealizować, a może jakaś podpowiedź jakie funkcje wykorzystać..?
    Pozdrawiam i jeszcze raz dziękuję.

    0
  • #19 30 Gru 2015 20:39
    2675900
    Użytkownik usunął konto  
  • Pomocny post
    #20 30 Gru 2015 23:55
    penknife
    Poziom 20  

    jak już koledzy wyżej wymienili:
    #F_CPU deklaruj w projekcie
    a poniżej moja drobna wariacja na temat:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #21 31 Gru 2015 00:08
    excray
    Poziom 39  

    Zawsze mnie zastanawia po co ludzie po wykryciu wciśnięcia przycisku zawieszają program na jakiś czas opisując go że (Bóg wie po co?) czekają aż drgania styków zanikną. To chyba taki nawyk do przepisywania bez zastanowienia kodu gdzieś znalezionego w necie powoduje że do dziś takie dziwne niuanse dalej są wklejane w program.

    0
  • #22 31 Gru 2015 00:43
    2675900
    Użytkownik usunął konto  
  • #24 31 Gru 2015 18:06
    sp5gbw
    Poziom 17  

    Dzięki za podpowiedzi. Wszystkie posty czytam uważnie i staram się je zrozumieć.

    Dziękuję koledze "penknife", że zadał sobie tyle trudu aby mi pomóc, będę chciał się jakoś odwdzięczyć. Kod kolegi jest piękny i zrozumiale skomentowany. Domyślam się, że aby go przetestować, będę musiał "dogadać się" z AVRStudio, które mam już w kompie (mam szóstkę), ale ciągle nie mogę go "ożenić" z USBasp...Swój "kod" kompiluję na WIN AVR, a tu też schody - bo jak na razie jest on w stanie skorzystać tylko z dwóch bibliotek: <avr/io.h> oraz <util/delay.h>, stąd te moje "programy" takie rozlazłe.
    Z tych zapewne powodów kompilacja kodu na razie się nie powiodła.

    Dzięki za uwagi koledze "piotrus_999".
    Robiłem pewne próby w tym "moim" kodzie i doszedłem do wniosku, że aby pierwszy impuls zerował licznik, trzeba by coś wymyślić, żeby naciśnięcie przycisku PIND (po odstępie czasowym) wyzerowało "n", korzystając z faktu, że nowa paczka impulsów nastąpi dopiero po czasie >= 10000T (okresów) podawanych na licznik impulsów.
    Sprawę komplikuje fakt, że stan licznika powinien pozostać, aż do jego zmiany spowodowanej nową paczką impulsów.

    Czy to jest do zrobienia bez wykorzystywania przerwań, timerów, wyzwalania zboczem, o których trochę czytałem, ale na to jestem jeszcze trochę "za krótki"?

    Dzięki "koledze "dondu" za linki - tyle tylko, że zamiast świętować idę studiować...


    Wszystkim kolegom składam Życzenia Szczęśliwego Nowego Roku

    0
  • #25 31 Gru 2015 18:44
    BlueDraco
    Specjalista - Mikrokontrolery

    Sam widzisz, że musisz odmierzać czas.

    Każdy projekt z mikrokontrolerem zaczyna się od przerwania timera. Bez tego nie da się zrobić prawie nic.

    0
  • #26 31 Gru 2015 21:30
    2675900
    Użytkownik usunął konto  
  • #27 01 Sty 2016 12:03
    dondu
    Moderator Mikrokontrolery Projektowanie

    ... proste projekty często da się oczywiście wykonać bez używania przerwań, ale uwagi kolegów wyżej są właściwą drogą - timery i przerwania to podstawa wykorzystania mikrokontrolerów.

    Jeżeli masz problem z tym tematem, to zaglądnij do spisu treści na stronie, której link załączyłem i kliknij "Kurs AVR".

    sp5gbw napisał:
    ... będę musiał "dogadać się" z AVRStudio, które mam już w kompie (mam szóstkę), ale ciągle nie mogę go "ożenić" z USBasp...Swój "kod" kompiluję na WIN AVR, a tu też schody - bo jak na razie jest on w stanie skorzystać tylko z dwóch bibliotek: <avr/io.h> oraz <util/delay.h>, stąd te moje "programy" takie rozlazłe.

    W czym dokładnie masz problem z AVR Studio 4?

    sp5gbw napisał:
    Wszystkim kolegom składam Życzenia Szczęśliwego Nowego Roku

    ... a my odwzajemniamy życzenia Tobie :)

    0
  • #28 01 Sty 2016 19:33
    sp5gbw
    Poziom 17  

    Dzięki
    Przejrzałem sporą część Twoich opracowań. Jest tego tyle, że starczyło by na niezłą "cegłę". Naprawdę są pomocne, szczególnie podoba mi się sposób przedstawiania uwag - czytając nie sposób ich zignorować.
    Aby uruchomić mój USBasp (działający z WINAVR), pozwoliłem sobie skorzystać z artykułu "Jak ożenić USBasp i Atmel Stydio. Wykonałem wszystko (jak mniemam) dobrze, choć miałem pewne wątpliwości co do Arguments; czy przepisać je ze spacjami czy nie (próbowałem różnie). Po skonfigurowaniu wszystko wygląda dobrze.
    Gdy kliknę "build" - succes, "0"errors itp. Lecz gdy kliknę na Start Without Debuging - pojawia się okno :

    Cytat:
    avrdude.exe: unknown option -- -
    Usage: avrdude.exe [options]
    Options:
    -p <partno> Required. Specify AVR device.
    -b <baudrate> Override RS-232 baud rate.
    -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).
    -C <config-file> Specify location of configuration file.
    -c <programmer> Specify programmer type.
    -D Disable auto erase for flash memory
    -i <delay> ISP Clock Delay [in microseconds]
    -P <port> Specify connection port.
    -F Override invalid signature check.
    -e Perform a chip erase.
    -O Perform RC oscillator calibration (see AVR053).
    -U <memtype>:r|w|v:<filename>[:format]
    Memory operation specification.
    Multiple -U options are allowed, each request
    is performed in the order specified.
    -n Do not write anything to the device.
    -V Do not verify.
    -u Disable safemode, default when running from a script.
    -s Silent safemode operation, will not ask you if
    fuses should be changed back.
    -t Enter terminal mode.
    -E <exitspec>[,<exitspec>] List programmer exit specifications.
    -x <extended_param> Pass <extended_param> to programmer.
    -y Count # erase cycles in EEPROM.
    -Y <number> Initialize erase cycle # in EEPROM.
    -v Verbose output. -v -v for more.
    -q Quell progress output. -q -q for less.
    -? Display this usage.

    avrdude version 5.10, URL: <http://savannah.nongnu.org/projects/avrdude/>



    i małe okno z tekstem " Start Debging is not supported for Simulator". Oczywiście programator nie programuje... Co ja źle robię?
    Pozdrawiam.

    0
  Szukaj w 5mln produktów