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

Atmega 8 układ czasowy. Proszę o propozycje programu.

26 Gru 2006 17:40 2850 13
REKLAMA
  • #1 3371724
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #2 3371857
    Andy74
    Poziom 25  
    Posty: 525
    Pomógł: 103
    Ocena: 24
    Witam.

    A co to znaczy "układ wyłącza się"? Ma odcinać swoje własne zasilanie, czy co? Ma czymś sterować? Jeśli tak to czym? W czym programujesz? Z czym konkretnie masz kłopot?
    Doprecyzuj pytanie, bo na tak zadane nikt Ci nie odpowie. Jestem na forum już dość długo, ale nie spotkałem tu jak dotąd jasnowidza... :)

    Pozdrawiam
    Andy
  • #3 3371880
    Konto nie istnieje
    Konto nie istnieje  
  • #4 3371901
    Andy74
    Poziom 25  
    Posty: 525
    Pomógł: 103
    Ocena: 24
    Nie no... nie miałem zamiaru się bynajmniej naśmiewać, ale przyznasz sam, że trudno było wywnioskować z Twojej pierwszej wypowiedzi co masz na myśli...
    W C niestety nie pomogę :(, ale teraz z pewnością znajdzie się ktoś obeznany w temacie, kto Cię naprowadzi.

    Pozdrawiam
    Andy
  • REKLAMA
  • #5 3375002
    Konto nie istnieje
    Konto nie istnieje  
  • #6 3381445
    ktrot
    Poziom 20  
    Posty: 166
    Pomógł: 47
    Ocena: 3
    Użyj jakiegoś timera i przerwania, powiedzmy TIMER0. Policzmy trochę. Zakładam zegar 8Mhz. Jezeli uzyjemy preskalera 256 to czas co jaki zostanie wywołane to przerwanie to 256*256/8000000=0,008. Ilość taktów co jakie zostanie wywołane przerwanie to 256*256=65536 (pierwsze 256 wynika z tego, ze licznik jest 8 bitowy drugie to preskaler) Żeby odliczyć 180s czyli 180*8000000 taktów przerwanie musi być wywołane 180*8000000/65536=21972 razy. Do zliczania przerwań uzyjemy dodatkowej zmiennej typu unsigned int ( uint16_t w winavr), zakładam przycisk podpięty do portu PORTD0
    piszemy naszą obsługę przerwania:
    
    unsigned int licznik;  // musi być zmienną globalna
    
    // procedura przerwania:
    ISR(TIMER0_OVF_vect)  
    {
      licznik++;
      if (licznik==21972)
        {
            TCCR0=0;   //zatrzymaj TIMER0
            LED_OFF();   //wyłacz diodę
            licznik=0;    //wyzeruj do ewentualnego następnego odlicznia
        }
    }
    
    //program główny:
    void main()
    {
      DDRD &=~(1<<PIND0);  //PORTD0 jako wejście
      licznik=0;
      sei(); //zezwalaj na przerwania
      TIMSK |=(1<<TOIE0); ustaw flagę przerwania OVF dla TIMER0
      while (PIND & (1<<PIND0));  //czekamy na naciśnięcie przycisku
      LED_ON(); //przycisk nacisnięty, zapalamy diodę
      TCCR0=4;  //startujemy TIMER0 preskaler 256
      while(1);  //nic więcej do roboty za 3min dioda zgaśnie, mozna w tej
                     //pętli badać stan przycisku i ewentualnie wyłączyć wcześniej
    }
    


    Uwagi:
    Zamiast LED_ON() LED_OFF() wpisz odpowiednie instrukcje lub funkcje zapalania/gaszenia diody.
    Uzywając zmiennej unsigned int mozna ten sposób odliczyć czas do ok 36min (preskaler 1024) ale uzywając zmiennej typu long lub kilku zmiennych nie ma ograniczeń. Program czeka na naciśnięcie przycisku odlicza 3min i nic wiecej nie robi, mozna część main() objąc pętlą aby mozna było ponownie zapalić diodę bez resetowania.
  • #7 3383541
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #8 3383639
    Mirek D
    Poziom 15  
    Posty: 120
    Pomógł: 8
    Ocena: 12
    Zwróć uwagę na post Kolegi "ktrot" :"Żeby odliczyć 180s czyli 180*8000000 taktów przerwanie musi być wywołane 180*8000000/65536=21972 razy"
    Policzył Ci dla kwarcu 8000000 Hz. Dla 1 MHz musisz zmienić ustawienia preskalera.
  • REKLAMA
  • #9 3406777
    tomgart
    Poziom 25  
    Posty: 864
    Pomógł: 49
    Ocena: 63
    A może zrobić funkcję _delyms(1000) i wywołać ją w pętli 180 razy? NIe trzeba wtedy przerwań.
    Ja tak ostatnio odmierzałem minutę.

    Pozdr.
    Tomgart

    
    #define F_CPU        1000000                                       /* 1MHz zegar procesora */
    
    #define CYCLES_PER_US ((F_CPU+500000)/1000000) /* cpu cycles per microsecond */
    
    void delay(unsigned int us)
    {
    
        unsigned int delay_loops;
        register unsigned int  i;
        delay_loops = (us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty)
        for (i=0; i < delay_loops; i++) {};
    }
    
    void delayms(unsigned int ms)
    {
                unsigned int i;
                for (i=0;i<ms;i++)
                            {
                            delay(999);
                            asm volatile (
                            "WDR"::);
                            }
    
    } 
    
    int main(void)
    {
    int k;
    for(k=0;k=<180;k++)
    delayms(1000);
    // tutaj instrukcja która ma się wykonać po 3 minutach....
    
    }
    
    
  • #10 3414788
    Konto nie istnieje
    Konto nie istnieje  
  • #11 3415862
    Platon
    Poziom 42  
    Posty: 9185
    Pomógł: 744
    Ocena: 169
    tomgart - nie odmierzałes minuty, tylko "około minute" :)
  • #12 3418908
    tomgart
    Poziom 25  
    Posty: 864
    Pomógł: 49
    Ocena: 63
    Platon: tak, w przybliżeniu :)
    dziura.arek: pisałem z głowy na szybko - byk jest w pętli głównej w main(): źle zapisałem mniejszy równy: powinno być: k<=180.
  • #13 3419036
    Konto nie istnieje
    Konto nie istnieje  

Podsumowanie tematu

✨ Dyskusja dotyczy realizacji układu czasowego opartego na mikrokontrolerze Atmega8, który po naciśnięciu przycisku odmierza określony czas (np. 3 minuty) i następnie wyłącza układ lub steruje diodą LED. Autor jest początkujący i poszukuje przykładowego programu w języku C (WinAVR). Zaproponowano wykorzystanie timera TIMER0 z przerwaniem, z obliczeniami dla zegara 8 MHz i preskalera 256, co pozwala na odliczenie 180 sekund przez zliczanie przepełnień licznika. Przedstawiono fragment kodu obsługi przerwania i sugestię zatrzymania timera po upływie czasu. Poruszono też kwestię użycia kwarcu 1 MHz, wymagającego zmiany ustawień preskalera. Alternatywnie zaproponowano prostą funkcję opóźnienia delayms() wywoływaną w pętli, bez użycia przerwań. Autor zgłaszał problemy z kompilacją, które zostały częściowo wyjaśnione. Wskazano również źródła dokumentacji mikrokontrolera Atmega8. Dyskusja zawiera praktyczne wskazówki dotyczące implementacji odliczania czasu i sterowania wyjściem w Atmega8 z wykorzystaniem WinAVR.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA