Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8, asembler, miganie diody

ldarko 14 Jun 2006 23:12 8896 18
  • #1
    ldarko
    Level 10  
    Witam

    Zaczynam dopiero z AVR. Chciałem uzyskac miganie diody, mam takie wpisy, nie mam pojęcia co jest nie tak. Teoretycznie w AVR Studio "mruga", ale nie wiem czy to nie sa za małe opóźnienia. Generalnie ma mrugac caly PORTB ( na razie bez uzywania Timera)

    .noolist
    .include "m8def.inc"
    .list
    .listmac
    .def acc = r16 ; r16 teraz ma nazwę acc
    .def acc2 = r17 ; r17 teraz ma nazwę acc2

    .cseg ;
    .org 0 ;
    rjmp Reset;


    Delay :
    ldi acc2,0
    ldi acc,0
    Del_0 :
    inc acc ; zwiększ zawartość acc
    brne Del_0 ; skocz gdy acc różne od 0
    inc acc2 ; zwiększ zawartość acc2
    brne Del_0 ; skocz gdy acc2 różne od 0
    ret



    Delay2:
    ldi acc2,0
    ldi acc,0
    Del_02 : ;
    inc acc ; zwiększ zawartość acc
    brne Del_02 ; skocz gdy acc różne od 0
    inc acc2 ; zwiększ zawartość acc2
    brne Del_02 ; skocz gdy acc2 różne od 0
    ret

    Reset:
    cli
    ldi r16, low(RAMEND)
    out SPL, r16
    ldi r16, high(RAMEND)
    out SPL, r16

    Main:
    ldi r20,0xFF ;LEDPin=1 to LED zgaszony
    out DDRB,r20
    out PORTB,r20
    rcall Delay

    ldi r20,0xFF
    out DDRD,r20
    ldi r20,0x00
    out PORTB,r20
    rcall Delay2

    rjmp Main ;
    .exit


    ps
    diody sa podlaczone na plytce uruchomieniowej przez opornik do masy, nie do plusa
    [28-30.06.2022, targi] PowerUP EXPO 2022 - zasilanie w elektronice. Zarejestruj się za darmo
  • #2
    soft.sc
    Level 16  
    Tak. Opóźnienia są za małe.
    Procedury opóźniające powinny wyglądać np. tak:
    Code:

    wait10us:         ; 3
    ; Procedura odlicza czas 10us
       ldi   time,11      ; 1
    wait10us_loop:   
       dec   time      ; 1
       brne   wait10us_loop   ; 2 (1)   

       ret         ; 4
    ;---------------------------------------------------------------
    waitms:
    ; przy wywolaniu procedury zadeklarowac stala TIME_MS
                ; 3
    ; procedura odlicza czas x ms
       sbiw   xh:xl,1      ; 2
       wdr
       breq   end_waitms   ; 1 (2)
       ldi   count,99 ; 99    ; 1
    licz_us:
       rcall   wait10us   ; 10us
       dec   count      ; 1
       nop         ; 1
       brne   licz_us      ; 2 (1)
       rjmp   waitms      ; 2
    end_waitms:
       ret         ; 7

    ; Przyklad zastosowania

    .SET   TIME_MS = 500                         ; 0,5 sekundy
       ldi   xl,$FF & TIME_MS
       ldi   xh,$FF & (TIME_MS >> 8)
       rcall   WAITMS


    Powyzsze procedury nie są uniwesalne. Przystosowane sa do zegara 4MHz.
  • #3
    ldarko
    Level 10  
    dziekuje za odpowiedź

    w moim przypadku prowdopobonie chodzi o wbudowany zegar 1MHz
    w jaki sposó liczyć czas opóźnień w tym przypadku

    pozdrawiam
  • #4
    zumek
    Level 39  
    soft.sc wrote:
    Tak. Opóźnienia są za małe...

    Niby dlaczego za małe(krótkie) :?:
    Procedury Delay - przy 1MHz - , wykonują się ~200ms , co daje częstotliwość "mrugania" diody ok. 5Hz , a to ludzkie oko spoko zauważy :D
    Sprawdź , czy te LED-y wogóle świecą , jak ustawimy na pinach stan wysoki.Poniżej kodzik zmieniający stany na przeciwne na PORTB , co 1000000 taktów proca.
    Code:

    .include "m8def.inc"

    #define accw r25:r24
    .def accb = r16 ;

    .cseg ;
    .org 0 ;
    rjmp Reset;

    Delay :
       nop
       nop
       ldi accb,4
       ldi r24,118
       ldi r25,47
    Del_0 :
       adiw accw,1 ; zwiększ zawartość acc
       brne Del_0 ; skocz gdy acc różne od 0
       dec accb ; zwiększ zawartość acc2
       brne Del_0 ; skocz gdy acc2 różne od 0
    ret

    Reset:
    cli
    ldi r16, low(RAMEND)
    out SPL, r16
    ldi r16, high(RAMEND)
    out SPL, r16
    ldi r20,0xFF ;LEDPin=1 to LED zgaszony
    out DDRB,r20
    out PORTB,r20 ;- chyba "zapalony" skoro masz podłączone PIN->R->LED->GND

    Main:
    rcall Delay
    in r20,PORTB
    com r20
    out PORTB,r20
    rjmp Main ;


    Piotrek
  • #5
    soft.sc
    Level 16  
    Quote:
    Niby dlaczego za małe(krótkie)

    Procedury delay liczą 256*256 cykli co daje trochę ponad 65ms dla zegara 1 MHz.
    Procedury, które podałem łatwo dostosować do dowolnego zegara. Wystarczy pozmieniać wartości ładowane do odpowiednich rejestrow. W komentarzach podane są cykle zegarowe zajmowane przez określoną instrukcję. Dla 1MHz cykl wykonuje się w czasie 1 mikrosekundy.
    Modyfikujemy tylko procedurę "wait10us:"
    Code:

    wait10us:         ; 3
    ; Procedura odlicza czas 10us
       ldi   time,1      ; 1
    wait10us_loop:   
       dec   time      ; 1
       brne   wait10us_loop   ; 2 (1)   

       ret         ; 4
  • #6
    zumek
    Level 39  
    soft.sc wrote:
    Procedury delay liczą 256*256 cykli co daje trochę ponad 65ms dla zegara 1 MHz...

    Code:

    loop:
        inc r16     ;1 cykl
        brne loop ;2 lub 1 cykl
        inc r17     ;1cykl
        brne loop ;2 lub 1 cykl
        ret

    Teraz sobie policz , czy to zajmie procowi 65ms , czy może 197ms :D
    Co innego , gdybyś użył timera ;)

    Piotrek
  • #7
    LordBlick
    VIP Meritorious for electroda.pl
    Hmm... Spróbuj regularnie migać LED, jednocześnie komunikując się z PC, obsługując pomiar temperatury za pomocą 1wire (DS18B20) i wyświetlać ją na LCD, używając waitXX... ;) Timer0 jak nic do zastosowania... Tymczasem małe co nieco w załączniku (miganie LED z użyciem timera), zarówno dla ATmega8, jak i na ATmega8515. Ponieważ ATmega8 nie posiada przerwania Output Compare0, czas jest tu mierzony za pomocą Timer0 Overflow. W przypadku ATmega8515, który to układ takowe przerwanie posiada, bez wahania go użyłem, gdyż skraca to zarówno objętość kodu wynikowego, jak i jego szybkość. Dla każdego z procesorów można oddzielnie zmieniać parametry (czas półokresu migania i prędkość zegara procesora oraz pod który pin i port jest podpięta LED - prawie jak Bascom :P) w plikach głównych TestLED_m8.asm i TestLED_m8515.asm
    Do prawidłowego skompilowania potrzebna jest standardowa instalacja AVRStudio w wersji co najmniej 4.12SP2. Tutaj można ją sciągnąć.
  • #8
    ldarko
    Level 10  
    dziekuje wszystkim za pomoc

    ostatni plik od Light-I działa poprawnie :) - dioda miga

    ale mam taki problem, kiedy użyłen kodu od od Zumek, uklad nie działał.
    Zauwazyłem jednak dziwną prawidłowość, kiedy miałem wsadzone wtyki do programatora LPT (Laptop) i dodatkowo laptop wszedl w stan wstrzymania systemu układ zaczynał działać. Sprawdziłem to jeszcze na innym podobnym przykładzie (który też realizował mruganie przez zastosowanie pętli delay) i podobnie, uklad dzialal na wstrzymaniu systemu i podlaczonych 3 stykach programatora RST, GND, i VCC podawane na programator z plytki Atmegi (tak jakby cos zamykalo sie przez LPT i bylo podawane na Atmege8)

    nie wiem czy mam coś uszkodzone czy nie, plytke uruchomieniowa zrobilem sam, taka jak na zdjeciu Atmega8, asembler, miganie diody

    czy moge prosic o jakis sprawdzony plik na atmege8 gdzie moglbym sprawdzic czy dzialaj petle Delay?
    moze ktos mial juz podobny problem?

    jeszcze raz dziekuje i pozdrawiam
  • #9
    User removed account
    User removed account  
  • #10
    LordBlick
    VIP Meritorious for electroda.pl
    Osobiście nie ufam wewnetrznemu podciągnięciu na /RESET i dokładam 4,7-10kΩ do Vcc.
    Moje procedurki w petli głównej zerują również licznik watchdog-a w pętli głównej (plik Main.asm), który gdy osiągnie maksimum, resetuje mikrokontroler. Oprócz tego jest tam taki myk, że reset od watchdoga nie inicjalizuje zmiennych(danych w RAM, m.in. licznik "tyknięć" przerwań timera, będący podstawą czasu), są w takim stanie, jak przed Reset...
  • #11
    ldarko
    Level 10  
    aha
    czyli RST ma nie wisiec w powietrzu tylko przez 4,7k lub 10k do 5V

    ps
    zauwazylem ze wasze przyklady z uzyciem Timera dzialaj poprawnie
    (nie dzieje sie nic jak laptop jest w stanie czuwania, przy wlaczanym programatorze) mam tylko problemy keidy nie uzywam Timera,
    czy dyspnuje ktos sprawdzonym przykladem na Atmega8 (wyjscia na R-dioda-masa)
    ciezko sie uczyc programowac jak "mechanika" zawodzi :)

    pozdrawiam
  • #13
    ldarko
    Level 10  
    :)
    tak w sumie to chyba z odmierzaniem czasu... (na ile potrafie rozeznac)

    poniewaz takie proste przyklady - ustawianie portów, gaszenie, zapelenie poszczegolnych diod to działa - nie potrafie zapalac i gasic na poszczegolnych portach w jednym programie bez uzycia TIMERA,
    wygladalo to tak jakby dzialalo niestabilnie i nie bylem pewny czy uklad dziala porawnie czy progrgam zle napisany

    ps
    np ten kod zapala mi tylko diody na C5 C4 C3 C1 i C0 (nie wiem czemu nie zapala na C2) no i nie mruga - a moze nie powinien??
    ... aha widze ze to walsnie c2 powinno mrugac, ale sie w ogole nie zapala

    Code:
    .include "m8def.inc" 
    

    #define accw r25:r24
    .def accb = r16 ;

    .cseg ;
    .org 0 ;
    rjmp Reset;

    Delay :
       nop
       nop
       ldi accb,4
       ldi r24,118
       ldi r25,47
    Del_0 :
       adiw accw,1 ; zwiększ zawartość acc
       brne Del_0 ; skocz gdy acc różne od 0
       dec accb ; zwiększ zawartość acc2
       brne Del_0 ; skocz gdy acc2 różne od 0
    ret

    Reset:
    cli
    ldi r16, low(RAMEND)
    out SPL, r16
    ldi r16, high(RAMEND)
    out SPL, r16
    ldi r20,0xFF ;LEDPin=1 to LED zgaszony
    out DDRC,r20
    out PORTC,r20 ;- chyba "zapalony" skoro masz podłączone PIN->R->LED->GND

    Main:
    rcall Delay
    in r20,PORTC
    com r20
    out PORTC,r20
    rjmp Main ;
    Moderated By Light-I:

    Kod ujęto w tagi [code][/code].

  • #14
    LordBlick
    VIP Meritorious for electroda.pl
    Błąd jest tu - stos ląduje w obszarze I/O (okolica przetwornika ADC) :
    Code:
    ldi r16, low(RAMEND)
    
    out SPL, r16
    ldi r16, high(RAMEND)
    out SPL, r16
    Porównaj pierwsze słowa dla procesora z moim załącznikiem (plik Main.asm)
    Code:
    ;Proc InitStack()
    
    InitStack:
    ; It must be not to be a subroutine, because must
    ; be stack point initialised before call it
    ; Inicialise Stack Point - push decrement it, pop increment
    [...]
    Tak przy okazji - zasilanie masz podpięte do AVcc też ?
  • #15
    ldarko
    Level 10  
    1) avcc wisi w powietrzu.
    2) porównałem, ale dopiero zaczynam nie wiem jak to poprawić :)
  • Helpful post
    #16
    LordBlick
    VIP Meritorious for electroda.pl
    Ok, SPL <> SPH... i podłącz AVcc, skoro uzywasz PORTC. Tak w ogóle to poczytaj notę katalogową (oczywiście nie staraj się zapamiętać wszystkiego, raczej gdzie co jest omówione), bez tego to jak bez mapy na nieznanej drodze...
  • #17
    ldarko
    Level 10  
    bardzo dziekuje za poswiecony czas :)))

    znalazlem te zmienne w pliku symreg z twojego przykładu
    i wkleilem taki kod
    Code:

    def   TempA         =   r16
    .def   TrueOrOne      =   r12
    .def   FalseOrZero      =   r13

    cli
       clr FalseOrZero ; fast Access Bool logic FALSE register
       ldi TempA, 1
       mov TrueOrOne, TempA ; fast Access Bool logic TRUE register
    .ifdef SPH
       ldi TempA, HIGH(RAMEND)
       out SPH, TempA
    .endif
       ldi TempA, LOW(RAMEND)
    out SPL, TempA


    i działa :) teraz sobie mruga - wprawdzie C2 dalej nie odpowiada, w kazdym razie rozumiem

    ps
    czy moge prosic jeszcze tylko o krotkie wytlumaczenie "gdzie to lądowało" tzn co było problemem

    pozdrawiam
  • #18
    LordBlick
    VIP Meritorious for electroda.pl
    W pliku "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m8def.inc" jest :
    Code:
    .equ   RAMEND   = 0x045f
    Tak więc (po reset wszystkie rejestry I/O zostają wyzerowane, więc SP=0x000) :
    Code:
    ldi r16, low(RAMEND)
    
    out SPL, r16
    ^ SP=0x005F [adres SREG dla ld(s)/st(s)]
    Code:
    ldi r16, high(RAMEND)
    
    out SPL, r16
    ^ SP=0x0004 [adres ADCL dla in/out/sbi/cbi/sbic]
    Gdyby to drugie było tak :
    Code:
    ldi r16, high(RAMEND)
    
    out SPH, r16
    ^ SP=0x045F i wszystko byłoby w porządku - stos zostałby ustawiony na koniec pamięci RAM, tak jak być powinno.
    PC2 może "nie odpowiadać" właśnie dlatego, że nie jest podłączone AVcc (zasilanie części analogowej i PC3, PC2, PC1, PC0 - s. 59, 60 noty katalogowej), lub coś nie tak z połączeniami.
  • #19
    ldarko
    Level 10  
    rozumiem

    jeszcze raz dziekuje za pomoc
    ps
    na pewno niedlugo nastepne pytania :)

    pozdrawiam