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

Atmega8, asembler - jak uzyskać miganie diody na całym PORTB bez Timera?

ldarko 14 Cze 2006 23:12 9262 18
  • #1 2729616
    ldarko
    Poziom 10  
    Posty: 39
    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
  • #2 2730564
    soft.sc
    Poziom 17  
    Posty: 142
    Pomógł: 15
    Ocena: 4
    Tak. Opóźnienia są za małe.
    Procedury opóźniające powinny wyglądać np. tak:
    
    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 2730618
    ldarko
    Poziom 10  
    Posty: 39
    dziekuje za odpowiedź

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

    pozdrawiam
  • #4 2730874
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    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.
    
    .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 2731266
    soft.sc
    Poziom 17  
    Posty: 142
    Pomógł: 15
    Ocena: 4
    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:"
    
    wait10us:			; 3
    ; Procedura odlicza czas 10us
    	ldi	time,1		; 1
    wait10us_loop:	
    	dec	time		; 1
    	brne	wait10us_loop	; 2 (1)	
    
    	ret			; 4
    
  • #6 2731392
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    soft.sc napisał:
    Procedury delay liczą 256*256 cykli co daje trochę ponad 65ms dla zegara 1 MHz...

    
    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 2731627
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    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ąć.
    Załączniki:
    • TestLED.zip (8.73 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #8 2733156
    ldarko
    Poziom 10  
    Posty: 39
    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 - jak uzyskać miganie diody na całym PORTB bez Timera?

    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 2733274
    Konto nie istnieje
    Konto nie istnieje  
  • #10 2733575
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    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 2733593
    ldarko
    Poziom 10  
    Posty: 39
    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 2733646
    ldarko
    Poziom 10  
    Posty: 39
    :)
    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

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

  • #14 2733726
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    Błąd jest tu - stos ląduje w obszarze I/O (okolica przetwornika ADC) :
    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)
    ;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 2733758
    ldarko
    Poziom 10  
    Posty: 39
    1) avcc wisi w powietrzu.
    2) porównałem, ale dopiero zaczynam nie wiem jak to poprawić :)
  • Pomocny post
    #16 2733777
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    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 2733803
    ldarko
    Poziom 10  
    Posty: 39
    bardzo dziekuje za poswiecony czas :)))

    znalazlem te zmienne w pliku symreg z twojego przykładu
    i wkleilem taki kod
    
    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 2733846
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    W pliku "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m8def.inc" jest :
    .equ	RAMEND	= 0x045f
    Tak więc (po reset wszystkie rejestry I/O zostają wyzerowane, więc SP=0x000) :
    ldi r16, low(RAMEND)
    out SPL, r16
    ^ SP=0x005F [adres SREG dla ld(s)/st(s)]
    ldi r16, high(RAMEND)
    out SPL, r16
    ^ SP=0x0004 [adres ADCL dla in/out/sbi/cbi/sbic]
    Gdyby to drugie było tak :
    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 2733882
    ldarko
    Poziom 10  
    Posty: 39
    rozumiem

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

    pozdrawiam

Podsumowanie tematu

✨ Dyskusja dotyczy problemu uzyskania migania diody na całym porcie PORTB mikrokontrolera Atmega8 w asemblerze bez użycia timera. Początkowe opóźnienia w pętlach delay były zbyt krótkie lub niepoprawnie liczone, co powodowało niestabilne działanie migania. Zaproponowano procedury opóźniające dostosowane do częstotliwości zegara procesora (1 MHz lub 4 MHz), z dokładnym rozbiciem cykli zegarowych instrukcji. Wskazano, że stos (stack pointer) był błędnie inicjalizowany – zamiast zapisywać wartość do rejestru SPH, zapisywano do SPL dwie części adresu RAMEND, co powodowało, że stos lądował w obszarze rejestrów I/O, m.in. w okolicy przetwornika ADC. Poprawne ustawienie SPH i SPL oraz podłączenie zasilania AVcc (szczególnie dla portu C) rozwiązało problem niereagujących pinów (np. PC2). Zwrócono uwagę na konieczność stosowania rezystora podciągającego 4,7-10 kΩ do linii RESET, aby uniknąć niestabilności układu. Zaproponowano również użycie timera dla stabilnego odmierzania czasu i migania diody, co jest bardziej niezawodne niż pętle opóźniające. Dołączono przykładowe kody asemblerowe z poprawnym inicjowaniem stosu i opóźnieniami, działające na Atmega8. Podkreślono znaczenie zapoznania się z notą katalogową mikrokontrolera dla prawidłowego zrozumienia i konfiguracji sprzętu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA