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.

Atmega16 działa tylko jeden licznik

artur816 28 Kwi 2008 11:50 857 3
  • #1 28 Kwi 2008 11:50
    artur816
    Poziom 9  

    Witam
    Próbuje napisać program w asemblerze wykorzystujący przerwania od dwóch liczników (uczą dopiero programowania avr w asemblerze)
    Przerwanie od licznika 0 ma obsługiwać pierwsze cztery wyświetlacze
    a przerwania od licznika 2 kolejne 4
    Problem polega na tym - że pojedynczo liczniki działają a jak chce użyć dwóch to działa tylko jeden (licznik 2).
    Nie wiem gdzie jest błąd - czy coś przeoczyłem ?
    jakiś rejestr czy co ?


    .INCLUDE "m16def.inc"
    .EQU SYS_FREQ = 1


    .ORG 0 ; wektor zerowania
    rjmp Reset ; skok do procedurty inicjalizujacej



    .ORG $008 rjmp licznik2

    .ORG $012 rjmp licznik0




    Reset:
    ldi R16, HIGH(RAMEND) ;załadowanie adresu końca pamięci
    out SPH, R16
    ldi R16, LOW(RAMEND)
    out SPL, R16

    sbi DDRA, 0
    sbi DDRA, 1
    sbi DDRA, 2
    sbi DDRA, 3
    sbi DDRA, 4
    sbi DDRA, 5
    sbi DDRA, 6
    sbi DDRA, 7

    sbi DDRC, 0
    sbi DDRC, 1
    sbi DDRC, 2
    ;----------------------------------------------------
    ldi R22, 0
    ldi R20, 5

    ldi R16, (1<<WGM01)|(1<<CS02)|(1<<CS00)
    out TCCR2, R16
    ldi R16, (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20)
    out TCCR0, R16

    ldi R16, (1<<OCIE2)|(1<<OCIE0)
    out TIMSK, R16

    ldi R16, SYS_FREQ*1
    out OCR2, R16
    ldi R16, SYS_FREQ*2
    out OCR0, R16

    sei

    ;---------------------------------------------------
    petla:
    rjmp petla


    licznik2:
    push R16
    push R17
    push ZL
    push ZH
    in R16, SREG
    push R16

    cpi R22, 4
    breq poczatek2

    ldi R23, 0b00011000

    out PORTC, R22 ; ktory wyswietlacz
    out PORTA, R23 ; wyswietlana wartosc
    inc R22

    pop R16
    out SREG, R16
    pop ZH
    pop ZL
    pop R17
    pop R16
    reti

    poczatek2:
    ldi R22, 0
    pop R16
    out SREG, R16
    pop ZH
    pop ZL
    pop R17
    pop R16
    reti
    ;-----------------------------------------------------

    licznik0:
    push R16
    push R17
    push ZL
    push ZH
    in R16, SREG
    push R16
    cpi R20, 8
    breq poczatek0

    ldi R21, 0b11100000

    out PORTC, R20 ; ktory wyswietlacz
    out PORTA, R21 ; wyswietlana wartosc
    inc R20

    pop R16
    out SREG, R16
    pop ZH
    pop ZL
    pop R17
    pop R16
    reti

    poczatek0:
    ldi R20, 5
    pop R16
    out SREG, R16
    pop ZH
    pop ZL
    pop R17
    pop R16
    reti

    0 3
  • #2 28 Kwi 2008 12:08
    Balu
    Poziom 38  

    Z ciekawości czemu nie wszystkie wyświetlacze na jednym timerze? Czemu nie piszesz zamiast

    Code:

     sbi DDRA, 0
    sbi DDRA, 1
    sbi DDRA, 2
    sbi DDRA, 3
    sbi DDRA, 4
    sbi DDRA, 5
    sbi DDRA, 6
    sbi DDRA, 7

    Code:

    ldi r16,0xff
    out DDRA, r16?


    Dodano po 13 [sekundy]:

    No i używaj znaczników code...

    0
  • #3 28 Kwi 2008 12:14
    Ch.M.
    Poziom 27  

    może dlatego Ci licznik nr.0 nie działa bo ustawiasz jego źródło na sygnał zewnętrzny taktowany zboczem narastającym :) (przeładowałeś za duzo CSn z rejestru TCCR0)
    a dokładniej tu się walnąłeś myląc rejestry:

    Code:
    ldi R16, (1<<WGM01)|(1<<CS02)|(1<<CS00) 
    
    out TCCR2, R16
    ldi R16, (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20)
    out TCCR0, R16


    parę uwag:
    zamiast
    Code:
    sbi DDRA, 0 
    
    sbi DDRA, 1
    sbi DDRA, 2
    sbi DDRA, 3
    sbi DDRA, 4
    sbi DDRA, 5
    sbi DDRA, 6
    sbi DDRA, 7

    napisz
    Code:
    ldi R16, 0b11111111 albo 255
    
    out DDRA, R16



    Program mało kompaktowy
    Komentarze szczątkowe!
    Pozdrawiam i polecam się

    P.S.
    Code:
    $006 TIMER2 COMP Timer/Counter2 Compare Match
    
    $012 TIMER0 OVF Timer/Counter0 Overflow

    U ciebie po 1 zły adres dla przerwania od porównania zgodności T2
    po 2 złe przerwanie na T0 od porówniania zgodności, nieobsługiwane sprzętowo, zmień je na przepełnieniowe T2 i zobacz czy dalsze zmieny są konieczne.

    0
  • #4 28 Kwi 2008 14:21
    artur816
    Poziom 9  

    A nie mogą oba przerwania od liczników 0 i 2 działać niezależnie ?
    ldi R16, SYS_FREQ*1
    out OCR2, R16
    ldi R16, SYS_FREQ*2
    out OCR0, R16
    w rejestrze OCR0 mam wartość dwa razy większą niż w OCR2.
    Jeśli zakomentarzuje ustawienia jednego licznika i jego przerwania to drugi działa i na odwrot .
    Próbuje korzystać z dwóch liczników na raz i juz nie wychodzi tak jak bym chcial
    (a co do Waszych podpowiedzi :
    ldi R16, 0b11111111 albo 255
    out DDRA, R16
    - dzięki , napisałem dłuższą wersje tego tylko dlatego że od takiej wersji zaczołem poznawanie AVR - zapalanie diody i te sprawy)

    Dodano po 1 [godziny]:

    Znalazłem błąd
    ldi R16, (1<<WGM01)|(1<<CS02)|(1<<CS00)
    out TCCR2, R16
    ldi R16, (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20)
    out TCCR0, R16
    źle przypisywałem bity w rejestrach
    powinno być:
    ldi R16, (1<<WGM21)|(1<<CS22)
    out TCCR2, R16

    ldi R16, (1<<WGM01)|(1<<CS01)|(1<<CS00)
    out TCCR0, R16

    - tak to jest jak się robi Ctrl C Ctrl V

    ale Wielkie dzięki za włączenie się do tematu

    0