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

[Atmega8][C]Przerwania / prescaler

vectra96 27 Wrz 2009 12:11 2501 6
REKLAMA
  • #1 7062703
    vectra96
    Poziom 12  
    Witam ponownie, znalazłem wcześniej na elektrodzie program zegarka na LCD 2x16, który niestety nie działał prawidłowo (migały niezrozumiałe znaki na lcd). W celach edukacyjnych postanowiłem przerobić procedury obsługi wyświetlacza, co dało efekt końcowy jaki teraz mam czyli działający program zegara na LCD, ale jest jeden problem. Zegar odmierza 1 sek w ciągu rzeczywistych 8 sek. Poniżej instrukcje odpowiadające za przerwania. Czy może mi wytłumaczyć w jaki sposób jest tu odmierzany czas?

    Z tego co zrozumiałem z poniższego zapisu liczenie odbywa się przy użyciu Timera0 ustawionego na CS01 (0x02) clk8(w komentarzach wpisane jest że 4?), co daje dla F_CPU 8000000 / 8 - 1000000 impulsów na 1 sek., liczenie zaczyna się od 9 do 255 (czyli do 247).
    Według komentarzy w poniższym kodzie zegar jest podzielony przez 4? W ciągu sekundy mają się wykonać 249 przepełnienia tak?

    Niestety ale nie ogarniam tego , czy może mi ktoś napisać jak to jest liczone?


    
    SIGNAL (SIG_OVERFLOW0)               //funkcja obsługująca przerwanie od timera0
    {
       TCNT0=9;                     //wpisanie do licznika timera0 wartosci poczatkowej
       stala0++;                     //w clu sktócenia cyklu zliczania(powinno byc 10 dla rezonatora 8MHz
       if(stala0>249)                  //ale ze względu na to że rezonator ma 8.000400MHz wpisane jest 9 w celach kompensacji)
       {                           //timer0 zlicza impulsy zegara podzielone przez 4 czyli w ciągu sekundy było by 2000000 impulsów(zakładając że do TCMC0 wpisujemy za każdym razem 5) (pojemność timera0 i tak wynosi tylko 255)
          stala0=0;                  //dzięki preskalerowi = 2 tych impulsów będzie 1000000 czyli 16 * 250 * 250.
          stala1++;
          if(stala1>15)
          {
             stala1=0;
             sekundy++;
          }
       }
    
        ...
    
    
       }      
       
       TIFR=1<<TOV0;                                 
    }
    
    
    
    SIGNAL (SIG_INTERRUPT1)               //obsługa przerwania z wejścia int 1
    {
       b=0;                        //ustaw stałą b na zero
       GIMSK=0<<INT1;                  //zablokuj przerwanie z wejścia INT1
    }
    
    
    
    
    int main(void)
    { 
    ....
    
    TIMSK=1<<TOIE0;                              //w rejestrze maskowania przerwań(TIMSK) wpisz 1 na miejsce bitu TOIE0 (zezwolenie na przerwanie od układu timera0 spowodowane przepełnieniem)         
       TCNT0=9;                                 //wpisz wartośc poszątkową do licznika timera0
       TCCR0=0x02;                                 //preskaler ustaw na 2 (CLK/8)
       GIMSK=1<<INT1;                              //włacz przerwanie z INT1
       MCUCR=0x02;                                 //przerwanie z INT1 wyzwalane zboczem opadającym
    
    ...
    
  • REKLAMA
  • Pomocny post
    #2 7062765
    skalsky5000
    Poziom 21  
    Wyłącz preskaler, bit CKDIV8
  • REKLAMA
  • #3 7063888
    vectra96
    Poziom 12  
    Witam zmieniłem w ustawieniach w zakładce Fuses z wartości SUT_CKSEL "Int. RC Osc. 1 MHz;Start-up time: 6CK + 0 ms" na wartość "Int. Rc Osc. 8Mhz; Start-up time: 6 CK + 0 ms" i na ekranie lcd migają litery cyfry itp. Gdy zmienię na pierwszą wartość normalnie wyświetlają się komunikaty na LCD, czy coś źle robię lub nie tę pozycję wybieram?
  • REKLAMA
  • #4 7064373
    Madergames9
    Poziom 15  
    Tak jak kolega wcześniej napisał, wyłącz w fusebits fuse odpowiedzialny za dzelenie przez 8. Powinno pomóc :D
  • #5 7064726
    vectra96
    Poziom 12  
    A możesz powiedzieć która opcja odpowiada za bit CKDIV8?


    [Atmega8][C]Przerwania / prescaler
  • REKLAMA
  • Pomocny post
    #6 7064817
    _Robak_
    Poziom 33  
    Przeczytaj sobie w datasheecie czy dzielisz zegar przez 8 czy przez 4 ;) Nie wiem co koledzy z tym fuse bitem ckdiv8, atmega8 nie ma takiego ;) Vectra96 sciagnij tez sobie program avrcalc i tam szybko bedziesz mogl wyznaczyc konfiguracje timerow :)
  • #7 7065035
    vectra96
    Poziom 12  
    K***a teraz to se zablokowałem atmege wybierając przez pomyłkę Ex. Clock; Start-up time: 6 CK + 0ms.

    Zna ktoś prostą metodę na odblokowanie ?

    Znalazłem coś o rezonatorze kwarcowym, ale prawdę mówiąc nie wiem czy w moich szpargałach mam coś takiego czy też to jest oscylator kwarcowy. Pisze na nim 12.000 HELE. 9G. Znalazłem też poniższy temat, w którym ktoś pisał że chyba da radę odblokować przy użyciu "multimetr, który ma funkcję generowanie przebiegu prostokątnego" mam coś takiego co prawda kupione za 8 zł w markecie ale działa. Czy da radę za pomocą tego odblokować? Jeżeli tak to jak to podłączyć?

    Dodano po 26 [minuty]:

    Dobra sprawa rozwiązana, znalazłem drugi procek atmega8, zaprogramowałem go według poniższego kodu, podłączyłem dowolną linię portu b do XTAL1 i XTAL2 zablokowanego procka (oczywiście podpiełem zasilanie do odpowiednich portów) wsadziłem zablokowany procek do programatora i uzyskałem połączenie z AVR Studio, przestawiłem fusebity na poprawne czyli 1 MHz i działa ;]

    #include <avr/io.h>
    
    int main(void)
    {
      while(1)
      {
        DDRB=0xFF;
    	PORTB=0xFF;
        asm("NOP");
        DDRB=0xFF;
    	PORTB=0x00;
      }
    } 
    



    Pozostaje jeszcze problem z odmierzaniem sekundy, _Robak_ piszesz że w tym procku nie ma CKDIV8? tak jak już pisałem niestety ale nie rozumiem kodu który zamieściłem w pierwszym poście. Nie wiem jak to liczyć.

    Dodano po 29 [minuty]:

    Witam, problem rozwiązany wystarczyło faktycznie ustawić "Int. Rc Osc. 8Mhz; Start-up time: 6 CK + 0 ms", oraz zwiększyć opóźnienia w funkcji wyświetlacza ;] Dziękuję za udzieloną pomoc!
REKLAMA