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.

Atmega8, asembler, miganie diody

ldarko 14 Cze 2006 23:12 8050 18
  • #1 14 Cze 2006 23:12
    ldarko
    Poziom 9  

    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

    0 18
  • #2 15 Cze 2006 12:06
    soft.sc
    Poziom 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.

    0
  • #3 15 Cze 2006 12:27
    ldarko
    Poziom 9  

    dziekuje za odpowiedź

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

    pozdrawiam

    0
  • #4 15 Cze 2006 13:51
    zumek
    Poziom 39  

    soft.sc napisał:
    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

    0
  • #5 15 Cze 2006 16:11
    soft.sc
    Poziom 16  

    Cytat:
    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

    0
  • #6 15 Cze 2006 17:05
    zumek
    Poziom 39  

    soft.sc napisał:
    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

    0
  • #7 15 Cze 2006 18:32
    LordBlick
    VIP Zasłużony dla elektroda

    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ąć.

    0
  • #8 16 Cze 2006 09:50
    ldarko
    Poziom 9  

    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

    0
  • #9 16 Cze 2006 10:27
    Anonymous
    Użytkownik usunął konto  
  • #10 16 Cze 2006 12:10
    LordBlick
    VIP Zasłużony dla elektroda

    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...

    0
  • #11 16 Cze 2006 12:17
    ldarko
    Poziom 9  

    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

    0
  • #12 16 Cze 2006 12:24
    LordBlick
    VIP Zasłużony dla elektroda

    Tak w sumie to z czym masz problem - z odmierzaniem czasu, czy zapalaniem i gaszeniem ?

    0
  • #13 16 Cze 2006 12:33
    ldarko
    Poziom 9  

    :)
    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 ;
    Moderowany przez Light-I:

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

    0
  • #14 16 Cze 2006 13:07
    LordBlick
    VIP Zasłużony dla elektroda

    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ż ?

    0
  • #15 16 Cze 2006 13:17
    ldarko
    Poziom 9  

    1) avcc wisi w powietrzu.
    2) porównałem, ale dopiero zaczynam nie wiem jak to poprawić :)

    0
  • Pomocny post
    #16 16 Cze 2006 13:23
    LordBlick
    VIP Zasłużony dla elektroda

    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...

    0
  • #17 16 Cze 2006 13:31
    ldarko
    Poziom 9  

    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

    0
  • #18 16 Cze 2006 13:43
    LordBlick
    VIP Zasłużony dla elektroda

    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.

    0
  • #19 16 Cze 2006 13:54
    ldarko
    Poziom 9  

    rozumiem

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

    pozdrawiam

    0