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

[ATTiny13][C] Uruchomienie Timera0

Morphix 07 Wrz 2010 19:31 12021 30
  • #1 8486327
    Morphix
    Poziom 10  
    Witam.Mam bardzo banalny problem, z którym niestety nie mogę sobie poradzić, a mianowicie uruchomienie Timera0 w ATTiny 13.Oto mój program:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    #define TIMER0_START TIMSK0 |= (1<<TOIE0); TCCR0B |= (1<<CS00) | (1<<CS01); 
    
    ISR(TIMER0_OVF_vect) 
    {
    PORTB=0xff;
    }
    
    int main (void)
    {
    DDRB=0xff;
    TIMER0_START;
    sei();
    
    while(1)
    {
    }
    }


    Chcę żeby uruchomiło się w nim przerwanie od Timera i wystawiło stan wysoki na wszystkich wyprowadzeniach, niestety nic się nie dzieje.Podejrzewam że źle konfiguruje któryś z rejestrów Timera, ale w dokumentacji nie mogę znaleźć wskazówek nt. tego które bity należałoby jeszcze ustawić.Analogiczny program dla ATMegi8 działa bez zarzutu.
    Bardzo proszę o pomoc i z góry dziękuję.
  • #2 8486398
    gaskoin
    Poziom 38  
    nazwa wektora jest zła, powinna być TIM0_OVF_vect
  • #3 8489276
    kubus_puchatek
    Poziom 18  
    Po pierwsze nie: TCCR0B |= (1<<CS00) | (1<<CS01);
    a : TCCR0B =(TCCR0B&0xf8) | (1<<CS00) | (1<<CS01);
    a po drugie masz bity WGM0x a ja nie widzę abyś dokonywał czegoś takiego jak ustawienie trybu pracy.
    Po trzecie sprawdź czy kontroler nie chodzi w efekcie przypadkowych ustawień wewnętrznie jak ślimak. Już widziałem przypadek że człowiek się irytował że soft nie działa a się okazało że złe ustawienia powodowały że dioda zapalała i gasła co 3 minuty. Sprawdź na dzień dobry fusebits.
  • #4 8489511
    gaskoin
    Poziom 38  
    kubus_puchatek napisał:
    Po pierwsze nie: TCCR0B |= (1<<CS00) | (1<<CS01);
    a : TCCR0B =(TCCR0B&0xf8) | (1<<CS00) | (1<<CS01);


    nie ma różnicy skoro i tak wcześniej nijak w rejestrze nie grzebie

    kubus_puchatek napisał:

    po drugie masz bity WGM0x a ja nie widzę abyś dokonywał czegoś takiego jak ustawienie trybu pracy


    jak wgm0x są równe 0 to licznik pracuje w normalnym trybie (poprostu liczy, po doliczeniu do max ustawia flagę OVF i liczy od nowa)
  • #5 8489830
    janbernat
    Poziom 38  
    A co będzie jak TIMER0_START zastąpimy:
    TIMSK0 |= (1<<TOIE0); TCCR0B |= (1<<CS00) | (1<<CS01); ;
    Ja się tylko pytam- co będzie jak są dwa średniki na końcu.
  • Pomocny post
    #6 8489978
    mirekk36
    Poziom 42  
    kubus_puchatek napisał:
    Po pierwsze nie: TCCR0B |= (1<<CS00) | (1<<CS01);
    a : TCCR0B =(TCCR0B&0xf8) | (1<<CS00) | (1<<CS01);


    Kolego zastanów się na drugi raz zanim udzielisz odpowiedzi bo niestety ale bzdury piszesz na maxa i na dodatek nikt tego nie zauważa. Nie znasz i nie umiesz się w C posługiwać operatorami dwuskładnikowymi ???

    toż operacja:

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


    jest dokładnie tym samym co:

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


    a po co ty tam jeszcze wciskasz maskowanie &f8 to już tylko Winetou raczy wiedzieć

    kubus_puchatek napisał:
    a po drugie masz bity WGM0x a ja nie widzę abyś dokonywał czegoś takiego jak ustawienie trybu pracy.

    A po kiszkę ustawiać bity WGMx skoro po resecie są one już ustawione ;) wprawdzie na zera ale są, a to oznacza ni mniej ni więcej tylko, to że jest domyślnie wybrany podstawowy tryb pracy Timera. NORMAL.

    kubus_puchatek napisał:
    Po trzecie sprawdź czy kontroler nie chodzi w efekcie przypadkowych ustawień wewnętrznie jak ślimak.

    O jakich ty przypadkowych ustawieniach w tak krótkim testowym kodzie piszesz, zgroza.

    kubus_puchatek napisał:
    Już widziałem przypadek że człowiek się irytował że soft nie działa a się okazało że złe ustawienia powodowały że dioda zapalała i gasła co 3 minuty.

    No pewnie, jak się nie wie do końca jak działa C i jak się pisze programy to tu popieram, może tak być, no ale autor wcale nie narzeka że mu się coś ślimaczy.

    kubus_puchatek napisał:
    Sprawdź na dzień dobry fusebits.
    To zawsze warto sprawdzić , ale w tym przypadku nie ma to najmniejszego znaczenia - ponieważ autorowi jeszcze raz przypominam po prostu nie działa przerwanie Timera.

    Już gaskoin podpowiedział raz dobrze, że źle autor użył nazwy przerwania i podał mu jaką trzeba użyć.


    janbernat -> jak będą dwa średniki na końcu to nic się nie stanie. Nie mniej jednak takie używanie dyrektywy #define to niestety efekt braku zrozumienia dobrych zasad programowania. A poza tym warto zapamiętać, że w gdy definiujesz coś #define to nigdy właśnie w definicji nie stawiasz średnika na końcu (właśnie po to)

    ----> to wszystko, dajcie autorowi czas na poprawkę, to mu ruszy ;)
  • #7 8490081
    Morphix
    Poziom 10  
    Niestety zmiana nazwy przerwania nic nie daje :cry:.Dzięki za rady te lepsze i te gorsze :P.Ale nadal czekam, aż ktoś pomoże to rozgryźć.Dodam jeszcze że w fusebitach nic nie grzebałem - są fabryczne.

    P.S.:Jedyne co zmieniałem to linijkę w pliku Makefile:
    
    F_CPU = 1200000

    (Fabryczna częstotliwość taktowania procka to 9,6MHz/8 (fusebit CKDIV)),
    a makefile był ustawiony na 8MHz.
    Wątpię czy to ma jakiś wpływ na działanie Timera, ale wolałem napisać.
  • #8 8490217
    mirekk36
    Poziom 42  
    No wpływ ma, w sensie że inaczej czas tyka dla niego, jednak procedura przerwania powinna się normalnie odpalać. Może jakiegoś innego babola robisz może w połączeniach samych. Bo skąd wiesz że on w ogóle działa. Próbowałeś mu migać diodą LED z pętli głównej żeby sprawdzić najpierw taki podstawowy tryb działania całości ??
  • #9 8490282
    Morphix
    Poziom 10  
    Tak.Sam mikrokontroler działa dobrze - porty i przerwania zewnętrzne działają.Testowałem programik z tego tematu:

    https://www.elektroda.pl/rtvforum/topic1430431.html

    wykorzystujący Timer0 i PWM i działa on ładnie, więc nie rozumiem dlaczego Timer na zwykłych ustawieniach nie chce działać.
  • #11 8491080
    arturt134
    Poziom 27  
    Ale testowałeś inny program, czy w swoim programie w main() migałeś diodą w pętli? Bo może masz coś zwalone w inicjalizacji niskopoziomowej lub wyłączony timer w module oszczędzania energii.
    Proponuję, żebyś:
    1. Sprawdził ustawienia rejestru wyłączającego moduły (ATTiny13A pewnie go ma, jeżeli używasz starego ATTiny13, to prawdopodobnie nie można w nim wyłączać modułów).
    2. Do swojego kodu dodał miganie diodą w main().
    3. Sprawdził, czy przerwanie włącza się w symulatorze (najlepiej AVR Simulator 2 z AVR Studio) - jak tam nie działa, to żadnym cudem nie zadziała też w rzeczywistym układzie.

    Dodano po 4 [minuty]:

    Jeszcze jedna uwaga. Raczej nie zakładaj, że wszystkie rejestry będą miały po resecie stan taki jak jest napisane w dokumentacji. Producent też popełnia błędy. Bezpieczniej jet poświęcić te kilkadziesiąt bajtów kodu, żeby inicjalizować krytyczne rejestry, np. powyłączać niepotrzebne moduły itp.
  • #12 8491112
    Morphix
    Poziom 10  
    Rzeczywiście miganie diodą nie działa : O.Spróbuję sprawdzić program w Simulatorze i poinformuję o wynikach.Używam Attiny13, nie Attiny13A.

    EDIT:Zrobiłem symulację i przerwanie ładnie wskakuje.
  • #13 8491370
    mirekk36
    Poziom 42  
    mirekk36 napisał:
    Próbowałeś mu migać diodą LED z pętli głównej żeby sprawdzić najpierw taki podstawowy tryb działania całości ??


    No przecież pisałem wcześniej o tym, to napisałeś, że sprawdzałeś i było ok ;) .... oj coś zakręcony kolega na maxa ;)

    Dodano po 3 [minuty]:

    arturt134 napisał:

    Jeszcze jedna uwaga. Raczej nie zakładaj, że wszystkie rejestry będą miały po resecie stan taki jak jest napisane w dokumentacji. Producent też popełnia błędy. Bezpieczniej jet poświęcić te kilkadziesiąt bajtów kodu, żeby inicjalizować krytyczne rejestry, np. powyłączać niepotrzebne moduły itp.


    Proponuję jednak takie uwagi włożyć między bajki, zamiast jak to zwykle bywa doszukiwać się błędów producenta - tym bardziej, że jak widać jest się początkującym i jeszcze nie do końca wie co się robi. Zatem takie podpowiedzi o błędach producentów mogą wyrządzić tylko więcej zła niż dobrego. Później byle coś się stanie, program nie będzie działał - to od razu zobaczymy post o tym, że ktoś nowy wykrył właśnie NOWY błąd w procesorze X ;)

    To co po resecie ma być w rejestrach, to jest i JUŻ, inaczej jest z pamięcią RAM
  • #14 8491402
    arturt134
    Poziom 27  
    mirekk36: Dużo jeszcze musi wody w Wiśle upłynąć, abyś zrozumiał, że na tym świecie nie ma nic pewnego.... Poza tym, ja tylko udzielam rady, nieważne lepszej, czy gorszej. Możesz jej posłuchać, możesz ją olać, możesz znać inny sposób na rozwiązanie problemu, być może lepszy. Dla mnie osobiście nie zależy na przekonywaniu kogokolwiek do swoich racji. Ale do licha nie zarzucaj mi bycia idiotą...
  • #15 8491479
    mirekk36
    Poziom 42  
    arturt134 --> sorry panie artur ale chyba masz jakieś kompleksy skoro twierdzisz , że ja ci takie coś zarzucam! Pomimo to jeśli to tak odebrałeś to przepraszam. Udzieliłeś dobrej porady tylko pod koniec wg mnie powołałeś się na bezsensowne wg mnie oczywiście argumenty o wadach procesorów itp ... wyjaśniłem dlaczego bezsensowych w miarę szczegółowo i że takie porady mogą wyrządzić więcej szkody niż pożytku.

    Nie zamierzam dyskutować na tematy czy można być wszystkiego pewnym w życiu bo to temat zbyt rozległy i nie dotyczy tego wątku ani w ogóle elektody.

    Trzeba umieć dyskutować.
  • #16 8491849
    kubus_puchatek
    Poziom 18  
    Czytajcie dokumentację. Nikt nie daje 100% pewności jaki stan bitu będzie po załączeniu zasilania. po drugie zmiana kodu jest delikatna ale w systemie przy próbie wykorzystania kodu (dalsza rozbudowa) okaże się że pojawiają się dziwne cuda niewidy coś działa a coś innego przestaje. Jeśli nie wyzerujemy odczytanych bitów mnożąc wartość odczytaną z rejestru przez negację maski bitowej to jedynie dodajemy nowe bity do starych więc operacja |= na jakimkolwiek rejestrze zadzaiała ale nie zawsze poprawnie. jeśli komuś się nie podoba zapis rej=rej | bity to jest po prostu amatorem bo nie wie co to MISRA i może pisać zegarek dla cioci. a zapis rej = (rej & NegMaska) | BityUstawiane zabezpiecza przed problemami i dziwnym zachowaniem. A mister mirekk36 niech dokładniej zerknie co robi ta mała poprawka którą klepnąłem zanim zacznie cokolwiek udowadniać.
  • #17 8491889
    gaskoin
    Poziom 38  
    nie ma się co kłócić o zapis rej = rej | bity; czy rej |= bity; bo to przecież to samo. tak samo nie ma się co kłócić o zapisy i = i+1, czy i+= 1; czy i++; lub ++i; bo to beznsens

    Cytat:
    rej = (rej & NegMaska) | BityUstawiane zabezpiecza przed problemami i dziwnym zachowaniem


    tu się zgodzę, ale to w przypadku długaśnych programów w których często tym rejestrem się wachluje bo zmienia się konfigurację w locie albo właściwie zmienia się tylko kilka bitów z danego rejestru.

    A projekt jest wiele mniej ambitny niż zegarek dla cioci, nikt nie rodzi się wszechwiedzący i każdy powinien o tym pamiętać. Więc nie wiem po co te nerwy (niezgodne z nickiem kubus_puchatek :P) i wymądrzanie się i chwalenie producentów. Nie ma co wynosić firm pod niebiosa, bo też zdarzają im się pomyłki bo to też są ludzie a nie bogowie. Niby skąd tyle errat do dokumentacji i wydań nowych rev procesorów (nawet u <tu fanfary> ***!!***ATMELA***!!*** <tu fanfary>).
  • #18 8492097
    mirekk36
    Poziom 42  
    kubus_puchatek napisał:
    a zapis rej = (rej & NegMaska) | BityUstawiane zabezpiecza przed problemami i dziwnym zachowaniem. A mister mirekk36 niech dokładniej zerknie co robi ta mała poprawka którą klepnąłem zanim zacznie cokolwiek udowadniać.


    Ja wiem dokładnie co robi ta maska, tyle, że jeszcze raz powiem, że w przypadku ustawiania rejestru konfiguracyjnego to jest takie działanie bez sensu.

    Szczególnie lubię określenie, że coś "zabezpiecza przed dziwnym zachowaniem, że dzieją się cuda niewida itp". Może wyjaśnisz bardziej precyzyjnie co miałeś na myśli ? czy po prostu odczuwasz wewnętrzną potrzebę bo COŚ może się zdarzyć. To nie jest kwestia czy komuś się podoba taki zapis rej = rej | coś tam tylko po prostu stosuje się odpowiedni zapis w stosunku do konkretnych potrzeb. A twoje powoływanie się na amatroszczyznę pachnie właśnie amatorszczyzną z twojej strony.

    Podpowiem, kedy warto używać albo nawet trzeba - jakiś przykład - takiego przy okazji zapisywania lub resetowania i jednocześnie MASKOWANIA.

    Gdy odwołujesz się do rejestrów portów I/O a nie chcesz zmieniać na pozostałych bitach stanów. Np

    PORTB = (PORTB 0x0F) | ( zmienna & 0xF0 );


    wtedy masz pewność, że jeśli zamiarem była tylko zmiana czterech starszych bitów portu to tylko to zostanie zmienione.

    Tymczasem gdy np ktoś ustawia rejestry konfiguracyjne po kolei odwołując się do grup bitów żeby było przejrzyście, np:

    TCCROB |= (1<<CS01) | (1<<CS00);  // ustawienie preskalera
    TCCR0B |= (1<<WGM2); // ustawienie jakiegoś tam trybu


    to takie twoje maskowanie nie ma najmniejszego znaczenia, po prostu jest niepotrzebne.

    Oczywiście w przypadku odczytu do celów analizy wartości (o czym wspomniałeś) także - zresztą nie ma co się licytować kiedy. Przepis jest prosty, wtedy kiedy trzeba. Tyle, że trzeba doczytać co i jak z czego wynika zamiast robić coś wg jedynie określonego sposobu bo mogą się zdarzyć cuda niewida!!!
  • #19 8492341
    kubus_puchatek
    Poziom 18  
    jeśli pierwotna zawartość rejestru miała 0B 0000 0111 to ustawienie podziału prescallera metodą rejestr|=0B0000 0001 na /1 daje..... nic. Powodzenia. Więc jeśli mamy inicjalizować pierwszy raz to wykonujemy wyłącznie rejestr = wartość; a nie rejestr |=wartość
  • #20 8492423
    mirekk36
    Poziom 42  
    kubus_puchatek napisał:
    jeśli pierwotna zawartość rejestru miała 0B 0000 0111 to ustawienie podziału prescallera metodąrejestr}=0B0000 0001 na /1 daje..... nic. Powodzenia.


    Oczywiście masz rację, ale bezpośrednio po resecie pierwotna wartość rejestru 0B jest znana. W pozostałych przypadkach właśnie należy zastosować odpowiednie sposoby to naturalne.
  • #21 8492465
    kubus_puchatek
    Poziom 18  
    I tu się mylisz. zakłócenia powodują że nie ma żadnej gwarancji jest tylko pobożne życzenie konstruktorów. Zresztą procesor ATtiny13 zasłyną z wywoływania nieistniejących przerwań od zegara dlatego teraz mamy już wersję ATtiny13A Norma IEC60730 definiuje że w każdej chwili wszystkie rejestry sterujące należy odświeżać.
  • #22 8492482
    mirekk36
    Poziom 42  
    kubus_puchatek --> nie będę się z tobą o to sprzeczał bo poniekąd masz rację w tym co teraz mówisz. No ale na niebiosa, skończmy takie czarnowidzenie w prostym programie testowym i próbie dojścia co jest nie tak, w zamian za to przekomarzając się o to co by było gdyby.
  • #23 8492681
    kubus_puchatek
    Poziom 18  
    Nie warto się kłócić....... duperela i pierdoła (cyt. Mrożek)

    Dodano po 46 [minuty]:

    zastąp po pierwsze to:
    ISR(TIMER0_OVF_vect)
    {
    PORTB=0xff;
    }

    Taką kombinacją:
    ISR(TIMER0_OVF_vect)
    {
    if (0xFF!=PORTB)
    {
    PORTB=0xff;
    }
    else
    {
    PORTB=0x00;
    }
    }

    Dodano po 32 [minuty]:

    Działa już?
  • #24 8493005
    gaskoin
    Poziom 38  
    mam jeszcze raz napisać, że nazwa wektora jest zła ?
  • #25 8493025
    mirekk36
    Poziom 42  
    gaskoin napisał:
    mam jeszcze raz napisać, że nazwa wektora jest zła ?


    No myślę, że powinieneś jeszcze raz napisać, bo nie dość, że kod nie jest umieszczony w znacznikach [code] to bez wcięć wygląda jak sieczka. Zatem nie trudno o takie przeoczenia. Tyle że warto 10 albo i ze 100 razy sprawdzić swoją wypowiedź / kod zanim się coś podpowie. Nie mówię, że ja nie popełniam błędów. Ale przed chwilą odbyła się batalia o zasady a tu co ?
  • #26 8530433
    kubus_puchatek
    Poziom 18  
    Jakby ktoś nie zauważył to w przerwaniu jest tylko włączana dioda i nigdzie nie jest gaszona. W efekcie człowiek nigdy nie zobaczy żeby coś się zmieniło na wyjściu. dlatego proponuję jednak podmienić obsługę przerwania.
  • #27 8530900
    gaskoin
    Poziom 38  
    Morphix napisał:
    W
    Chcę żeby uruchomiło się w nim przerwanie od Timera i wystawiło stan wysoki na wszystkich wyprowadzeniach
  • #28 8531074
    sulfur
    Poziom 24  
    mirekk36 napisał:
    jak będą dwa średniki na końcu to nic się nie stanie. Nie mniej jednak takie używanie dyrektywy #define to niestety efekt braku zrozumienia dobrych zasad programowania. A poza tym warto zapamiętać, że w gdy definiujesz coś #define to nigdy właśnie w definicji nie stawiasz średnika na końcu (właśnie po to)


    Nie wiem co kolega ma na myśli pisząc "właśnie po to", ale:
    1. To prawda, że dwa średniki nie robią nic, tak jak trzy, pięć i dziesięć.
    2. W "define" nie wstawia się średnika aby wymusić ten średnik w kodzie oraz umożliwić używanie definicji jako argumentu funkcji. Zgoda, że zapis bez średnika uważany jest za dobre zasady programowania.
    #define ASDF(x) x
    funkcja(ASDF(5));

    Gdyby definicja była ze średnikiem, to powyższy zapis spowodowałby błąd kompilacji.

    Pomijam fakt, że w kodzie autora wątku średnik występuje i tak wcześniej, więc nie ma zastosowania w powyższym.
  • #29 8531321
    mirekk36
    Poziom 42  
    Za to trzeba szczególnie uważać na takie definicje:

    #define TIMER0_START TIMSK0 |= (1<<TOIE0); TCCR0B |= (1<<CS00) | (1<<CS01); 


    i lepiej zamiast nich zrobić normalną funkcję inline, żeby później nie mieć totalnej kiszki gdy się zastosuje zapis jak poniżej ;)

    if( cos_tam ) TIMER0_START;
  • #30 8531393
    sulfur
    Poziom 24  
    Jak dodamy do tego oszczędność w stosowaniu nawiasów
    #define DWARAZYX(x) 2*x
    DWARAZYX(2+2)
    to mamy bardzo ładny trójkąt bermudzki i zmarnowanych kilka dni na szukanie dziury w całym.

    Są to argumenty, których używają "rasowi programiści C++", aby nie używać makrodefinicji, ponieważ jest to zło.
REKLAMA