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.

ATtiny 12: asembler - zwiekszanie zmiennej w przerwaniu

ucy74 05 Lip 2006 12:59 1786 11
  • #1 05 Lip 2006 12:59
    ucy74
    Poziom 20  

    Chcę kożystać z przerwania INT0, a w nim o jeden powiększać zmienną zapisywaną w rejestrze np.: r20. Niestety po powrocie z przerwania zerowany jest stan rejestrów, awięc zmienna znika. Komend Push i Pop nie ma w ATtiny12.

    Jak operować na zmiennych?
    Jak odkładać je na stos?

    0 11
  • #2 05 Lip 2006 14:19
    Nawigator
    Poziom 33  

    Tiny12 ma stos sprzetowy 3-poziomowy czyli w jednym momencie możesz mieć wpisane tylko 3 adresy powrotu. Jezeli masz jeden użyty bo jesteś w przerwaniu to innych odwołań np. przy rcall może być co najwyżej 2 poziomy. Jak jest więcej to musisz przerobić program, czasem kosztem długości kodu.
    Popatrz jak były pisane programy na 1200.
    Pozdr. N.

    0
  • #3 30 Lip 2006 17:15
    ucy74
    Poziom 20  

    Znalazłem, na razie, dwa sposoby:
    Pierwszy, to używanie w przerwaniu wartości wpisywanej w rejestry Osccal lub Tcnt0, oczywiście niewłaściwe, ale przydatne ;-)
    Drugi, to zerowanie w przerwaniu flagi komendą Cli, a potem powrót z przerwania nie komendą Reti, ale skok do poczatku programu gdzie ustawiam parametry przerwań i je odblokowuję.

    0
  • #4 30 Lip 2006 17:56
    zumek
    Poziom 39  

    ucy74 napisał:
    Znalazłem, na razie, dwa sposoby:
    Pierwszy, to używanie w przerwaniu wartości wpisywanej w rejestry Osccal lub Tcnt0, oczywiście niewłaściwe, ale przydatne ;-)
    Drugi, to zerowanie w przerwaniu flagi komendą Cli, a potem powrót z przerwania nie komendą Reti, ale skok do poczatku programu gdzie ustawiam parametry przerwań i je odblokowuję.

    Nie rozumiem stwierdzenia:"Niestety po powrocie z przerwania zerowany jest stan rejestrów, awięc zmienna znika."Gdyby było tak jak piszesz , to niemożliwością było by używanie przerwań , jeśli po powrocie z przerwania , rejestry by się zerowały.Musiałeś coś pokiełbasić w kodzie :D

    Piotrek
    PS
    Zbudowałem na ATtiny12 ściemniacz oświetlenia ,gdzie wykorzystywane są przerwania zewnętrzne oraz timera i nie stwierdziłem znikania/zerowania rejestrów.

    0
  • #5 02 Sie 2006 11:11
    ucy74
    Poziom 20  

    Byłaby szansa na jakiś kawałek kodu asm ze zwiększaniem wartości zmiennej w przerwaniu :-) ? Zmienna ustawia potem stan wyjść.

    0
  • #6 02 Sie 2006 21:11
    zumek
    Poziom 39  

    ucy74 napisał:
    Byłaby szansa na jakiś kawałek kodu asm ze zwiększaniem wartości zmiennej w przerwaniu :-) ? Zmienna ustawia potem stan wyjść.

    Np.
    Code:

    .include "tn12def.inc"
    .cseg
    .org 0x000
       rjmp start
    .org INT0addr
       rjmp intr0
    start:
       in r16,GIMSK
       ori r16,(1<<INT0)
       out GIMSK,r16
       in r16,MCUCR
       ori r16,(1<<ISC01)
       out MCUCR,r16
       sbi DDRB,PB0
       cbi DDRB,PB1
       sbi PORTB,PB1
       clr r20
       sei
    lop:
       sbrc r20,0
       sbi  PORTB,0
       sbrs r20,0
       cbi PORTB,0
       rjmp lop
    intr0:
       inc r20
       in r16,GIMSK
       andi r16,~(1<<INT0)
       out GIMSK,r16
       reti


    Piotrek

    0
  • #7 03 Sie 2006 00:00
    ucy74
    Poziom 20  

    Wkleiłem i dopisałem to o co chodziło mi w docelowym kodzie. Każde powiększenie liczby w przerwaniu ustawia określony stan na porcie. Muszę omijać pin na który trafia przerwanie :-)

    Niestety - przerwanie wywołuje się tylko pierwszy raz... :cry:

    Code:
    .include "tn12def.inc"
    
    .cseg
    .org 0x000
       rjmp start

    .org INT0addr
       rjmp intr0

    start:
       in r16,GIMSK
       ori r16,(1<<INT0)
       out GIMSK,r16
       in r16,MCUCR
       ori r16,(1<<ISC01)
       out MCUCR,r16
       sbi DDRB,PB0  - podobnie powinienem chyba opisać pozostałe piny - ddrb = 00001101
       cbi DDRB,PB1
       sbi PORTB,PB1
       clr r20
       sei

    loop:   
       ldi r21, 1
       cp r20,r21
       breq  SEQ1

       ldi r21, 2
       cp r20,r21
       breq  SEQ2

       ldi r21, 3
       cp r20,r21
       breq SEQ3

       ldi r21, 4
       cp r20,r21
       breq SEQ4

       ldi r21, 5
       cp r20,r21
       breq SEQ5
       rjmp loop

    Seq1:
       ldi r22, 1
            out Portb, r22
       rjmp loop

    Seq2:
       ldi r22, 4
          out Portb, r22
       rjmp loop

    Seq3:
       ldi r22, 8
          out Portb, r22
       rjmp loop

    Seq4:
       ldi r22, 13
       out Portb, r22
       rjmp loop

    Seq5:
       ldi r22, 0
       out Portb, r22
       ldi r20, 0
       rjmp loop

    intr0:
       inc r20
       in r16,GIMSK
       andi r16,~(1<<INT0)
       out GIMSK,r16
       reti


    Jeśli można prosić o objaśnienie:
    Code:
       ori r16,(1<<INT0)
    
       ...
       ...
       ori r16,(1<<ISC01)
       ...
       ...
       andi r16,~(1<<INT0)

    0
  • #8 03 Sie 2006 17:21
    zumek
    Poziom 39  

    ucy74 napisał:
    ...Niestety - przerwanie wywołuje się tylko pierwszy raz... :cry:

    Bo tak napisałem kod , że przerwanie samo siebie wyłacza , byś napewno widział , że zadziałało ;)
    Twoje instrukcje , poza włączaniem i wyłączaniem pullupów na PORTB , nic więcej nie robią .Ty pewnie chcesz pomrugać LED-ami na tym porcie ?
    Instrukcje ORI/ANDI , ustawiają/kasują bity.Jeśli chcesz by przerwanie działało nonstop , pozostaw tylko inc r20 i reti , a resztę usuń.

    Piotrek

    0
  • #9 04 Sie 2006 21:08
    ucy74
    Poziom 20  

    Przepisałem wedle swej wiedzy. Symulacja w AVR Studio 4 działa poprawnie, ale po zaprogramowaniu LED'y nie migają...

    Code:
    .include "tn12def.inc"
    
    .cseg
    .org 0x000
       rjmp start

    .org INT0addr
       rjmp intr0

    start:
       ldi r16, 13
       out 0x17, r16
       ldi r16, 0
       out 0x18, r16
       clr r20
       clr r21
       clr r22
       clr r23

       ldi r16,64
       out 0x3b,r16
       ldi r16,51
       out 0x35,r16
       sei

    loop:
       cpi r23, 1
       breq seq0   
       sleep
       rjmp loop

    Seq0:
       ldi r21, 1
       cp r20,r21
       breq  SEQ1

       ldi r21, 2
       cp r20,r21
       breq  SEQ2

       ldi r21, 3
       cp r20,r21
       breq SEQ3

       ldi r21, 4
       cp r20,r21
       breq SEQ4

       ldi r21, 5
       cp r20,r21
       breq SEQ5
       rjmp loop

    Seq1:
       ldi r22, 1
          out 0x18, r22
       ldi r23, 0
       rjmp loop

    Seq2:
       ldi r22, 4
          out 0x18, r22
       ldi r23, 0
       rjmp loop

    Seq3:
       ldi r22, 8
          out 0x18, r22
       ldi r23, 0
       rjmp loop

    Seq4:
       ldi r22, 13
       out 0x18, r22
       ldi r23, 0
       rjmp loop

    Seq5:
       ldi r22, 0
       out 0x18, r22
       ldi r20, 0
       ldi r23, 0
       rjmp loop

    intr0:
       ldi r23, 1
       inc r20
       reti

    0
  • Pomocny post
    #10 05 Sie 2006 12:30
    zumek
    Poziom 39  

    ucy74 napisał:
    Przepisałem wedle swej wiedzy. Symulacja w AVR Studio 4 działa poprawnie, ale po zaprogramowaniu LED'y nie migają...

    Drogi kolego ucy74 , jeśli już coś robisz , to rób to dobrze , albo nie rób wogóle - nie mogłem się powstrzymać ;)
    Ustawiasz INT0 na wyzwalanie zboczem narastającym ,"usypiasz" proca snem głębokim (Power-down) i dziwisz się , że nie chce się obudzić :(
    Na str.31 dokumentacji ATTiny12 , jest jasno napisane ...:
    Only an external reset, a watchdog reset (if enabled), an external level interrupt, or an pin change interrupt can wake up the MCU.
    Większość (jeśli nie każdy) AVR-ów , tak już ma :D

    Piotrek

    0
  • #11 06 Sie 2006 01:05
    ucy74
    Poziom 20  

    zumek napisał:
    ...jeśli już coś robisz , to rób to dobrze , albo nie rób wogóle...
    Jeśli chcesz coś zrobić - zanim zrobisz to dobrze, musisz to zrobić jakkolwiek... ;-) ...inna szkoła.
    zumek napisał:
    ...an external level interrupt, or an pin change interrupt can wake up the MCU.
    Czyli, że jeśli ustawiam zewnętrzne przerwanie na narastające zbocze to µC śpi dalej? Powinienem ustawić przerwanie na low level?

    0