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

[AVR][asembler][Sterowanie diodą LED]

19 Paź 2009 18:33 2854 5
  • Poziom 34  
    Jestem początkujący jeśli chodzi o mikrokontrolery AVR. Znam dobrze natomiast '51. Chcę napisać program naprzemiennie gaszący i zapalający diodę LED. Dioda jest podpięta katodą do linii portu, anoda przez rezystor do +5V. W związku z tym dioda jest sterowana zerem. Poniżej przedstawiam mój kod. Częstotliwość zegara wynosi 16MHz.
    Code:
    .nolist
    

    .include "m8def.inc"

    .list



    .cseg

    .org 0

    rjmp begin
       delay1:
          ldi R16, 0
          del1:
             inc R16
          brne del1
       ret

       delay2:
          ldi R17, 0
          del2:
             rcall delay1
             inc R17
          brne del2
       ret

       delay3:
          ldi R18, 0
          del3:
             rcall delay2
             inc R18
          brne del3
       ret

    begin:

    ldi R17, high(RAMEND) ;inicjalizacja stosu
    ldi R16, low(RAMEND)
    out SPH, R17
    out SPL, R16

    ldi R20,0xFF
    out DDRB,R20
    out PORTB,R20 ;dioda zgaszona i port ustawiony jako wyjście

    petla_glowna:
       rcall delay3
       in R20, PORTB
       com R20
       out PORTB, R20
    rjmp petla_glowna


    Mam pytanie jak duże w tym programie jest opóźnienie wnoszone przez podprogram delay2 ? Czy wystarczające do zauważenia migotania diody ?
  • Pomocny post
    Poziom 26  
    Jeśli dobrze pamiętam to tak to się liczyło
    Code:

       delay1:
          ldi R16, 0 ;1 cykl
          del1:
             inc R16 ;1cykl
          brne del1 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
    ;razem (1+1+2)*256-1+4=1027 cykli

       delay2:
          ldi R17, 0 ;1 cykl
          del2:
             rcall delay1 ;3+1027 cykli
             inc R17 ;1 cykl
          brne del2 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
    ;razem (1+1030+1+2)*256-1+4=264707 cykli

    czyli 264707 cykli / (16 000 000 cykli/sek) = 16,5 ms

    Jeśli pracujesz na AVR Studio to łatwo to sprawdzić w symulacji. Po dojściu do linii przed wywołaniem opóźnienia wyzerować podwójnym kliknięciem licznik cykli i sprawdzić po wykonaniu podprogramu.
  • Poziom 34  
    Czyli licząc opóźnienie wnoszone przez delay3 powinno wyjść tak:
    Code:
       delay3:
    
          ldi R18, 0 ;1 cykl
          del3:
             rcall delay2 ;3+264707 cykli  - jak rozumiem 3 to ilość cykli rcall ?
             inc R18 ;1 cykl
          brne del3 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
                 ;razem (1+264710+1+2)*256-1+4=67766787 cykli


    67766787*(16MHz)^-1=4,24s Czy tak ?
  • Poziom 26  
    Było by dobrze, ale źle postawiłem nawias, bo ldi nie wykonuje się w pętli, ale tylko raz. Po poprawce:
    Code:

       delay1:
          ldi R16, 0 ;1 cykl
          del1:
             inc R16 ;1cykl
          brne del1 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
    ;razem 1+(1+2)*256-1+4=772 cykli

       delay2:
          ldi R17, 0 ;1 cykl
          del2:
             rcall delay1 ;3+772 cykli
             inc R17 ;1 cykl
          brne del2 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
    ;razem 1+(775+1+2)*256-1+4=199172 cykli

       delay3:
          ldi R18, 0 ;1 cykl
          del3:
             rcall delay2 ;3+199172 cykli 
             inc R18 ;1 cykl
          brne del3 ;2 cykle (1 gdy nie ma skoku)
       ret ;4 cykle
    ;razem 1+(199175+1+2)*256-1+4=50989572 cykli

    co przy kwarcu 16MHz da 3,19 sekundy
  • Poziom 34  
    To by się zgadzało. Okazało się to na dzisiejszej laborce. Program po wysłaniu do flash'a działał szybciej.
  • Poziom 37  
    Ciekawostka. Zamiast migać całym portem jak to robisz przez :
    com R20
    out PORTB, R20
    Wpisz SBI PinB,x gdzie x to numer tej końcówki (np PinB,4) i ciesz się migającym pinem portu :-) Powinno działać.
    Pozdrawiam