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

Jak skonfigurować RTC z Timer2 w Atmega 32 z kwarcem 32.768 kHz?

pgp 06 Kwi 2006 17:47 1572 3
REKLAMA
  • #1 2500025
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Chcę zaimplementowac RTC w mojej Atmedze. Mają to być przerwania od asynchronicznego Timera2. Coś nie działa, mam kilka pytań :

    1. czy piny w porcie C (PC7 i PC6 które służa jako TOSC1 i TOSC2) trzeba ustawić jako we/wy ? czy wystarczy ustawienie bitu AS2 w ASSR ?

    2. jakie powinno być napięcie na nich ( u mnie na obu pinach rezonatora jest 0.4 V).

    3. Czy można zasymulować rezonator 32 768 w programie VMLAB ?

    4. Czy jeżeli używam tez przerwań od Timera0 (do odczytu klawiatury) to musze to jakoś pogodzić ze sobą ?

    Dołaczam istotne fragmenty kodu:


    fragment f-cji main :

    ///////////// inicjalizacja kwarcu 32 768 //////////////////////////

    TIMSK &=~((1<<TOIE2)|(1<<OCIE2));
    ASSR=(1<<AS2);
    TCNT2=0;
    TCCR2=5;// ustawienie preskalera na /128 => przerwania co 1 sek
    while(ASSR&0x07);
    TIMSK=(1<<TOIE2);
    ////////// timer 0 do klawiatury: /////////////
    TIMSK=(1<<TOIE0); //zezw na przerwania od Timera0
    TCNT0=tau0;
    TCCR0=5; //XTAL/1024
    sei(); //zezwolenie globalne na przerwania



    obsługa przerwania:
    SIGNAL (SIG_OVERFLOW2)
    {

    if(c==0) {sbi(PORTA,0); c=1;}
    else {cbi(PORTA,0); c=0;} //miganie diody co sekundę

    if(++t.second==60)
    {
    t.second=0;
    if(++t.minute==60)
    {
    t.minute=0;
    if(++t.hour==24)
    {
    t.hour=0;
    if (++t.date==32)
    {
    t.month++;
    t.date=1;
    }
    else if (t.date==31)
    {
    if ((t.month==4)||(t.month==6)||(t.month==9)||(t.month==11))
    {
    t.month++;
    t.date=1;
    }
    }
    else if (t.date==30)
    {
    if (t.month==2)
    {
    t.month++;
    t.date=1;
    }
    }
    else if (t.date==29)
    {
    if((t.month==2)&&(not_leap()))
    {
    t.month++;
    t.date=1;
    }
    }
    if (t.month==13)
    {
    t.month=1;
    t.year++;
    }
    }
    }
    }


    }


    char not_leap(void)
    {
    if(!(t.year%100))
    return (char)(t.year%400);
    else
    return (char)(t.year%4);
    }


    z moich obserwacji wynika że przerwania od timera2 nie sa wogóle zgłąszane - dioda nie miga, minuty nie sa aktualizowane
  • REKLAMA
  • #2 2500234
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    Tak to robią w Atmelu
    /******************************************************************************
    *
    *   Function name:  RTC_init
    *
    *   returns:        none
    *
    *   parameters:     none
    *
    *   Purpose:        Start Timer/Counter2 in asynchronous operation using a
    *                   32.768kHz crystal.
    *
    *******************************************************************************/
    void RTC_init(void)
    {
        Delay(1000);            // wait for 1 sec to let the Xtal stabilize after a power-on,
    
        cli(); // mt __disable_interrupt();  // disabel global interrupt
    
        cbi(TIMSK2, TOIE2);             // disable OCIE2A and TOIE2
    
        ASSR = (1<<AS2);        // select asynchronous operation of Timer2
    
        TCNT2 = 0;              // clear TCNT2A
        TCCR2A |= (1<<CS22) | (1<<CS20);             // select precaler: 32.768 kHz / 128 = 1 sec between each overflow
    
        while((ASSR & 0x01) | (ASSR & 0x04));       // wait for TCN2UB and TCR2UB to be cleared
    
        TIFR2 = 0xFF;           // clear interrupt-flags
        sbi(TIMSK2, TOIE2);     // enable Timer2 overflow interrupt
    
        sei(); // mt __enable_interrupt();                 // enable global interrupt
    
        // initial time and date setting
        gSECOND  = 0;
        gMINUTE  = 0;
        gHOUR    = 12;
        // mt release timestamp
        gDAY     = 05;
        gMONTH   = 12;
        gYEAR    = 3;
    }
    
    daje przerwanie co 1 sekundę i zegar sobie tyka.
  • REKLAMA
  • #3 2500513
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Robie podobnie jak proponujesz :

    ///////////// inicjalizacja kwarcu 32 768 //////////////////////////
    czekaj(1000*tau);
    TIMSK &=~((1<<TOIE2)|(1<<OCIE2));//Disable the Timer/Counter2 interrupts
    ASSR=(1<<AS2);// select asynchronous operation of Timer2

    TCNT2=1; // wyzerowanie aktualnego stanu licznika
    TCCR2=5;// ustawienie preskalera na /128 => przerwania co 1 sek
    OCR2=0;//
    while(ASSR&0x07);
    TIFR = 0xFF; // clear all interrupt-flags

    TIMSK=(1<<TOIE2);//załaczenie przerwań od prezrpełnienia Timera 2
    TIMSK=(1<<OCIE2);



    i nic....
    może problem jest w nazwie funkcji przyrywającej ??
    powinienem użyć SIGNAl czy INTERRUPT ?
    co podać w nawiasie ?
  • #4 2502236
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    To są wszystkie przerwania zdefiniowane w AVR-GCC Jak się pomylisz to może cię spotkać rozczarowanie:
    #define SIG_INTERRUPT0          _VECTOR(1)
    #define SIG_INTERRUPT1          _VECTOR(2)
    #define SIG_INTERRUPT2          _VECTOR(3)
    #define SIG_OUTPUT_COMPARE2     _VECTOR(4)
    #define SIG_OVERFLOW2           _VECTOR(5)
    #define SIG_INPUT_CAPTURE1      _VECTOR(6)
    #define SIG_OUTPUT_COMPARE1A    _VECTOR(7)
    #define SIG_OUTPUT_COMPARE1B    _VECTOR(8)
    #define SIG_OVERFLOW1           _VECTOR(9)
    #define SIG_OUTPUT_COMPARE0     _VECTOR(10)
    #define SIG_OVERFLOW0           _VECTOR(11)
    #define SIG_SPI                 _VECTOR(12)
    #define SIG_UART_RECV           _VECTOR(13)
    #define SIG_UART_DATA           _VECTOR(14)
    #define SIG_UART_TRANS          _VECTOR(15)
    #define SIG_ADC                 _VECTOR(16)
    #define SIG_EEPROM_READY        _VECTOR(17)
    #define SIG_COMPARATOR          _VECTOR(18)
    #define SIG_2WIRE_SERIAL        _VECTOR(19)
    #define SIG_SPM_READY           _VECTOR(20)
    
    Na początek proponowałbym jednak SIGNAL
REKLAMA