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.

[C] AVR Atmega8 złe opóźnienie....

aqq 04 Gru 2008 16:28 2222 13
  • #1 04 Gru 2008 16:28
    aqq
    Poziom 10  

    Hej, mam taki problem, że ucze się języka C w poradnika Pana Teodora Otulaka, niestety dioda zamiast zapalać się i gasnąć co 1s zapala się i gasi co około 5s... :( Zmieniałem fusebity na zewnętrzny kwarc (lfuse: 0xEC, hfuse: 0x99), więc mógłby mi ktos powiedzieć co tu jeszcze schrzaniłem? (Wątpię, żeby to miało coś wspólnego ale dodam, że na PC mam zainstalowanego Debiana)

    Code:

        #include <avr/io.h>

        // trzebabyło zdefiniować bo to juz nie jest obsługiwane
        #define sbi(add,bit) add |= _BV(bit);   
        #define cbi(add,bit) add &= ~_BV(bit);

        #define F_CPU         4000000L                           
        #define CYCLES_PER_US ((F_CPU+500000)/1000000)
       

        #define LED_ON sbi(DDRB,PB1);sbi(PORTB,PB1)
        #define LED_OFF sbi(DDRB,PB1);cbi(PORTB,PB1)

        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)
        {
             for (;;)
                      {
                         LED_ON;
                         delayms(1000);
                         LED_OFF;
                         delayms(1000);
                      }
           return (0);
        }

    0 13
  • #2 04 Gru 2008 19:39
    PSow
    Poziom 9  

    Moim zdaniem masz źle ustawione fuse bity. Zajrzyj do dokumentacji ATmega8 (System clock and clock options -> Clock sources -> Cristal Oscillator). Tam jest taka tabelka, z której by wynikało, że zastosowałeś ustawienie dla kwarców z przedziału 0.9 do 3.0 MHz, a o ile dobrze rozumiem masz kwarc 4MHz. Generalnie do ustawiania fuse bitów ja używam tego kalkulatora, przy czym trzeba pamiętać, że kwarce 4MHz i więcej, podchodzą pod kategorię "high freq.".

    Druga sprawa, jeśli zależy ci na dokładnym czasie trwania opóźnienia, to jest prostsze i bardziej eleganckie rozwiązanie.

    0
  • #3 04 Gru 2008 20:48
    aqq
    Poziom 10  

    Rzeczywiscie, miałem ustawione na medium freq. Ale mam jeszcze jedno pytanie co znaczy np Start-up time: 1K CK +4ms ?

    0
  • #4 04 Gru 2008 20:59
    dawid512
    Poziom 32  

    Opóźnienie 4ms po starcie.

    -1
  • #5 04 Gru 2008 22:57
    aqq
    Poziom 10  

    Przestawiłem lfuse na 0xdf hfuse został na 0x99. Zmienłem kodzik, i... dalej nie działa. Dioda na PB1 wczesniej z duzym opóźnieniem, ale migała. Teraz się swieci cały czas :(

    Code:
    #define F_CPU 4000000UL
    

    #include <avr/io.h>
    #include <util/delay.h>

    #define sbi(add,bit) add |= _BV(bit);
    #define cbi(add,bit) add &= ~_BV(bit);

    #define LED_ON sbi(DDRB,PB1);sbi(PORTB,PB1);
    #define LED_OFF sbi(DDRB,PB1);cbi(PORTB,PB1);
    int main (void)
    {
         int i;
         for (;;)
                  {
                     LED_ON;
          for(i=0;i<50;i++)
          {
                        _delay_ms(10);
          }   
                        LED_OFF;
          for(i=0;i<50;i++)
          {
                        _delay_ms(10);
          }      
                  }
       return (0);
    }

    0
  • #6 04 Gru 2008 23:04
    dawid512
    Poziom 32  

    Korzystasz może z AVR STUDIO? Jeśli tak to po mimo zadeklarowania zegara w programie ustaw go także w opcjach. Po za tym po co stosujesz pętlę do opóźnienia? Nie lepiej tak?

    Code:
    _delay_ms(250);
    
    _delay_ms(250);

    0
  • #7 04 Gru 2008 23:12
    aqq
    Poziom 10  

    Nie, korzystam z kompilatora avr-gcc na Debianie. Po napisaniu programu zapisuję plik jako program.c a następie wpisuję do konsoli:

    Code:

    avr-gcc -mmcu=atmega8 program.c -o program
    avr-objcopy -O ihex program program.hex
    uisp -dprog=stk200 --erase --upload if=program.hex --verify

    ...i pokazuje że wykryto, połączono, wymazano, wgrano i zweryfikowano.

    0
  • #8 04 Gru 2008 23:46
    PSow
    Poziom 9  

    Nie wiem, czy to urok avr-gcc, czy samych mikrokontrolerów, ale generalnie źle one znoszą pętle bezpośrednio zagnieżdżone w głównej pętli programu (też kiedyś miałem tego typu przygody). Zrób sobie oddzielną funkcję, np. coś w tym stylu:

    Code:
    #define F_CPU 4000000L
    

    #include <avr/io.h>
    #include <util/delay.h>

    void opoznienie(unsigned short n);

    int main()
    {
       DDRB |= _BV(1);         // PB1 jako wyjście

       for(;;)
       {
          PORTB ^= _BV(1);     // XOR na PB1 - w praktyce zawsze odwraca poprzedni stan
          opoznienie(50);     // 500 ms
       }
       return 0;
    }

    void opoznienie(unsigned short n)
    {
       unsigned short i;
       for(i = 0; i < n; i++)
          _delay_ms(10);
    }


    Możesz też zrobić to "na chama" - _delay_ms(500); Będzie trochę mniej dokładnie (jak ostrzega jedna ze stron, które podlinkowałem), ale nie oszukujmy się, w takim programie nie jest to specjalnie istotne ;) Generalnie do zadań, gdzie ważny jest czas i tak stosuje się wbudowane timery/countery.

    P.S. Zrób sobie skrypt w bashu do kompilacji, że też chce ci się wklepywać taką długą komendę... ;)

    0
  • #9 05 Gru 2008 06:52
    aqq
    Poziom 10  

    Mam skrypcik, napisałem tak zeby tylko było wiadomo o co chodzi ;) Skopiowałem, wgrałem i... dalej to samo, dioda się tylko świeci :(

    0
  • #10 05 Gru 2008 09:52
    PSow
    Poziom 9  

    Powoli kończą mi się pomysły... Kwarc masz podpięty, jak należy (tj. z dwoma kondensatorkami 12-22pF, w układzie jak w dokumentacji)? Czy diodę na pewno masz podpiętą pod PB1? Czy podczas kompilacji nie wyskakują warningi/errory? Czy na pewno masz zasilanie układu w odpowiednim zakresie napięć i odpowiednio stabilne?

    Mógłbyś dokładniej opisać, jak podłączyłeś diodę i kwarc (albo jeszcze lepiej, narysować)?

    Zrób też taki eksperyment... daj jako parametr opóźnienia 250 i powiedz, czy teraz mruga.

    0
  • #11 05 Gru 2008 11:58
    skynet_2
    Poziom 26  

    takie coś na pewno zadziała

    Code:
    #include <avr/io.h> 
    
    #include <util/delay.h>

    int main()
    {
       DDRB = _BV(1);
       PORTB = 0;
       while(1)
       {
       PORTB ^= _BV(1);
        _delay_ms(1000);//dioda włączona przez sekundę, wyłączona przez sekundę
       }
       return 0;
    }


    spróbuj tak skompilować

    Cytat:
    avr-gcc -mmcu=atmega8 -std=gnu99 -DF_CPU=4000000UL program.c -o program
    avr-objcopy -O ihex program program.hex
    uisp -dprog=stk200 --erase --upload if=program.hex --verify


    kolego aqq może zainstaluj eclipse + plugin do AVR i masz bardzo dobre GUI. Przez plugin programujesz µC, ustawiasz fusy graficznie, automatycznie tworzony jest makefile, czego chcieć więcej.

    Pozdrawiam kolegow debianowców.

    0
  • #12 05 Gru 2008 14:46
    aqq
    Poziom 10  

    Zrobiłem wszystko tak jak pisał kolega skynet_2. Niestety.. efekt dalej ten sam :( Zasilanie jest stabilne (zasilanie jest z zasilacza przez stabilizator, oraz przedchwilą zeby się upewnić ze to nie on zamieniłem go nową baterią 9V, to samo...). Napięcie przy procesorze wynosi (wg. miernika za 15zł) 4.92V. Poprzednio miałem zamontowaną atmegę32, układ działał do pewnego czasu dobrze, ale pewnego ranka włączyłem płytkę prototypową i całe opóźnienia się posypały, i w mega32 i potem w atmedze8 juz ani chwili nie działały dobrze :(

    Kondensatorki mam 33pF bo akurat nie miałem innych. Dioda jest podłączona krótszą nóżką do masy dłuższą do rezystora 560 a on do PB1.

    Kompiluję, tworzę plik program.hex (w konsoli nic się nie pokazuje) następnie jak wgrywam to wyskakuje:

    Code:
    Atmel AVR ATmega8 is found.
    
    Erasing device ...
    Reinitializing device
    Atmel AVR ATmega8 is found.
    Uploading: flash
    Verifying: flash

    0
  • #13 05 Gru 2008 14:59
    BoskiDialer
    Poziom 34  

    aqq napisał:
    Dioda na PB1 wczesniej z duzym opóźnieniem, ale migała. Teraz się swieci cały czas

    Jeśli działała z dużym opóźnieniem, to pewnie wynik tego, że dzielenie zajmuje jednak trochę czasu. Mnie jednak funkcja delay() się cała zoptymalizowała [po wstawieniu asm volatile(""::); do pętli już nie; jedna iteracja 6 cykli + dzielenie]. Jeśli teraz nie działa, to nie resetujesz WDT (w fusebitach masz ustawione WDT always on: hfuse:6==0)

    Jeśli to nie to, to czas przejść do pomiarów: czy na resecie jest stan wysoki (powinien być)?

    0
  • #14 05 Gru 2008 15:15
    aqq
    Poziom 10  

    Okej, zmieniłem hfuse na 0xD9 (dioda przynajmniej zaczęła migać ;) na oko ciężko powiedzieć ale okolo 4-8x na sekundę), na resecie jest stan wysoki (3,5V) oprócz tego podciągłem go przez rezystor 4.7k do plusa i teraz jest 4,89V.

    0