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

[MEGA16] [MEGA16][C] Timer 0 nie zlicza poprawnie przy kwarcu 16MHz i prescalerze 64

mog123 11 Sie 2009 00:37 1173 13
REKLAMA
  • #1 6879313
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    Witam, mam nastepujacy problem - napisalem timer(uzywajac timera 0) do kontroli czasu w programie(glownie serw). Ustawilem prescaler na 64, co przy kwarcu 16MHz daje 250kHz, czyli jeden takt timera odlicza 1/250000 s. czyli 0,000004s. Potem "timer pomocniczny" sumuje wszystkie przepelnienia do 1 sekundy (czyli tysiac razy).

    //   Ustawienie licznika 0
       TCCR0=_BV(WGM01)|_BV(CS01)|_BV(CS00);
       OCR0= 0xFA; //zliczaj do 250 impulsow (0,001s)
    
    //   Przerwania   
       TIMSK=_BV(OCIE1A)|_BV(OCIE1B)|_BV(OCIE2)|_BV(OCIE0);
       TIFR =_BV(OCF1A)|_BV(OCF1A)|_BV(OCF2)|_BV(OCF0);
    
    ISR(TIMER0_COMP_vect) // przy przerwaniu (gdy licznik dolicz do OCR0)
    {
       backup_tmr++;
       if(backup_tmr==1000){
                                         t.second++;
                                         backup_tmr=0;
                                        }
       if(t.second==60)
       {                                
        t.second=0;                        // wyzeruj licznik sekund oraz
        if (++t.minute==60)        // inkrementuj licznik minut i sprawdź czy jest ich 60
        {                                // jeśli tak to:
          t.minute=0;                // wyzeruj licznik minut oraz
          if (++t.hour==24)        // inkrementuj licznik godzin i sprawdź czy jest ich 24
          {                                // jeśli tak to:
            t.hour=0;                // wyzeruj licznik godzin
          }
        }
      }
    }


    Dalej chce uzyc tego "czasomierza" do kontroli programu/serwokontrolera w taki sposob:
    int main()
    {
    
       tmr_setup();
       t.second=0;
       t.minute=0;
       t.hour=0;
       while(1)
       {
       if((t.second%6)==0)   for(i=0;i==16;i++)	serwo[i]=0x20;
       if((t.second%4)==0)   for(i=0;i==16;i++)	serwo[i]=0x94;
       }   
       
    
    } 
    


    No ale pozycje serw sie nie zmieniaja, zostaja na swoim miejscu inicjujacym :/ sterownik dziala na bank(sprawdzalem przebiegi na oscyloskopie), tylko ta kontrola czasu cos nawala przez co nie moge zmieniac pozycji. Fusy oczywiscie ustawione(low:CE high:99 )
  • REKLAMA
  • #2 6879346
    Demoman
    Poziom 17  
    Posty: 134
    Pomógł: 31
    Ocena: 3
    pokaż deklaracje zmiennej "t"... jest volatile?
  • REKLAMA
  • #3 6879351
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    typedef struct
    {
      uint8_t second;
      uint8_t minute;
      uint8_t hour;
    } time;
    
    time t;  

    Jest w pliku naglowkowym - "defines.h"
  • #5 6879359
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    dalej nic.
  • #6 6879373
    Demoman
    Poziom 17  
    Posty: 134
    Pomógł: 31
    Ocena: 3
    niczego konkretnego się nie dopatrzyłem ;) może pora nie sprzyja...

    zastanawia mnie jednak ta pętla while:
    
       if((t.second%6)==0)   for(i=0;i==16;i++)   serwo[i]=0x20;
       if((t.second%4)==0)   for(i=0;i==16;i++)   serwo[i]=0x94; 


    Stan w tablicy serwo (cokolwiek tam się znajduje) jest do 4ej sekundy 0x94 potem do 6 0x20 i możliwe że dalej jeśli nic tam nie zmieniasz... takie były Twoje założenia?
  • #7 6879383
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    Inicjuje tablice serwo:
    vu8 serwo[16] = {0x90,0x40,0x50,0x66,0x70,0x76,0x80,0x90,0x90,0x80,0x76,0x70,0x60,0x50,0x40,0x30};


    vu8 to volatile unsigned char

    W 4tej sekundzie powinny wszystkie sie zmienic na 0x94, potem w szostej na 0x20, potem w osmej wrocic do 0x94 w 12tej utrzymac 0x94 w 16tej dalej utrzymac 0x94 w 18tej przelaczyc 0x20 itd. - Na szybkiego wymyśliłem jakis sposob przelaczania serw by spawdzic wlasnie jak im to wychodzi, a one dalej stoja na pozycjach inicjujacych.
  • #8 6879510
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    Witaj Kolego.

    Chciałem Cię zapytać jak masz zadeklarowaną zmianą typu 'time' powinieneś mieć w pętli głównej volatile time t a w przerwaniu extern volatile t. Tak masz zrobione ? Jeśli nie to koniecznie tak musi być. No chyba że masz tylko jeden plik w którym masz wszystko umieszczone to tylko volatile time t.
  • REKLAMA
  • #10 6879516
    flapo213
    Poziom 21  
    Posty: 566
    Pomógł: 35
    Ocena: 10
    Kolego 'Terminator' chyba jednak wydaje mi się że pętla pójdzie choć skłądnia nie jest delikatnie mówiąc powalajaca, Twoja wersja jest taka jak sie stosuje, z tym == nigdy nie próbwałem ale for śmiga do momentu spełnienia warunku więc skoro i nie jest 16 to zacznie procedurę inkrementacji. Zaciekawiło mnie aż sprawdzę po południu. Pozdrawiam

    Dodano po 2 [minuty]:

    Kolego a nie zapomniałeś o " sei(); " to globalne włączenie systemu przerwań, zamieściłeś tylko kawałek kod więc nie wiem czy włączyłes globalny system przerwań i przerwanie od Timera 0. Pozdrawiam
  • REKLAMA
  • #11 6879521
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    flapo213 napisał:
    Kolego 'Terminator' chyba jednak wydaje mi się że pętla pójdzie choć skłądnia nie jest delikatnie mówiąc powalajaca, Twoja wersja jest taka jak sie stosuje, z tym == nigdy nie próbwałem ale for śmiga do momentu spełnienia warunku więc skoro i nie jest 16 to zacznie procedurę inkrementacji. Zaciekawiło mnie aż sprawdzę po południu.

    To jakiś nowy standard C? Nie sprawdzaj, bo szkoda czasu - pętla for wykonuje się jeśli warunek jest spełniony - ten nie jest spełniony od razu, więc pętla nie wykona się nigdy.

    Uwierz - kompilator nie rozróżnia dwóch wersji - jest (była i będzie) tylko jedna.

    4\/3!!
  • #12 6879803
    Demoman
    Poziom 17  
    Posty: 134
    Pomógł: 31
    Ocena: 3
    No faktycznie... for jest nie "halo" xD

    Sprawdzanie późną porą ma swoje minusy ;)

    Aktualnie nie zmieniasz stanu ani jednego serwa, popraw tego for'a.
  • #13 6880519
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    tak samo pisanie pozna pora ma swoje minusy XD
    Cos mi sie powalilo i myslalem ze to jest "wykonuj do" XD
    zaraz przetestuje.

    i sei() jest.

    edit: smiga!
    dzieki wielkie ;D
  • #14 6885804
    mog123
    Poziom 15  
    Posty: 199
    Pomógł: 3
    Ocena: 8
    Czy uwazacie ze moja matma zwiazana z liczenie mczasu sie zgadza? Bo cos za szybko przelaczaja sie te pozycje.

Podsumowanie tematu

✨ Problem dotyczy niepoprawnego zliczania przerwań timera 0 w mikrokontrolerze AVR przy kwarcu 16 MHz i prescalerze 64. Timer ustawiony jest w trybie CTC z OCR0=0xFA, co powinno generować przerwania co 1 ms. W przerwaniu liczona jest zmienna backup_tmr do 1000, aby uzyskać 1 sekundę. Wątpliwości pojawiły się wokół deklaracji zmiennej typu strukturalnego "time t" używanej do przechowywania sekund, minut i godzin – zalecane jest użycie słowa kluczowego volatile, aby zapewnić poprawną synchronizację między przerwaniem a głównym programem. Dodatkowo wykryto błąd w pętli for, gdzie warunek i==16 uniemożliwiał jej wykonanie; poprawny warunek to i
Wygenerowane przez model językowy.
REKLAMA