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

[AVR][C] podstawy- diody LED

qw3r 22 Paź 2009 21:05 3596 16
  • #1 7162528
    qw3r
    Poziom 10  
    Witam, chcę się dowiedzieć jak opóźnic miganie diody LED za pomocą pętli for (ma być pustą pętlą) do około 0,5 MHz, z góry dziękuję
  • Pomocny post
    #2 7162635
    miszcz310
    Poziom 24  
    Zamiast "gołej" pętli proponuję użycie funkcji: _delay_loop_2(uint16_t __count)
    Z biblioteki <avr/delay.h>. Bo raczej miganie LEDkami nie potrzebuje hiper dokładnego odmierzania czasu (choć jest to możliwe wykorzystując inne funkcje z tej biblioteki). Z tymi MHz to przesadziłeś, pewnie chodziło Ci po prostu o Hz. :D

    Aha funkcję w programie wywołujesz pisząc _delay_loop_1(0xffff); w ten sposób uzyskasz maksymalne opóźnienie. Jeżeli chcesz jeszcze bardziej opóźnić po prostu wstaw tą instrukcję n razy...
  • #3 7162699
    qw3r
    Poziom 10  
    przepraszam nie MHz a Hz, masz racje ( :
    probowalem z _delay_ms(x), dzialalo, ale jednak musze miec to zrobione z petla for (takie "zadanie") .. :( i nie mam pojecia jak..
    
    int main( void ) // program główny
    {
    sbi(DDRD,4); // uyj linii PD4 jako wyjscia
    
    while(1) // petla nieskonczona
    {
    for(float x=0;x<0x32;++x)
    sbi(PORTD,4); // zgas diode LED podłaczona do linii PD4
    
    for(float x=0;x<0x3E8;++x)
    cbi(PORTD,4); // zapal diode LED podłaczona do linii PD4
    
    
    }
    }


    mam takie cos ale to nie jest 0,5Hz
  • Pomocny post
    #4 7162763
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #5 7162774
    miszcz310
    Poziom 24  
    Hmmmm jeżeli mogę coś doradzić, to nie używaj zmiennych typu float do pętli, do pętli używa się int a najlepiej unsigned int. W unsigned int można przechowywać największą liczbę 2^16-1, czyli jakoś ponad 65,5k. jeżeli to ma być jakieś w miarę dokładne odliczanie napisz jakiego kwarcu używasz, i te fory jak dla mnie powinny wyglądać tak :
    "for(int i; i<65000; i++); "<--powinno zadziałać chyba że masz jakieś super-duper opcje optymalizacyjne ustawione. jak to nie zadziała to możesz spróbować
    for(int i; i<65000; i++){} aha na początek może to być za mało żeby w ogóle było zauważalne np. dla 1MHz taka pętla zajmie ok. 65ms więc może być wcale nie widoczne... wstaw z 10 takich to będzie migać co ok 0,65 sek. oczywiście przy kwarcu 1Mhz. jeżeli masz inny kwarc to możesz sam przeliczyć albo napisać. Można też for w forze napisać... No ale dobra sprawdź i powiedz czy działa.

    Reszta kodu raczej w pożądku, zmień tylko te fory.
  • Pomocny post
    #6 7162846
    tmf
    VIP Zasłużony dla elektroda
    Zacznijmy od tego, ze za pomoca for w C nie da sie uzyskac dokladnego odliczania czasu! Przeciez w zaleznosci od optymalizacji (-O) i wersji kompilatora roznice beda siegaly tysiecy procent. Raz bedziesz mial 10Hz, a innym razem 0,01 Hz. Jesli chcesz w miare dokladnie odmierzac czas to albo korzystasz z funkcji z delay.h, albo piszesz wstawke w assemblerze co pozwoli ci policzyc takty (acz tu tez uwaga na rozne rodziny AVR), albo najdokladniej to wykorzystac sprzetowy timer z ew. preskalerem.
  • #7 7162968
    qw3r
    Poziom 10  
    dzialam na symulatorze hapsim.. wlaczam sobie ATmega128
    zmienilem te petle for.. ale teraz robi mi jeden "obieg" tzn for-sbi-for-cbi a potem zaczyna dioda migac po swojemu tzn cbi-sbi-cbi-sbi..
    To rozumiem nie da sie zrobic tego chociaz aby migalo w przyblizeniu 0.5Hz? : (
  • Pomocny post
    #8 7163029
    miszcz310
    Poziom 24  
    No właśnie w przybliżeniu się da. Na pewno te fory są w pętli while(1){}, bo jak się robi tylko raz to może być jakiś bałagan z nawiasami czy coś. Aha a masz napisane "for(unsigned int i; ....." Bo chodzi o to żeby nie było zmiennej i poza tym nawiasem for(;;). Bo jeżeli wstawiłeś dokładnie takie fory i tam gdzie były tamte to powinno działać.
  • Pomocny post
    #9 7163060
    czmi3l
    Poziom 14  
    po 1 primo :-)

     for(float x=0;x<0x32;++x) 


    W języku C deklaracja zmiennej w pętli jest niedopuszczalna :)

    jak już chcesz jakieś opóźnienie uzyskać to możesz zrobić:

    
    unsigned int x;
    for (x = 0; x < 65535; x++) ; // średnik tu jest kluczowy ;)
    

    ale żeby to zadziałało musisz w opcjach kompilatora wyłączyć optymalizację.
    Opóźnienie regulujesz zmieniając x < jakaśLiczba

    Po drugie możesz w pętli for wywoływać funkcję _delay_ms(jakaś wartość) z biblioteki delay.h
  • #10 7163065
    qw3r
    Poziom 10  
    mam unsigned int i robi mi jak napisałem wcześniej, przebieg z for'ami potem bez..
    
    int main( void ) // program główny
    {
    sbi(DDRD,4); // uyj linii PD4 jako wyjscia
    
    while(1) // petla nieskonczona
    {
    for(unsigned int i; i<60000; i++){}
    
    cbi(PORTD,4); // zapal diode LED podłaczona do linii PD4
    
    for(unsigned int i; i<60000; i++){}
    
    sbi(PORTD,4); // zgas diode LED podłaczona do linii PD4
    
    }
    }
    
  • Pomocny post
    #11 7163167
    miszcz310
    Poziom 24  
    Hmmmm wiesz co sprawdziełem sobie z tym Twoim symulatorem i u mnie się też tak robi... Według mnie ten kod, który podałem będzie działał normalnie tzn. nie na symulatorze tylko na prawdziwym procku.

    O! Wiesz co czmi3l nawet nie wiedziałem, że to tak w C jest... Dobrze wiedzieć z tymi deklaracjami, zastanawia mnie jednak czemu kompilator nic nie krzyczy przy 'moim' zapisie?
  • #12 7163180
    qw3r
    Poziom 10  
    o dziękuję dodałem volatile przed deklaracja zmiennej.. i o dziwo dziala..
    jest to wlasnie (chyba) wylaczenie optymalizacji ( : nie wiem włączyłem google na szybko i "jo" :D
    oto mój program:
    
    int main( void ) // program główny
    {
    volatile unsigned int x;
    sbi(DDRD,4); // uyj linii PD4 jako wyjscia
    
    while(1) // petla nieskonczona
    {
    for (x = 0; x < 10000; x++);
    cbi(PORTD,4); // zapal diode LED podłaczona do linii PD4
    for (x = 0; x < 10000; x++);
    sbi(PORTD,4); // zgas diode LED podłaczona do linii PD4
    
    }
    }
    



    PS oczywiście dziękuję za pomoc, bez was nie zrobiłbym tego ( :
  • #13 7163486
    miszcz310
    Poziom 24  
    Hmm jak poprawiłem for(unsigned int i=0;... to mi teraz działa...
  • Pomocny post
    #14 7163540
    tmf
    VIP Zasłużony dla elektroda
    Z volatile ma to prawo dzialac, bez - nie. Kompilator taka petle powinien wyrzucic bo jest pusta i nic nie robi. Nie wiem skad ten upor i zabawa z petlami, skoro jest od tego funkcja delay. No i w prawdziwym procesorze przy petli do 10000 to migania nie zobaczysz, nawet jesli go popedzisz w wewnetrznego RC to masz w zaleznosci od proce 1,2-8MHz, czyli opoznienie nie wieksze niz 10-20ms, a przy 8 MHz jakies 1-3 ms.
  • #15 7163629
    gregy
    Poziom 11  
    polecam stronke Radzia i jego przykłady :)
    W tym wypadku:
    Przykład 2 - układ czasowy
    funkcja waitms:
    void waitms(unsigned char x)
    {
    unsigned char a, b; // zmnienne licznikowe
    for( ; x > 0; --x) // ta pętla zostanie wykonana x-razy
    for(b = 10; b > 0; --b) // a ta 10 razy
    for(a = 25 * OSC; a > 0; --a) // natomiast ta 100 razy
    __asm("nop"); // dodatkowa instrukcja opóźniająca o 1 cykl
    // razem to da opóźnienie ok. x * 1ms
    // x od 0 do 255
    // gdy x = 0 to opóźnienie = 256ms 
    }
  • #16 7163741
    Konto nie istnieje
    Poziom 1  
  • #17 7163930
    czmi3l
    Poziom 14  
    miszcz310 napisał:

    O! Wiesz co czmi3l nawet nie wiedziałem, że to tak w C jest... Dobrze wiedzieć z tymi deklaracjami, zastanawia mnie jednak czemu kompilator nic nie krzyczy przy 'moim' zapisie?


    Bo pewnie nie ma ustawionego trzymania się standardu C :-). Spróbuj np. w dev c++ stworzyć projekt C i taką formę zastosować.
REKLAMA