Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Codevision i AtMega32

uvesik 23 Kwi 2008 20:49 1943 10
  • #1 23 Kwi 2008 20:49
    uvesik
    Poziom 9  

    Witam

    Niestety mam 2 problemy:

    1. Rezonator 4Mhz, AtMega32. Chodzi o obsługe przerwania Timera1. Chcialbym aby przerwanie bylo generowane co 1s. Niestety dla ustawień:

    TCCR1A=0x00;
    TCCR1B=0x04; // Prescaler 256
    TCNT1H=0xC2; // Wartosc poczatkowa
    TCNT1L=0xF6;

    nie działa poprawnie, odlicza zbyt szybko.

    2. CodeVision . Chciałbym wyświetlić tekst + liczbę int. Napisałem kod:

    sprintf(tekst,"T=%d",sekundy);
    lcd_wstaw(tekst);

    gdzie tekst to tablica char tekst[10]; i niestety wysietla mi samą liczbę.

    Prosze o pomoc :)

    0 10
  • #2 23 Kwi 2008 21:58
    nsvinc
    Poziom 35  

    sekundy w int?

    Uzyj tego

    Code:

    unsigned char sekundy=0;


    Potem do wyswietlania:

    Code:

    sprintf(tekst,"T=%u",sekundy);


    Napisales ze twoja zmienna tekst to

    char tekst[10];

    Lepiej i bezpieczniej napisać

    unsigned char tekst[10];

    CO do licznika T1 - ułatw sobie prace, ustaw licznik tak by tykał przerwaniem co np. 1/8 lub 1/16 sekundy. Bezpieczniej i dokladniej. A w samym przerwaniu napisz sobie jakas zmienna "licznik", ktora zwiekszasz co przerwanie, a potem

    if (licznik>=16) sekundy++; //dla ovf 1/16s

    0
  • #3 23 Kwi 2008 22:03
    uvesik
    Poziom 9  

    nsvinc napisał:

    CO do licznika T1 - ułatw sobie prace, ustaw licznik tak by tykał przerwaniem co np. 1/8 lub 1/16 sekundy. Bezpieczniej i dokladniej. A w samym przerwaniu napisz sobie jakas zmienna "licznik", ktora zwiekszasz co przerwanie, a potem

    if (licznik>=16) sekundy++; //dla ovf 1/16s


    Hmmm myślałem ze skoro licznik ma duże
    możliwości zliczania to będzie lepiej wykorzystać go w taki sposób.

    Więc to wina niedokładności ?

    Pozdr.

    0
  • #4 23 Kwi 2008 22:09
    nsvinc
    Poziom 35  

    Licznik moze i ma duze mozliwosci zliczania, ale ja zawsze stosuje częstrze wywołania niz co sekunde, jesli chce go zastosować do zegarka - metoda na 100% sprawdzona, i jak masz dobry kwarc to gubi tylko pare sekund tygodniowo :)

    0
  • #5 23 Kwi 2008 22:18
    uvesik
    Poziom 9  

    Aha ustawiłem preskaler na 64. Wywołuje sie 4 razy na sek. Ale dalej niestety nie zlicza dokładne a przecież wartości początkowe mam poprawne ?

    Pozdr.

    0
  • #6 23 Kwi 2008 22:20
    nsvinc
    Poziom 35  

    Kozystasz z COdeVision - uzyj kreatorka zeby ustalić jakie maja byc wartości i jaki preskaler...

    0
  • #7 24 Kwi 2008 07:44
    uvesik
    Poziom 9  

    Wartości są ok. Korzystam z wew. oscylatora 4Mhz.

    Może powinienem go jakoś skalibrować ?

    W opcjach programatora AVR Studio, mam zakładkę Calibrate for freq.
    Ale nie wiem co mam zrobić z odczytaną wartością.

    Pozdr.

    0
  • #8 24 Kwi 2008 08:04
    MarasK
    Poziom 18  

    w nocie katalogowej jest ładna instrukcja jak kalibrować generator.

    0
  • #9 24 Kwi 2008 08:05
    Fyszo
    Spec od GSM

    uvesik napisał:
    ...niestety nie zlicza dokładne a przecież wartości początkowe mam poprawne ?


    Ale one są orientacyjne, musisz metodą prób i błędów 'podkręcać' nastawy aby dojść do ideału.

    Albo kombinować z oscylatorem.

    0
  • #10 25 Kwi 2008 20:00
    GienekS
    Poziom 32  

    Na wewnętrznym to się nie ma co dziwić że źle chodzi a do kalibracji i tak potrzebny jest kwarc nawet wystarczy zegarkowy na Timer2
    A to procedura kalibracji dla ATmega169

    Code:
    /*****************************************************************************
    
    *
    *   Function name : OSCCAL_calibration
    *
    *   Returns :       None
    *
    *   Parameters :    None
    *
    *   Purpose :       Calibrate the internal OSCCAL byte, using the external
    *                   32,768 kHz crystal as reference
    *
    *****************************************************************************/
    void OSCCAL_calibration(void)
    {
        unsigned char calibrate = FALSE;
        int temp;
        unsigned char tempL;

        CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
        // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
        CLKPR = (1<<CLKPS1) | (1<<CLKPS0);
       
        TIMSK2 = 0;             //disable OCIE2A and TOIE2

        ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)
       
        OCR2A = 200;            // set timer2 compare value

        TIMSK0 = 0;             // delete any interrupt sources
           
        TCCR1B = (1<<CS10);     // start timer1 with no prescaling
        TCCR2A = (1<<CS20);     // start timer2 with no prescaling

        while((ASSR & 0x01) | (ASSR & 0x04));       //wait for TCN2UB and TCR2UB to be cleared

        Delay(1000);    // wait for external crystal to stabilise
       
        while(!calibrate)
        {
            __disable_interrupt();  // disable global interrupt
           
            TIFR1 = 0xFF;   // delete TIFR1 flags
            TIFR2 = 0xFF;   // delete TIFR2 flags
           
            TCNT1H = 0;     // clear timer1 counter
            TCNT1L = 0;
            TCNT2 = 0;      // clear timer2 counter
               
            while ( !(TIFR2 & (1<<OCF2A)) );   // wait for timer2 compareflag
       
            TCCR1B = 0; // stop timer1

            __enable_interrupt();  // enable global interrupt
       
            if ( (TIFR1 & (1<<TOV1)) )
            {
                temp = 0xFFFF;      // if timer1 overflows, set the temp to 0xFFFF
            }
            else
            {   // read out the timer1 counter value
                tempL = TCNT1L;
                temp = TCNT1H;
                temp = (temp << 8);
                temp += tempL;
            }
       
            if (temp > 6250)
            {
                OSCCAL--;   // the internRC oscillator runs to fast, decrease the OSCCAL
            }
            else if (temp < 6120)
            {
                OSCCAL++;   // the internRC oscillator runs to slow, increase the OSCCAL
            }
            else
                calibrate = TRUE;   // the interRC is correct
       
            TCCR1B = (1<<CS10); // start timer1
        }
    }

    0
  • #11 26 Kwi 2008 00:16
    Zajc3w
    Poziom 14  

    Kalibracja wewnetrzego oscylatora do licznia czasu nie a sensu. Zmieni sie zasilanie(np zasilacz przysiadzie o 0.1V) lub temperatura i czsy znowu "popłyną" do zegara tylko kwarc :)

    0