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

ATTiny2313 / C - Timer0 Początki

maximus22_kr 13 Paź 2015 11:20 2178 47
  • #1 13 Paź 2015 11:20
    maximus22_kr
    Poziom 18  

    Witam
    Próbuję zapoznać się z językiem C. Mam gotową płytkę z ATTiny2313.
    Chciałem na początek pomęczyć diodę LED. Jako, że Delay nie jest dobrym rozwiązaniem próbuję z Timerem0

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Chciałem włączyć go w trybie Normal z preskalerem 64 i załadować wartość 6 do rejestru, jeśli dobrze obliczyłem, gdy Timer0 "przekręci" się 500 razy będzie sekunda.
    Mam błąd przy konfiguracji Timera0. Błąd "Symbol 'TCCR0B' could not be resolved".

    W PDF Attiny2313 jest:
    TCCR0B
    TCCR1B

    Jako "Bascomowiec" jestem przyzwyczajony do oznaczeń Timer0, Timer1, Timer2. Jeśli dobrze odczytuję PDF to Timer0 ( 8Bit ) ma rejestr TCCR1B i jest konfigurowany przez bity CS12 CS11 CS10.

    Czy mógłby ktoś to potwierdzić lub wyprowadzić z błędu ?

    0 29
  • Arrow Multisolution Day
  • #2 13 Paź 2015 11:31
    szczywronek
    Poziom 27  

    Timer0 to bity i rejestry z "0" w nazwie, np: TCCR0A, TCCR0B, COM0A1, CS00, CS01, ... Analogicznie licznik 1 będzie miał w nazwie "1".

    Przy okazji: zdecydowanie musisz poczytać o obsłudze przerwań w C. To co masz w pętli nieskończonej jest zdecydowanie dziwaczne :) ISR (procedura obsługi przerwania) powinna być osobną funkcją. U Ciebie, w pętli while, jest deklaracja (?) procedury przerwania i pusty blok {}.

    EDIT:
    Jeszcze kilka spraw się nie zgadza:
    1. Zjadło Ci się przesunięcie bitowe przy CS00
    2. Przy ustawianiu rejestrów TCCR0B i TIMSK niepotrzebnie korzystasz z sumy bitowej zamiast przypisania.
    3. Przypuszczam, że z tą wartością początkową to nie do końca o to Ci chodziło. Tzn. to zadziała jednokrotnie. Licznik odliczy od tych 6 do przekręcenia, ale potem będzie już liczył od 0 a nie od 6.

    0
  • #3 13 Paź 2015 13:25
    maximus22_kr
    Poziom 18  

    Pusty blok jest dlatego, że utknąłem na konfiguracji Timer0.
    Jeśli chodzi o rejestry, to podejrzewałem, że jest tak, jak Kolega pisze.

    Wartość TCNT0 = 6; trzeba będzie wpisać do przerwania Timera

    Przy ustawieniach:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    jest błąd, w ustawieniach projektu mam wybrany ATTiny2313 i 8000000 Hz.

    Ale jeśli włączę Timer1
    Kod: c
    Zaloguj się, aby zobaczyć kod


    to błędów nie ma

    0
  • #4 13 Paź 2015 13:47
    szczywronek
    Poziom 27  

    Teraz to popsułeś. Zobacz opis rejestru TCCRxA w dokumentacji (strona 73 w pdfie ze strony atmela). Tam nie ma bitów CSx0 i CSx1.
    Punkt (1) z mojego poprzedniego postu też bym poprawił.

    Jeżeli kompilator nie rozpoznaje rejestru TCCR0B to jest to problem ze środowiskiem a nie kodem programu. Napisz z jakiego środowiska korzystasz i wklej cały log z kompilacji.

    0
  • #5 13 Paź 2015 14:02
    maximus22_kr
    Poziom 18  

    Dla TCCR0A jest WGM01 i WGM00
    Dla TCCR0B w trybie Compare jest CS02, CS01 i CS00

    Środowisko to Eclipse Mars, zainstalowane najnowsze Atmel Toolchain i AVR Dude ( AVR Dude wziąłem z programu MK AVR Kalkulator Pana Mirka )

    Ta sama płytka i kontroler, ale na próbę odpaliłem tylko Delay i LED działa bez problemu, wygląda, jakby był problem z nazwą rejestru.

    0
  • #6 13 Paź 2015 15:33
    yokoon
    Poziom 28  

    Witam.
    Jeżeli kompiluje się bez błędów to nie się nie przejmuj tym.
    Miałem to samo, po kilku uruchomieniach samo zniknęło.

    Pisałem o tym na forum Atnela - poszukaj.
    Temat: 28-09-2015
    Rejestry typu TCCRxx podkreślone na czerwono.

    0
  • #7 13 Paź 2015 16:33
    maximus22_kr
    Poziom 18  

    Jedynym błędem, który pokazuje Eclipse jest ta nazwa rejestru.

    Czy poniższy kod jest poprawny i będzie migał diodą co 1 sekundę ?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    albo raczej, czy powinien działać, bo u mnie dioda cały czas świeci.

    0
  • Arrow Multisolution Day
  • #8 13 Paź 2015 16:36
    szczywronek
    Poziom 27  

    Nie powinien działać tak jak zakładasz. Nie włączyłeś licznika - rejestr TCCR0B był ok, czemu uparcie zmieniasz na TCCR0A? No i sam zauważyłeś, że sekunda to będzie 500 przekręceń licznika.

    Ten Twój "błąd" to nie błąd kompilatora tylko analizatora z Eclipse. Program pewnie kompilował się bez błędów - nie pokazałeś logu z kompilacji więc tylko gdybam.
    Spróbuj wyczyścić projekt (Project -> Clean) i przebudować Index (Projekt -> C/C++ Index -> Rebuild).

    Dodane po chwili:
    No i w definicjach na początku coś się nie zgadza. Np. przy LED1... raz masz port D a za chwilę B. Ponadto operacja:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    Robi chyba coś innego niż byś chciał.

    0
  • #9 14 Paź 2015 13:09
    maximus22_kr
    Poziom 18  

    Początki trudne.
    Posiłkowałem się teraz tym, Link
    Faktycznie, trochę zamieszania narobiłem.

    Teraz wygląda to tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jeśli chodzi o włączenie przerwań to jest sei();

    Mam natomiast inne pytanie.
    Dlaczego inicjując wyjścia w taki sposób:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zapala się LED2 i LED3 ( a powinno tylko LED3 )

    a gdy zmienię kolejność - nie zmieniając kodu
    Kod: c
    Zaloguj się, aby zobaczyć kod

    świeci tylko LED3

    0
  • #10 14 Paź 2015 13:35
    szczywronek
    Poziom 27  

    Wersja zapalająca oba LEDy:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    Dla poprawy czytelności wyrzućmy definicje i linijki związane z rejestrem DDR bo to nie one są problemem:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    I jeszcze zamieńmy definicje PB0 i PB1 na odpowiadające im wartości:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Obliczmy przesunięcia:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    No i teraz wszystko widać:
    - w pierwszej linijce masz sumę bitową rejestru PORTB i wartości binarnej 0b1, po tej operacji rejestr PORTB ma wartość 0b1
    - w drugiej linijce masz iloczyn bitowy wartości rejestru PORTB (0b1) i wartości 0b10 -> w efekcie otrzymujesz 0. Jeśli diody podłączone są od VCC do mikrokontrolera - to się zapalają.

    Teraz druga wersja kodu - ta która zapala tylko LED3:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Postępowanie analogiczne jak poprzednio:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    - pierwsza linijka to iloczyn wartości rejestru PORTB (0) i 0b10 -> w wyniku otrzymujesz zero
    - druga linijka to suma wartości rejestru PORTB (0) i 0b1 -> w wyniku masz 0b1. Wszystko się zgadza.

    Błąd wynika z tego, że nie masz dobrze opanowanych operacji bitowych. Jeżeli chcesz skasować jakiś bit rejestru to musisz wykonać operację:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    U Ciebie brakuje negacji (tyldy). Osobna kwestia jest taka, że po resecie mikrokontrolera te rejestry mają wartość 0. Kasowanie (nie ustawionych wcześniej) bitów nie ma sensu.

    0
  • #11 14 Paź 2015 16:52
    maximus22_kr
    Poziom 18  

    Cytat:
    Błąd wynika z tego, że nie masz dobrze opanowanych operacji bitowych.

    Niestety smutna prawda.

    Do tego dochodzą przyzwyczajenia z Bascom, tam prościej operowało się poszczególnych bitach portu.

    A jak w kwestii Timera0 ?
    jeśli dobrze wyczytałem w PDF Attiny2313 to:
    Dla TCCR0A jest WGM01 i WGM00
    Dla TCCR0B w trybie Compare jest CS02, CS01 i CS00
    [/quote]Nie włączyłeś licznika - rejestr TCCR0B był ok, czemu uparcie zmieniasz na TCCR0A? No i sam zauważyłeś, że sekunda to będzie 500 przekręceń licznika.

    To jest OK ?
    Kod: c
    Zaloguj się, aby zobaczyć kod
    [/quote]

    0
  • #12 14 Paź 2015 17:48
    BlueDraco
    Specjalista - Mikrokontrolery

    To nie jest ok:

    TCCR0B |= (1 << CS01)|(CS00);

    A w ogóle operacje |= na rejestrach sterujących są bez sensu.

    0
  • #13 14 Paź 2015 19:09
    szczywronek
    Poziom 27  

    Wszystko już było - zobacz punkty 1 i 2 z drugiego postu w tym wątku ;) Z tym "nie włączaniem licznika" chodziło mi o to, że w którejś wersji programu nie ustawiałeś bitów CS w rejestrze TCCR0B. A bez tego licznik nie mógł działać.

    0
  • #14 14 Paź 2015 22:53
    maximus22_kr
    Poziom 18  

    BlueDraco napisał:
    To nie jest ok:

    TCCR0B |= (1 << CS01)|(CS00);

    A w ogóle operacje |= na rejestrach sterujących są bez sensu.


    Jako początkujący na razie raczej "klepie" gotowe kody, jak działa to eksperymentuje, żeby skumać jak to działa.

    W większości przykładów, np. tutaj jest
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #15 14 Paź 2015 23:02
    szczywronek
    Poziom 27  

    Najtrudniej analizuje się własny kod, bo zawsze patrzy się przez pryzmat wiedzy o tym co on powinien robić i nie dostrzega się drobnych błędów :)

    Porównaj linijkę z Twojego kodu i z przykładu:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    Teraz widzisz różnicę? Od drugiego postu w tym temacie zwracam Ci na to uwagę...

    0
  • #16 21 Paź 2015 16:03
    maximus22_kr
    Poziom 18  

    Cytat:
    Najtrudniej analizuje się własny kod, bo zawsze patrzy się przez pryzmat wiedzy o tym co on powinien robić i nie dostrzega się drobnych błędów :)


    Zgadzam się z tym w 100%.
    Przy Bascomie rzadko sięgałem do PDF'ów kontrolerów, przy C nie da się bez tego wszystkiego zrobić.

    Bez tych 500 "przekręceń" licznika nawet w Bascom by nie poszło, jak zwykle zbyt dużo chęci i za szybko działam, nie wczuwając się w niektóre tematy.

    Udało się odpalić, więc teraz walczę z moim ulubionym DS18B20, w założeniu oprócz pomiaru temperatury, wynik chcę przesłać na UART - korzystałem z kodu Pana Mirka ( zarówno main.c jak biblioteki do obsługi 1Wire ), zmieniając tylko tryb Timera na przepełnienie ( do CTC jeszcze się nie przyzwyczaiłem ), no i oczywiście w pliku onewire.h ustawiłem odpowiednią końcówkę ( PORTD.5, nóżka nr 9 ATTiny2313 )

    onewire.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    main.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    UART działa ( zajrzałem do PDF i ustawiłem rejestry ), ale cały czas wysyła Brak DS.

    Zastanawiam się, czy coś pominąłem, połączenia elektryczne sprawdziłem miernikiem, rezystor 4K7 oczywiście jest.

    0
  • #18 22 Paź 2015 12:43
    maximus22_kr
    Poziom 18  

    Może źle to ująłem, nic nie robi poza wysyłaniem na UART Brak DS co około sekundę.

    0
  • #19 22 Paź 2015 13:09
    szczywronek
    Poziom 27  

    Ok. Zauważ, że kod odpowiedzialny za wysyłanie tego komunikatu (" Brak DS ") znajduje się przed pętlą główną w funkcji main. Czyli ten kod nie powinien się wykonać więcej niż jeden raz w trakcie działania programu. U Ciebie tak nie jest. Procesor cyklicznie wykonuje kod z początku funkcji main, stąd wniosek -> procesor się resetuje. To opóźnienie (około 1s) wynika najpewniej z delaya (750ms) na początku programu.

    Mikrokontroler może się resetować przez problemy sprzętowe z zasilaniem - np. program tak steruje wyjściami że wywołuje zwarcie lub źródło zasilania ma zbyt małą wydajność aby uciągnąć jakieś wyświetlacze/ledy i inne wodotryski.
    Inna prawdopodobna opcja (i ta jest moim faworytem) to przepełnienie stosu. Piszesz o UARTcie p. Mirka - chodzi o tą "bibliotekę" z buforami kołowymi? Ile pamięci SRAM zajmuje Twój program?

    W ramach poszukiwania winowajcy skróć na razie program. Np. wstaw pętlę nieskończoną (pustą) tuż po rozkazie sei. Jeśli program nadal będzie wariował to eliminując kolejne instrukcje dojdziesz do tego, która powoduje problem.

    Przy okazji: ta linijka po ifie na pewno jest zakomentowana u Ciebie? Bo jej odkomentowanie "rozsypie" wyrażenie warunkowe z if

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #20 22 Paź 2015 16:59
    maximus22_kr
    Poziom 18  

    Żadnych dodatków nie ma, jest tylko ATTiny2313 z kwarcem, wyprowadzone kilka portów oraz złącze 3 pinowe terminal block dla DS18B20 oczywiście podciągnięte rezystorem.

    Jeśli chodzi o rozmiar to
    Program: 1830 bytes (89.4% Full)
    (.text + .data + .bootloader)

    Data: 116 bytes (90.6% Full)
    (.data + .bss + .noinit)

    mkAVR Kalkulator pokazuje 89% - 1830 b

    Jeśli chodzi o bibliotekę, to użyłem tej z płytki dołączonej do książki Pana Mirka, są dwa pliki MKUART.H i MKUART.C

    0
  • #21 22 Paź 2015 17:35
    szczywronek
    Poziom 27  

    No to najprawdopodobniej masz już jeden błąd namierzony - zajętość pamięci SRAM 90% to zdecydowanie za dużo. Nie mam pod ręką tej płyty, ale z tego co pamiętam to w pliku nagłówkowym (mkuart.h) powinny być definicje rozmiarów buforów. Coś w stylu "UART_RX_BUFF_SIZE" i "UART_TX_BUFF_SIZE". Strzelam, że mają po 32B. Zmniejsz je do 16B i daj znać czy coś się zmieniło.

    0
  • #22 23 Paź 2015 12:00
    maximus22_kr
    Poziom 18  

    w mkuart.h mam tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    zmieniłem wartości na 12 i 16, bo były większe

    Teraz jest
    Device: attiny2313

    Program: 1830 bytes (89.4% Full)
    (.text + .data + .bootloader)

    Data: 96 bytes (75.0% Full)
    (.data + .bss + .noinit)

    0
  • #23 23 Paź 2015 12:08
    szczywronek
    Poziom 27  

    12 odpada. Mechanizm działania buforów w tym kodzie wymaga, aby te wielkości były potęgami dwójki. Daj 8B :) Myślałem, że to bufory zajmują większość pamięci, ale wychodzi na to, że masz jeszcze coś "sporego" w kodzie.

    0
  • #24 23 Paź 2015 12:27
    maximus22_kr
    Poziom 18  

    Musiałem dać 16. Przy 8 nic nie wysyłał.

    Program: 1820 bytes (88.9% Full)
    (.text + .data + .bootloader)

    Data: 100 bytes (78.1% Full)
    (.data + .bss + .noinit)

    Wyrzucę na razie obsługę RS485.
    Efekt taki, że tylko raz wysyła Brak DS oraz to że dioda LED miga cyklicznie co mniej więcej sekundę.

    Zastanawiam się, czy problemem nie jest to, że mam podpięty jeden czujnik, a wywołuję procedure dla kilku

    0
  • #25 24 Paź 2015 10:40
    2675900
    Użytkownik usunął konto  
  • #26 24 Paź 2015 10:59
    szczywronek
    Poziom 27  

    Piotrus_999 napisał:
    Nie za bardzo kumam co robi definicja procedury obsługi przerwania w pętli
    Odnosisz się do omawianego aktualnie kodu, czy też nie chciało Ci się czytać całego tematu i tylko siejesz zamęt komentując omówione już błędy :> ?
    Swoją drogą: w żadnym z prezentowanych tu kodów nie ma definicji procedury obsługi przerwania umieszczonej w pętli. Poczytaj o różnicy między definicją a deklaracją ;)

    0
  • #27 24 Paź 2015 13:34
    2675900
    Użytkownik usunął konto  
  • #28 30 Paź 2015 16:53
    maximus22_kr
    Poziom 18  

    Cytat:
    Raczej najpierw musisz sie nauczyć C

    No właśnie próbuję. Przez ostatnie kilka dni przewertowałem więcej PDF od kontrolerów, niż przez ostatnie 3 lata :D
    Na razie największy problem dla mnie to operacje bitowe - wiadomo w Bascom łatwiej.

    Kupiłem nawet Attiny4313, coby nie brakło pamięci.
    Problem był jednak w momencie polecenia włączenia przerwań, były włączone dopiero po pierwszym odczycie czujników, przesunąłem wyżej zaraz po konfiguracji rejestrów Timer'a ( tak, jak w Bascom ). Trochę to dziwne, cały kod wziąłem z płyty Pana Mirka, dodając tylko obsługę UART a wyrzucając obsługę LCD.

    Teraz działa, ale chciałem dodać "mignięcie" LED w momencie odczytu i tutaj mam problem. Zrobiłem funkcję, która ma to obsłużyć.
    Dioda ma mignąć na 0,5 sekundy, dlatego dodałem drugą zmienną dla licznika. Niestety dioda "milczy" uparcie, czyli się nie świeci.


    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #29 30 Paź 2015 18:16
    hugeone.co.uk
    Poziom 8  

    po pierwsze nie licznik_led nie jest volatile a dalej nie sprawszalem

    0
  • #30 30 Paź 2015 21:09
    maximus22_kr
    Poziom 18  

    hugeone.co.uk napisał:
    po pierwsze nie licznik_led nie jest volatile a dalej nie sprawszalem


    I z tego powodu się nie zapala LED ? Raczej nie powinna się zgasić.

    0