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

Atmega8L przepełnienie timer2 codevision

Piecia 18 Sty 2009 18:53 2265 28
  • #1 6018582
    Piecia
    Poziom 14  
    Witam
    Mam problem z programem zliczającym przepełnienia timer2. Do lini TOSC1/2 podłączony mam kwarc zegarkowy 32,768kHz, chciałbym wykorzystać przerwanie od przepełnienia tego licznika do odliczania równej sekundy oraz wyświetlić wynik na ekranie LCD. Oto kod programu:
    
    long int licz=0;
    
    void init_timer(void)         //Inicjalizacja timera
     {
       TIMSK = 0x40;                //inicjalizacja przerwania wywołanego przepełnieniem timera2 ( bit TOIE2->1)
       ASSR = 0x08;                 //tryb asynchroniczny
       TCCR2 = 0x05;                //preskaler 128
     }
    
    interrupt [TIM2_OVF] void timer2_compa_isr(void)
    {  
        licz++;
     
    }
    
    
    void main(void)
    { 
    #asm("sei");
      init_timer(); 
      
        
     
      while(1)                   
      {
         itoa(licz, tekst);
         pisztekst(tekst); 
         delay_ms(500);
         
      }
               
    #asm("cli");  
    }
    


    na ekranie LCD pojawiaja się jedynie jakies krzaki..

    z góry dziekuję za pmoc

    Piecia

    Proszę używać znaczników [code] - uzupełniłem.
    [zumek]
  • #2 6018890
    Konto nie istnieje
    Poziom 1  
  • #3 6019590
    Piecia
    Poziom 14  
    atom1477 napisał:
    Bo problem masz z wyświetlaczem LCD a nie z Timerem.
    A gdzie jakaś inicjalizacja wyświetlacza LCD?


    Wszystko jest z tym ze nie umieścilem tego w poscie... wyświetlacz LCD działa bez zarzutów...
  • #4 6019694
    Jerzy_W
    Poziom 14  
    Dwie sprawy

    1) Zadeklaruj zmienną licz jako volatile
    2) Odblokowanie przerwań "sei" po inicjalizacji LCD i Timera
  • #5 6020315
    Konto nie istnieje
    Poziom 1  
  • #6 6020758
    Piecia
    Poziom 14  
    napewno cos jest z przerwaniem, bo usówając funckje przerwania wszystko dziła bez zarzutów i wyświetla "zero". Być moze ustawy rejestró są złe??? Wyświetla mi "utD" dokladnie a powinno zwiekszac i wyświetlac zmienna licz...
  • #8 6026795
    Piecia
    Poziom 14  
    nic to nie dało... Próbowałem jeszcze załączać diody podłączone do portu uC w przerwaniu także bez skutku.
  • #9 6027057
    Konto nie istnieje
    Poziom 1  
  • #10 6034648
    Piecia
    Poziom 14  
    nic to nie daje. Juz nie wiem co mam robić próbowałem jeszcze użyć LED - do portd.7 - w sygnalizacji przepełnienia T2. Przesyłam calutki kod programu:

    
    #include <mega8.h>
    #include <delay.h>
    
    int licz = 4;
    
    // Timer 2 overflow interrupt service routine
    interrupt [TIM2_OVF] void timer2_ovf_isr(void)
    {
     licz++;
         
    }
    
    
    // Declare your global variables here
    
    void main(void)
    {
    // Declare your local variables here
    
    // Input/Output Ports initialization
    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTB=0x00;
    DDRB=0x00;
    
    // Port C initialization
    // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTC=0x00;
    DDRC=0x00;
    
    // Port D initialization
    // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTD=0x00;
    DDRD=0xC0;
    
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    TCCR0=0x00;
    TCNT0=0x00;
    
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: Timer 1 Stopped
    // Mode: Normal top=FFFFh
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer 1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    // Timer/Counter 2 initialization
    // Clock source: TOSC1 pin
    // Clock value: Timer 2 Stopped
    // Mode: Normal top=FFh
    // OC2 output: Disconnected
    ASSR=0x08;
    TCCR2=0x05;
    TCNT2=0x00;
    OCR2=0x00;
    
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    MCUCR=0x00;
    
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x40;
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    TIFR = 0xC0; 
    
    
    
    // Global enable interrupts
    #asm("sei")
    
    while (1)
          {
        if(licz%2 == 1) 
         PORTD.7 = 1;
           
         
        if(licz%2 == 0)
         PORTD.7 = 0;
         
         
    
          };
    #asm("cli")
    }
    


    Nic jednak to nie dało. Z układem nic sie nie dzieje, a wszystko wygląda na to ze program główny także nie działa.

    pozdrawiam
  • #12 6035037
    Piecia
    Poziom 14  
    _Robak_ napisał:
    zmien
    int licz = 4;

    na
    volatile int licz = 4;


    Jak to nie zadziala to na poczatku programu przypisz wartosc do zmiennej licz np 1 a potem w przerwaniu daj podstawienie np licz=5 i zobacz co bedzie wyswietlac


    dalem tak jak zrobiles i dioda swieci caly czas. Wniosek jaki sie narzuca to to ze przerwanie nie dziala. Dioda powinna mrugac co sec.
  • #13 6035814
    _Robak_
    Poziom 33  
    z tego co widze to masz wszystkie porty ustawione jako wejscie, te co steruja dioda i lcdkiem ustaw jako wyjscia. Przy tak malo skomplikowanym programie wywal te czesci z code wizarda bo to sie ciezko czyta, a kodu starczy kilka linijek ;)
  • #14 6038192
    Piecia
    Poziom 14  
    Dioda podłączona jest do PORTD.7:
     DDRD = 0xC0;

    Czyli ustawiona jako wyjście. Pozostałe linie są jako wejścowe, bo narazie tsama diode chce wysterowac.:)
  • #15 6038908
    _Robak_
    Poziom 33  
    Na razie sprawdz czy w ogole sie przerwanie wywoluje, bo dioda moze szybko mergotac i ci sie wydaje ze swieci bo mozesz miec cos z fusami np.
    
    #include <mega8.h> 
    #include <delay.h> 
    
    volatile int licz ; 
    
    // Timer 2 overflow interrupt service routine 
    interrupt [TIM2_OVF] void timer2_ovf_isr(void) 
    { 
     licz=0; 
          
    } 
    
    
    
    void main(void) 
    { 
    
    PORTD=0x00; 
    DDRD=0xC0; 
    
    ASSR=0x08; 
    TCCR2=0x05; 
    TCNT2=0x00; 
    OCR2=0x00; 
    
    
    TIMSK=0x40; 
    
    ACSR=0x80; 
    SFIOR=0x00; 
    TIFR = 0xC0; 
    
    #asm("sei") 
    licz = 1;
    while (1) 
          { 
        if(licz%2 == 1) 
         PORTD.7 = 1; 
            
          
        if(licz%2 == 0) 
         PORTD.7 = 0; 
          
          
    
          }; 
    #asm("cli") 
    }
    


    I teraz zobacz czy ci sie swieci dioda czy nie, w zaleznosci czy sterujesz nia zerem czy jedynka
  • #16 6040128
    rpal
    Poziom 27  
    Na poczatek zasugeruję aby kolega napisał co ma ustawione w opcjach kompilatora. Mam ten produkt (legalnie kupiłem) i niestety musze stwierdzić że zachowanie zmiennych mocno zalezy od opcji kompilatora.
    A może rzecz najwazniejsza. Gdzie się podziało zainicjowanie licznika podczas wejścia w procedurę przerwania, drogi kolego ?
    W ogóle to nie bardzo rozumiem sam pomysł. Z tego co wiem to podłączać kwarc zegarkowy można dopiero do ATMega16 oraz 32 w AtMega8 to chyba nie chodzi.
    Osobiście proponuję zrobić to nieco inaczej. Mianowicie wyzwalaj sobie tym swoim przebiegiem zegarkowym np. przerwanie INT0. Zadeklaruj globalną zmienną którą to przerwanie będzie powiękaszać przy każdym wejściu w procedurę przerwania a kiedy przekroczy jakąś przyzwoitą wartość zeruj ją wraz ze zmianą stanu portu wyjściowego i tak w koło wojtek. Przynajmniej sprawdzisz czy ukłąd w ogóle działa i generuje jakiś przebieg zegarowy.
    CodeVision ma swój kreator który jakby go nie krytykować, odwala lwią część roboty za projektanta , zwłaszcza tego niedoświadczonego.
    Na mój gust to po prostu nie wyzwalasz żadnych impulsów zegarowych.
    Kolejna sprawa po co ta zamiana postaci itoa().
    Jak już generowanie impulsów Tobie zaskoczy to wystarczy na podstawie licznika pobierać dane z tablicy znaków i w ten sposób wyświetlać tekst na LCD. POza tym nie widzę tam inicjalizacji LCD więc w ogóle nic nie możesz wyświetlić. Napisz coś więcej o schemacie bo sprawa jest iście banalna.
    W ogóle dziwię się że coś tam się krzaczy bo nawet śladów po obsłudze LCD w tym kodzie nie ma. Masz kreatora wystarczy tam wejść a sam ci tę obsługę podłaczy. MOże zacznij od poczatku pozwól aby program cokolwiek na tym LCD napisał. Potem zajmij się przebiegiem przerwania, które możesz sobie dla testów zrobić na wewnetrznym przebiegu zegarowym, bez jakiś tam kwarców od zegarka, które nie wiadomo czy w ogóel działają :)
    Jeśli PORTD jest jako wejście a tylko 7 pin jest wyjściem to inicjowanie powinno wyglądac tak:
    // Port D initialization
    // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTD=0x00;
    DDRD=0x80;

    POza tym napisz sobie taki prosty programik dla testów LED-a
    
    void main()
    {
    while(1){
    PORTD.7=0;
    delay_ms(500);
    PORTD.7=1
    delay_ms(500);
    }
    }
    

    To wystarczy aby led zaczął do Ciebie mrugać:)
  • #17 6043154
    Piecia
    Poziom 14  
    A wiec tak:

    rpal napisał:
    Gdzie się podziało zainicjowanie licznika podczas wejścia w procedurę przerwania, drogi kolego ?

    oto ona:
    
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x40;
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    TIFR = 0xC0;
    

    Cytat:

    W ogóle to nie bardzo rozumiem sam pomysł. Z tego co wiem to podłączać kwarc zegarkowy można dopiero do ATMega16 oraz 32 w AtMega8 to chyba nie chodzi.

    Radze dokładnie przeglądnąć datasheeta, dla ułatwienia str.123


    Cytat:

    Kolejna sprawa po co ta zamiana postaci itoa().
    Jak już generowanie impulsów Tobie zaskoczy to wystarczy na podstawie licznika pobierać dane z tablicy znaków i w ten sposób wyświetlać tekst na LCD. POza tym nie widzę tam inicjalizacji LCD więc w ogóle nic nie możesz wyświetlić. Napisz coś więcej o schemacie bo sprawa jest iście banalna.
    W ogóle dziwię się że coś tam się krzaczy bo nawet śladów po obsłudze LCD w tym kodzie nie ma. Masz kreatora wystarczy tam wejść a sam ci tę obsługę podłaczy. MOże zacznij od poczatku pozwól aby program cokolwiek na tym LCD napisał. Potem zajmij się przebiegiem przerwania, które możesz sobie dla testów zrobić na wewnetrznym przebiegu zegarowym, bez jakiś tam kwarców od zegarka, które nie wiadomo czy w ogóel działają :)

    LCD działa bez zarzutów. Jednak widze ze kolega niesłusznie przeczytał tylko pierwszego posta i nie zainteresował sie pozostałymi. W odpowiedziach wyraźnie napisane jest:

    Piecia napisał:
    atom1477 napisał:
    Bo problem masz z wyświetlaczem LCD a nie z Timerem.
    A gdzie jakaś inicjalizacja wyświetlacza LCD?


    Wszystko jest z tym ze nie umieścilem tego w poscie... wyświetlacz LCD działa bez zarzutów...


    Cytat:

    Jeśli PORTD jest jako wejście a tylko 7 pin jest wyjściem to inicjowanie powinno wyglądac tak:
    // Port D initialization
    // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTD=0x00;
    DDRD=0x80;

    POza tym napisz sobie taki prosty programik dla testów LED-a
    
    void main()
    {
    while(1){
    PORTD.7=0;
    delay_ms(500);
    PORTD.7=1
    delay_ms(500);
    }
    }
    

    To wystarczy aby led zaczął do Ciebie mrugać:)[/code]


    Okej kolego, zgadza sie. Będzie mrugać:) Jednak mi nie o to chodzi. Chce odmierzać równe czasy przepełnienia T2 a nie jakies banalne zapalanie diodek. Interesuje mnie tylko obsluga T2 zeby móc wyświetlacz np godzine i date na wyświetlaczu a mruganie diodami to tylko testowa wersja programy. Jesli chodzi o inicjalizacje pinów PORTu D to piny 7 i 6 bo w sumie mam podłączone dwie diody ale chce tylko jedną chce sterować. I następnym razem sugeruje dokładniejsze czytanie i oszczędzenie sobie głupich uwag.
  • #18 6043598
    Konto nie istnieje
    Poziom 1  
  • #19 6043679
    rpal
    Poziom 27  
    Rozumiem że kolega za głupie uważa przykład o analizie poprawności działania kodu oraz eliminacji błędów w sprzęcie poprzez banalne mruganie diodami. Jeśli Twoja godność ucierpiała biję się w pierś i przepraszam. Muszę jednak stwierdzić że wszelkie błędy aliminuje się raczej małymi krokami a nie hurtem jak leci. Odpalanie prototypu z żadka kończy się sukcesem za pierwszym razem, czego jak widzę jesteś sam przykładem. Skoro Timer Tobie nie działa to może zastanów się i jednocześnie sprawdź co jest tego powodem. Pierwszy krok to sprzęt drugi to program. Ani ja ani inni koledzy nie są alfą i omegą aby zdalnie odgadnąć tajniki Twojego prototypu.
    Fakt źle zrozumiałem treść postów ale i też metodologia jaką przyjąłem radząc miała na celu eliminację najczęstszych błedów. Na koniec pozostaje mi życzyć powodzenia w uruchamianiu zegara czasu rzeczywistego i może pomyśl czy w ogóle masz tam jakikolwiek przebieg zegarowy o częstotliwości zbliżonej do 32768 Hz. Cytując kol.Frediego Chopina i jego rady, proponuję zajżeć do noty katalogowej jako żródła wiedzy. Na koniec jeszcze raz przeproszę za wszystko i więcej głupiej rady koledze nie udzielę.
    A tak przy okazji pisząc o głupich radach i wytykaniu nieistniejących błedów w kodzie załaczam typową procedurę obsługi przerwania w CodeVision i tym co nazwałem inicjowaniem licznika przy wejściu do przerwania. Ten kompilator ma kreator i generalnie program sam się zrobi (przynajmniej tak prosty o którym piszesz) oczywiście pod warunkiem prawidłowego , jego urzycia. Jeśli nie zainicjujesz tego rejestru TCNT2 przy wejściu w przerwanie to na niewiele ono się zda. Poniżej przykład dane oczywiście przypakowo zaczerpnąłem z własnej wyobrażni.
    // Timer 2 overflow interrupt service routine
    interrupt [TIM2_OVF] void timer2_ovf_isr(void)
    {
    // Reinitialize Timer 2 value
    TCNT2=0x0A;
    // Place your code here
    
    }

    Jaka załapiesz na tym przykładzie w czym rzecz sam sobie pomożesz.
    Procedura przerwani aprzytoczona w pierwszym poście dotyczy obsługi porównania, Ty zaś piszesz o przepełnieniu. Mój przykład dotyczyczy przepełnienia zgodnie z tym co piszesz.
  • #20 6043747
    Konto nie istnieje
    Poziom 1  
  • #21 6043819
    rpal
    Poziom 27  
    atom1477 napisał:
    W ATMEGA8 od rezonatora 32768Hz trzeba podłączyć kondensatory jakieś 33p idące do masy, bo te wewnętrzne nie działają. Przynajmniej tak mi się wydaje.

    rpal, wyjaśnij mi tej kod w obsłudze przerwania bo nie pojmuję:

    chodzi o to że wchodząc w przerwanie spowodowane przepełnieniem czyli zliczaniem od wartości początkowej w przykładzie 0Ah do FFh, licznik dalej sobie liczy przechodząc przez zero i dalej w górę. Chcąc nadać jakikolwiek sens temu przerwaniu czyli aby było generowane co ustalony okres czasu (określony przez częstotliwość zegarową i oczywiście ilość zliczonych impulsów) trzeba wartość tego licznika najpier zainicjowac na wstępie programu a potem przy każdym wejściu w obsługę przerwania. O to biega. Kolega będący autorem postu, swój problem opisuje "na raty" tytuł postu jest o przepełnieniu a kolejne przykłądy programu raz o przepełnieniu innym razem o porównywaniu. Nie sądzę aby ktoś mu pomógł kiedy pisze raz o zupie innym razem o czym innym :)
    Teraz tak sobie myślę (zakłądam że napisał program poprawnie pod względem skojarzenia odpowiednich przerwań) że te przerwania wykonują mu się przy każdym przepełnieniu które powiedzmy następują spontanicznie :) czyli co 256 impulsów zegarowych a ponieważ zmienna zawarta w przerwaniu jest tylko powiększana i nic poza tym wychodzą mu z tego powodu krzaki. Jednak nie podejmuję się dogłębnej analizy bo jeszcze wyjdzie że to głupie rady :)
    itoa(licz, tekst); 
    na tym poziomie wiedzy jaką nam przedstawił to nie widzę żądnej deklaracji zmiennej tekst więc i to może byc przyczyną błędów.
  • #22 6044138
    Konto nie istnieje
    Poziom 1  
  • #23 6044221
    rpal
    Poziom 27  
    Możesz się ze mną nie zgadzać ale pisanie programów ma byc takl zrobione aby treśc była jasna dla każdego postronnego obserwatora. Program tutaj przedstawiony jest delikatnie mówiąc "po bałaganiarsku" a kolejna może najważniejsza rzecz to tzw. styl czyli zasady którymi pisanie się rządzi. Dziś przepełnienie ma wynikac co 256 impulsów jutro co 255 ktoś tego nie zauważy i mamy tzw. kłopot. Nie liczyłęm impulsów ale wiem że takie sa po prostu zasady gry. Forum to pomoc na zasadach życzliwości a nie nauka programowania lub konstruowania. Z tego nikt nikogo nie wyręczy. PZDR
  • #24 6044251
    Konto nie istnieje
    Poziom 1  
  • #25 6044297
    rpal
    Poziom 27  
    Ten kompilator działa wrednie bo w zależności od jego opcji które ustawia się poprzez menu można zrobic tak ze liczba INT będzie CHAR i to w cale nie jest żart służę przykłądami jakby co :) O tym co kolega ma w opcjach niestety nic nie wspomina. Assembler w tym względzie jest jednoznaczny i prosty.
    A takl na marginesie my sie tu produkujemy a autor delikatnie odpłynął więc może jest po prostu po kłopocie. W sumie co nas to obchodzi skoro nie melduje że coś nie teges :) Zajmijmy się np. TV albo czymś tam innym.
  • #26 6046359
    Piecia
    Poziom 14  
    Na poczatek załączam dwa pliki .hex i .c, o ktore mnie proszono.. Jeden z nich jest sterownik wyświetlacza LCD w którym probowalem zaimplementowac przerwanie od przepelnienia T2, drugi natomiast zapalanie diody powodowane tym ze przerwaniem.

    Nie zrozumielismy sie z kolega Rpal. Można także wywołać przerwanie powodowane przepełnieniem licznika. To własnie zamierzam uczynić. A druga sprawa dotycząca bardziej prywatnych sfer to chciałbym podkreślić, że niektórzy maja prace a dodatkowo sie uczą(być może dla Ciebie jest to abstrakcja) i "niestety" nie mogą tak czesto jak kol Rpal przesiadywać na forum - Rpal przepraszam, ale forum to nie jest komunikator GG.

    W załączeniu są programy które podkreślam kompilują sie bez problemów. Musze jednak przyznac i przeprosic za ten burdel, który zrobilem zamiszczając część kodu programu. Mam nadzieje ze kody które przeslalem Wam w zalaczniku nie przyniosa kolejnych problemow:)) Głównie zależy mi na obsłudze diody gdyż jest to program bardzo prosty i jesli uda mi sie go uruchomic to na bank z LCD nie bede mial problemow.

    pozdrawiam serdecznie
  • #27 6046498
    Konto nie istnieje
    Poziom 1  
  • #28 6048326
    Piecia
    Poziom 14  
    Zgadza sie Rpal przyznaje racje funkcja przerwania jest zle dobrana. Ale to tylko w kodzie programu "zegar"(bo pozniej juz zmienilem - timer2 - sterowanie dioda). Problem jednak jest banalny- Walniety kondensator 22pF pobudzający kwarz- wymienilem na 27pF i wszystko smiga. Temat uważam za zamknięty i dziekuję wszystkim za pomoc:)

    pozdr
  • #29 6049070
    rpal
    Poziom 27  
    No właśnie miałem tobie napisać że drugi program jest OK bo w przerwach miedzy byciem na forum a chorowaniem obejżałem go sobie. Hipoteza że nie było przebiegu zegarowego była więc słuszna ? Na początku właśnie to sugerowałem, inni chyba także. Kup sobie JTAGA zdiagnozuje prawie wszystko i to bardzo pomocne narzędzie. Z CodeVison niestety nie działa ta tańsza wersja ale AVR Studio obsługuje. PZDR
REKLAMA