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

[AVR][C][Atmega8]TIMER i Preskaler - błąd przy kompilacji

Bartek.k.k 03 Cze 2011 23:15 5444 27
REKLAMA
  • #1 9574513
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Witajcie, jako amator buduje termometr z wykorzystaniem kodu Pana Mirka Kardasia z książki "Mikrokontrolery AVR w języku C". Kod się wspaniale kompiluje, jeżeli ustawiona jest Atmega32, przy ustawieniu na atmege8 i wstawieniu odpowiedniego kwarcu, takiego jak w kodzie eclipse wywala błąd:

    [AVR][C][Atmega8]TIMER i Preskaler - błąd przy kompilacji

    Przepraszam, że to wstawiam jako obrazek, ale nie wiem co dokładnie będzie potrzebne do analizy błędu, więc wstawiłem wszystko :-> Jeżeli usunę te linijki podkreślone na czerwono, przekompiluje kod i wrzucę do Atmegi, to wszystko się wyświetla, lecz temperatura się nie odświeża :cry: Proszę o pomoc. Pozdrawiam Bartekk!

    PS Proszę nie zwracać uwagi na podkreśloną linijkę dotyczącą podświetlenia wyświetlacza, mam je podłączone na krótko z ominięciem procesora.
  • REKLAMA
  • #2 9574607
    polprzewodnikowy
    Poziom 26  
    Posty: 985
    Pomógł: 54
    Ocena: 225
    Błędy masz jak na dłoni, ATmega8 nie ma portu A, Timer0 ATmegi 8 nie ma w podanych rejestrach wskazanych bitów. Przestudiuj datasheety ATmegi 8 i 32, to wszystko stanie ci się jasne.
  • REKLAMA
  • Pomocny post
    #3 9574633
    Wojtek75
    Poziom 25  
    Posty: 529
    Pomógł: 91
    Ocena: 36
    Dobrze, że uczysz się C ale jeżeli chcesz w pełni wykorzystywać ten język to naucz się jeszcze korzystać z not katalogowych uC.

    1. O porcie A już kolega polprzewodnikowy napisał.
    2. Timer0 w M8 w przeciwieństwie do M32 nie ma możliwości pracy w trybie CTC. Chcesz CTC to przenieś obsługę na T1 lub T2. Ewentualnie T0, ale w trybie normal z cyklicznym przeładowaniem wartości w rejestrze licznika.
  • #4 9574692
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Wojtek75 napisał:
    2. Timer0 w M8 w przeciwieństwie do M32 nie ma możliwości pracy w trybie CTC. Chcesz CTC to przenieś obsługę na T1 lub T2. Ewentualnie T0, ale w trybie normal z cyklicznym przeładowaniem wartości w rejestrze licznika.


    Czy tu chodzi, aby ustawić bit WGM w tryb normalny i CTC więc: TCCR0 |= (1<<WGM00);. Czy dobrze myślę? Niby ustawiłem bit WGM na tryb CTC w atmedze 8 TCCR0 |= (1<<WGM10); i 1 krzyżyk znikł :) Lecz czytając wypowiedź kolegi wyżej przestawiłem na timer1 komendą TCCR1B |= (1<<WGM10);. Czy jest to poprawny zapis?

    Dodano po 33 [minuty]:

    Nie wiem czy jest to poprawne, ale temperatura się odświeża ! :D Wczytałem się w datasheety i rejestr jest teraz taki:

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


    Tylko, że jak odświeża się temperatura to gaśnie i zaświeca się ekran, jak zrobić, aby zmieniała się tylko temperatura bez gaszenia?
  • #5 9574757
    Wojtek75
    Poziom 25  
    Posty: 529
    Pomógł: 91
    Ocena: 36
    Bartek.k.k napisał:
    Czy tu chodzi, aby ustawić bit WGM w tryb normalny i CTC więc: TCCR0 |= (1<<WGM00);. Czy dobrze myślę?

    Źle myślisz. Zobacz jakie bity masz w tym rejestrze w M8.
    Bartek.k.k napisał:
    Niby ustawiłem bit WGM na tryb CTC w atmedze 8 TCCR0 |= (1<<WGM10); i 1 krzyżyk znikł :)

    Również źle. Jak wyżej.
    Bartek.k.k napisał:
    Lecz czytając wypowiedź kolegi wyżej przestawiłem na timer1 komendą TCCR1B |= (1<<WGM10);. Czy jest to poprawny zapis?

    To nie jest poprawny zapis. W rejestrze TCCR1B w M8 nie ma bitu WGM10.

    Nie strzelaj na oślep tylko przejrzyj notę naprawdę zaoszczędzisz sobie sporo czasu i nerwów.
  • REKLAMA
  • #6 9574773
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Wojtek75 napisał:
    Bartek.k.k napisał:
    Czy tu chodzi, aby ustawić bit WGM w tryb normalny i CTC więc: TCCR0 |= (1<<WGM00);. Czy dobrze myślę?

    Źle myślisz. Zobacz jakie bity masz w tym rejestrze w M8.
    Bartek.k.k napisał:
    Niby ustawiłem bit WGM na tryb CTC w atmedze 8 TCCR0 |= (1<<WGM10); i 1 krzyżyk znikł :)

    Również źle. Jak wyżej.
    Bartek.k.k napisał:
    Lecz czytając wypowiedź kolegi wyżej przestawiłem na timer1 komendą TCCR1B |= (1<<WGM10);. Czy jest to poprawny zapis?

    To nie jest poprawny zapis. W rejestrze TCCR1B w M8 nie ma bitu WGM10.

    Nie strzelaj na oślep tylko przejrzyj notę naprawdę zaoszczędzisz sobie sporo czasu i nerwów.


    Jeżeli lepiej się przyglądnąłem to TCCR1B |= (1<<WGM12);. Czy dobrze?

    Ustawiłem niby coś takiego, ale teraz na wyświetlaczu pustka.

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


    Rozumiem tryb CTC, OCR1A również, z TIMSK można powiedzieć, że również, ale nie rozumiem tej linijki:

    TCCR1B |= (1<<CS12)|(1<<CS10); /* preskaler = 1024 */

    W nocie,
    CS12 CS11 CS10
    1 0 1 clkI/O/1024 (From prescaler) oznacza, że źródło CS12 i CS10 ustawiają prescaler na 1024. Nie wiem czy zmęczenie powoduje, że głupieje. Na dziś wystarczy. Pozdrawiam i dziękuje za pomoc, Bartekk.
  • #7 9577455
    Wojtek75
    Poziom 25  
    Posty: 529
    Pomógł: 91
    Ocena: 36
    Bartek.k.k napisał:

    Jeżeli lepiej się przyglądnąłem to TCCR1B |= (1<<WGM12);. Czy dobrze?

    Zdecydowanie lepiej.

    Bartek.k.k napisał:

    Ustawiłem niby coś takiego, ale teraz na wyświetlaczu pustka.

    /* ustawienie TIMER0 dla F_CPU=11,0592MHz */

    OCR1A = 108;

    T1 w m8 to licznik 16-bitowy. Oczywiście w nocie masz tą informację. Trzeba sobie przeliczyć co wpisać do OCR1A żeby przerwanie zgłaszało się po takim samym czasie jak w przypadku ośmiobitowego T0. Czasami może się okazać że trzeba zmienić preskaler żeby uzyskać dokładnie tą samą wartość.

    Bartek.k.k napisał:
    Rozumiem tryb CTC, OCR1A również, z TIMSK można powiedzieć, że również, ale nie rozumiem tej linijki:

    TCCR1B |= (1<<CS12)|(1<<CS10); /* preskaler = 1024 */

    No tym ustawiasz preskaler. Nie wiem czego tu nie rozumiesz?
  • #8 9577468
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Wojtek75 napisał:
    Bartek.k.k napisał:

    Ustawiłem niby coś takiego, ale teraz na wyświetlaczu pustka.

    /* ustawienie TIMER0 dla F_CPU=11,0592MHz */

    OCR1A = 108;

    T1 w m8 to licznik 16-bitowy. Oczywiście w nocie masz tą informację. Trzeba sobie przeliczyć co wpisać do OCR1A żeby przerwanie zgłaszało się po takim samym czasie jak w przypadku ośmiobitowego T0. Czasami może się okazać że trzeba zmienić preskaler żeby uzyskać dokładnie tą samą wartość.


    Tu właśnie leże, całkowicie nie wiem co należy tutaj wpisać.

    Wojtek75 napisał:
    Bartek.k.k napisał:
    Rozumiem tryb CTC, OCR1A również, z TIMSK można powiedzieć, że również, ale nie rozumiem tej linijki:

    TCCR1B |= (1<<CS12)|(1<<CS10); /* preskaler = 1024 */

    No tym ustawiasz preskaler. Nie wiem czego tu nie rozumiesz?


    To już zrozumiałem. Poprawny zapis wg. mnie powinien być taki:

    TCCR1B |= (1<<WGM12) |(1<<CS12) |(1<<CS10); /*tryb CTC i preskaler 1024*/

    lub

    TCCR1B |= (1<<WGM12);
    TCCR1B |= (1<<CS12) |(1<<CS00);

    CS12 i CS00 oznaczają preskaler 1024 wg. not katalogowych. Mimo zapisu:

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


    na wyświetlaczu pustka.
  • #9 9577536
    Konto nie istnieje
    Konto nie istnieje  
  • #10 9577545
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    A włączyłeś globalne przerwania (sei() ??


    W kodzie Pana Mirka nigdzie tego nie było, tym bardziej nie wiem, gdzie to nawet wstawić :->

    Edit:// Przerwania globalne sei(); dodane, lecz nadal pustka na lcd. Nie wiem w jaki sposób obliczyć OCR1A. W datasheet jest jakiś wzór:

    fOCn=(fclk_I/O)/2 ⋅ N ⋅ (1 + OCRn) Tylko za bardzo nie wiem co podstawić pod OCRn, bo N to preskaler jak się nie myle, fclk_i to częstotliwość procesora, a O też nie wiem co to jest.
  • #11 9577568
    Konto nie istnieje
    Konto nie istnieje  
  • #12 9577574
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    to w takim razie książka godna polecenia.


    Widocznie do tego kodu nie potrzeba tych funkcji, bo jeżeli jest to tak ważne, to w książce pewnie byłoby to napisane, tym bardziej, że jest to książka dla początkujących. Proszę tego nie odebrać jako obrazę, jest to tylko moje zdanie.

    Wracając, początek programu zaczyna się tak:

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


    Jest jakiś łatwy sposób na obliczenie wartości OCR1A, bo chyba przez podanie błędnej wartości na wyświetlaczu nic się nie wyświetla.


    Edit:// Wyświetlacz sprawny :)

    Dodano po 7 [minuty]:

    Ale ze mnie głupia istota. Potencjometr nie był dociśnięty :-> Wracając, przy rejestrze

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


    na wyświetlaczu w górnej linii wyświetla się 1 czarny kwadracik, a na dole 3 symbole termometru (int8_t znak_termo[] PROGMEM = {4,10,10,10,17,31,31,14};)
  • #13 9577591
    Konto nie istnieje
    Konto nie istnieje  
  • #14 9577602
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Wychodzi na to, że działa chodź jak to mówią "szału nie ma". Wyświetlacz miga z dość dużą szybkością i słabo widać co na nim piszę. Mimo wpisania innych wartości do OCR1A, lcd miga nadal tak samo. Po dodaniu funkcji globalnej sei(); przed rejestrem, przerwania w ogóle nie działają, bo wyświetlacz stoi w miejscu i nic nie wyświetla.


    Edit:// Co do przerwań globalnych. Walnąłem ogromnego byka. Są one oczywiście, lecz Pan Mirek umieścił je nie na początku jak myślałem, a w połowie kodu :-> Przepraszam za wprowadzenie w błąd.
  • Pomocny post
    #15 9577614
    Konto nie istnieje
    Konto nie istnieje  
  • #16 9577627
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    Wpisz większą wartość do OCR1A, przerwanie wtedy musi wywoływać się rzadziej albo zrób tak jak czasami robię kiedy procek działa za szybko a potrzebuję mieć przerwanie rzadziej;
    zadeklaruj zmienną globalną, np: uint8_t licz = 0;
    
    SIGNAL(TIMER2_COMPA_vect)
    {
    licz++;
    if(licz >= 10) //liczba przykładowa, zależy jak często chcesz mieć wykonywany kod
    {
    licz=0;
    //tutaj kod wykonywany w przerwaniu
    }}
    

    inny sposób na wolne przerwanie to obniżenie częstotliwości taktowania procka, albo zastosowanie timera 2 i taktowanie go kwarcem 32kHz


    Obniżenie taktowania pomogło, lecz na dzisiaj chyba wystarczy :-> Jedyne co mnie interesuje to brak reakcji na wpisanie innej wartości do OCR1A, miganie lcd jest takie same. Pozdrawiam i życzę miłej nocy.
  • #17 9577631
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #18 9577636
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    A jaką inną wartość wpisujesz ??

    Wpisz do OCR1A wartość 0x0A8C (dla kwarcu 11.0592MHz) to będziesz miał częstotliwość 4Hz, wartość obliczona tym programem co dodałem wyżej.


    Niestety coś jest chyba nie tak. Migotanie jest takie same, na dodatek litery itp. są strasznie nie wyraźne. Po wyłączeniu przerwań, treść wyświetlana na lcd jest bardzo wyraźna.

    karol_85 napisał:
    A jaką inną wartość wpisujesz ??


    Załóżmy, że chciałbym odświeżanie na poziome 2Hz to OCR1A = 0x1518.


    PS Dobrze, że moderatorzy słodko śpią to chociaż błędy w postach można szybko wyedytować :D
  • #19 9577645
    Konto nie istnieje
    Konto nie istnieje  
  • #20 9577647
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    Dziwne, jeśli wyłączysz przerwania to procesor Ci do żadnego nie wejdzie.


    Zgadza się, wyświetla się tylko tekst bez odświeżania.

    karol_85 napisał:
    Druga sprawa konfigurujesz timer 1 a wektor przerwania masz od timera 0.


    Chodzi o ten fragment?

    Bartek.k.k napisał:
    /* ustawienie TIMER0 dla F_CPU=11,0592MHz */


    Jeżeli tak to jest to wynik mojego lenistwa, nie chciało mi się zmienić z TIMER0 na TIMER1.
  • #21 9577648
    Konto nie istnieje
    Konto nie istnieje  
  • #22 9577650
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    Chodzi mi o to: ISR(TIMER0_COMP_vect), przecież jak byk pisze TIMER0, zero oznacza timer 0, a w rejestrach konfigurujacych masz wszędzie 1 czyli są od timera 1.


    Fakt, eclipse wywala błąd przy tym fragmencie, ale wszystko już mówię. Kod był pisany dla Atmegi32, tak jak pisałem na początku. Niestety po zmianie na TIMER1B nadal jest wykrzyknik. Tego niestety nie umiem skonfigurować. Zostawmy to na jutro :)
  • #23 9577653
    Konto nie istnieje
    Konto nie istnieje  
  • #24 9577659
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    W sumie to nie jest blad, a taki zolty wykrzynik wiec moge skompilowac kod i wrzucic. Gdyby obok fragmentu byl czerwony krzyzyk to kompilacja, by sie nie udala. Co do kodu, tak jest to kod wziety z ksiazki. Chyba od tego on jest, jezeli Pan Mirek go tam umiescil to czytelnik moze go uzywac, chyba ze sa jakies prawa autorskie. Diody i przyciski szybko sie nudza. Poczatkujacy lubia wkraczac na glebokie wody :->. Pozdrawiam Bartekk!

    PS Przepraszam za brak polskich znakow.
  • #25 9577660
    Konto nie istnieje
    Konto nie istnieje  
  • #26 9577664
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    Dzis juz tego nie zrobie, bo aktualnie przebywam w wannie. Dziekuje Ci kolego, ze nauczyles mnie timerow. Jutro, jezeli moderatorzy nie beda mieli nic przeciw napisze czy wszystko dziala. A tak przy okazji, jaka funkcje pelni to przerwanie, o ktorym mowa?
  • #27 9577668
    Konto nie istnieje
    Konto nie istnieje  
  • #28 9577983
    Bartek.k.k
    Poziom 21  
    Posty: 617
    Pomógł: 15
    Ocena: 64
    karol_85 napisał:
    Pisałem wyżej: TIMER1_COMPA_vect. I jeśli chodzi o terminologię to nie funkcja tylko wektor przerwania


    Chyba się pomyliłeś, ponieważ po wpisaniu Twoich poprawek ekran stał w miejscu nieruchomo. Zmieniając COMPA na COMPB wszystko zaczęło poprawnie chodzić :)
    karol_85 napisał:
    Dobrze, że jesteś ambitny ale nie mając podstawowej wiedzy o programowaniu chcesz ogarnąć wszystko na raz. Jakbyś zaczął od podstaw i ogarnął najpierw wiedzę o przerwaniach a później timery to byś nie popełnił tego błędu,chociaż należało by na odwrót. Moim zdaniem początkujący za często chcą od razu wkraczać na głęboką wodę bo jak to jest w życiu z pływaniem - toną. Metoda małymi kroczkami jest najskuteczniejsza, bo uczysz się po woli ale skutecznie. Nie ogarniesz na raz dużego kawałka wiedzy i nie zrozumiesz całego kodu (np tego co w tym programie) nie znając podstaw.


    Zaczynam od małych projektów, ale układ termometru był moim konstrukcyjnym marzeniem, więc musiałem go zrobić nawet bez odpowiedniej wiedzy :->

    karol_85 napisał:
    Uważaj z kompem w tej wannie bo skończy jak ten utopiony przez serce w reklamie tp a później suszarka nie pomoże


    Dzięki za troskę :)

    karol_85 napisał:
    Powodzenia w programowaniu !!!


    Dziękuje i wzajemnie :)

    Podczas pisania pytania dotyczące modyfikacji kodu, aby migała, odświeżając się tylko sama temperatura bez górnej linii sam z sukcesem zmodyfikowałem kod :)

    Fragment:

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


    wystarczyło wstawić na początek kodu, przed inicjalizacją LCD, aby przerwania nie odświeżały tego fragmentu :) Na poniższym filmiku jest pokazane jak to działa z odświeżaniem całego wyświetlacza, a pod 2 filmik z wersją v2 :) A ja zabieram się do lutowania 2 czujnika i puszczenie go za okno. Temat myślę, że całkowicie rozwiązany i zrozumiany. Jeżeli ktoś ma jakieś pytania, proszę śmiało pisać :)

    v1-> http://www.youtube.com/watch?v=UkuwycE7Bqc
    v2-> http://www.youtube.com/watch?v=7Yj1xosiZQk

Podsumowanie tematu

✨ W dyskusji poruszono problem kompilacji kodu dla mikrokontrolera ATmega8, który był pierwotnie napisany dla ATmega32. Użytkownik napotkał błędy związane z rejestrami timerów oraz brakiem portu A w ATmega8. Odpowiedzi wskazywały na konieczność przestudiowania not katalogowych, aby zrozumieć różnice między timerami. Użytkownik próbował ustawić timer w trybie CTC, jednak napotkał trudności z konfiguracją rejestrów. Po kilku próbach i wskazówkach od innych uczestników, udało mu się poprawnie ustawić timer1, co pozwoliło na odświeżanie temperatury na wyświetlaczu. Wskazano również na potrzebę włączenia globalnych przerwań oraz poprawnego ustawienia wartości OCR1A, co miało wpływ na działanie wyświetlacza LCD.
Wygenerowane przez model językowy.
REKLAMA