2016-04-06 8 views
0

Ich versuche, den Einsatz von Interrupts als eine Möglichkeit zum Timing Aktionen auf einem 6502 Teensy Micro-Controller zu bekommen. Ich habe es geschafft, einen Zähler zu schaffen, die durch das Auslösen der Interrupt-Bits schneller ergänzt:Grundlegende Programmierung eines Mikrocontrollers 6502 mit Interrupts

%uasm65 
; v.002 
; Increment port 0A200h at a rate of once increment 
; per second. Use the timer based interrupt handler 
; to control the time delay. 

T1LL: equ B006h 
T1LH: equ B007h 
IER: equ B00Eh 
ACR: equ B00Bh 
COUNTDOWN: equ 500d 
IRQVect: equ 0002d 
OutChar: equ 0e003h 
PrntMess: equ 0e00ch 

org 0200h 

lda #0d 

sta IER    ; Disable all interrupts. 
lda #11000000b 
sta ACR    ; Set to T1 free running mode; 

lda #COUNTDOWN< 
sta T1LL   ; Low byte of latch. 
lda #COUNTDOWN> 
sta T1LH   ; High byte of latch. 


; Initialize the interrupt vector. 
    lda #InterruptHandler< 
    sta IRQVect 
    lda #InterruptHandler> 
    sta IRQVect+1d 

    lda #01000000b 
    sta IER  ; Enable all interrupts 
    cli   ; Enable interrupts 

MainLoop: 
    nop 
    jmp MainLoop 



InterruptHandler: 
;Save registers on the stack. 
    php 
    pha 
    txa 
    pha 
    tya 
    pha 
    inc 0a200h 

;Restore registers from the stack. 
    pla 
    tay 
    pla 
    tax 
    pla 
    plp 

    cli ; Enable interrupts. 
    rti ; Return from interrupt. 

    end 
%/uasm65 

Was ich versuche, einmal pro Sekunde an die Konsole „Hallo“ drucken zu tun ist, und „dort“, wenn die IRQ gedrückt, löst den Interrupt aus. Würde ich eine Verzögerungsschleife wie zum Beispiel verwenden:

Delay: 
;Save registers on the stack. 
pha 
txa 
pha 
tya 
pha 

;Change the number that is being loaded into the 
; 'A' register in order to change the delay time. 
lda 0a600h 

OutLoop: 
ldx #0dfh 

InLoop1: 
ldy #0ffh 

InLoop2: 
dey 
bne InLoop2 

dex 
bne InLoop1 

sec 
sbC#1d 
bne OutLoop 

;Restore registers from the stack. 
pla 
tay 
pla 
tax 
pla 

rts 

end 

Oder brauche ich etwas, das von Interrupts Zeit ist? Jede Anleitung wäre hilfreich.

+2

Der 6502, mit dem ich arbeitete, hatte keine integrierten Timer oder Ports, Sie mussten einen peripheren IC verwenden, wie zum Beispiel einen 6522 VIA mit Speicherabbild. Wenn Sie einen Timer verwenden, müssen Sie die IRQ-Anforderung durch Lesen des [Datenblatt] (http://www.princeton.edu/~mae412/HANDOUTS/Datasheets/6522.pdf) löschen. Die Verwendung einer Software-Schleife für eine Zeitverzögerung ist eine Übung für Schüler, es verschwendet nur kostbare Prozessorzeit. –

+1

Ich arbeite mit einem Teensy Minicontroller, der LEDs steuert. – user3050884

+0

Kleine Nebenbeobachtung: 'RTI' zieht das Statusregister vom Stapel, bevor es den Programmzähler zieht; Sie brauchen nicht vorher 'CLI'. – Tommy

Antwort

0

Wenn Ihr 6502 mit 1 MHz läuft, bedeutet dies, dass 1.000.000 Zyklen in 1 Sekunde ausgeführt werden. Die minimale Anzahl von Zyklen, die ein Befehl ausführen kann, ist 2 und das Maximum ist 8 (das tatsächliche Maximum ist 7, aber einige Befehle haben einen Strafzyklus, wenn die Adresse eine Seite überspannt, beispielsweise 22FF-2300).

Wenn Sie also nicht auf einen Timer warten möchten, können Sie jede kreative Möglichkeit finden, 1 Million Zyklen zu brennen. Natürlich werden Sie sich auf Schleifen verlassen. Jede gute 6502-Befehlsreferenz gibt Ihnen die Zykluszeiten für jede einzelne Anweisung.

Wenn Sie die Fabrikausrüstung steuern, sind Verzögerungsschleifen ohne Kontrolle einer Unterbrechungsquelle, einschließlich NMI und RESET, ein No-No. Aber dir geht es gut hier.

Also, du machst es richtig - aber nicht an der richtigen Stelle.

Ich nehme an, Ihre Hauptschleife würde "Hallo" einmal pro Sekunde drucken, und die ISR würde "There" drucken. Sie möchten also Ihre Verzögerungsschleife nicht in den ISR legen. Die Wörter "Verzögerung" und "Wartungsroutine unterbrechen" gehen in der Regel niemals zusammen.

Sie wollen wahrscheinlich nicht, dass die Sache so etwas wie Drucken Hello Hello HeTherello Hello entweder tut.

Sie müssen also Ihren ISR konstruieren, um nichts anderes zu tun, als eine Flagge zu setzen, die dann von Ihrer Hauptschleife überprüft wird. Ihre Hauptschleife kann in jeder Schleife nach dieser Flagge suchen und "Dort" drucken, nach Drucken "Hallo", wenn es gesetzt ist. Es sollte dann offensichtlich die Flagge löschen.

Wenn Sie möchten, dass dies in dem Moment reagiert, in dem Sie den IRQ auslösen, müssen Sie möglicherweise nach dem Flag in Ihrer Verzögerungsschleife suchen und die Schleife beenden, wenn das Flag gesetzt ist. Wenn Sie dies tun, müssen Sie auch die Entprellung implementieren - Sie brauchen entweder eine Zeitspanne, in der das Flag ignoriert wird oder eine Programmierung, um nur dann das Flag zu setzen, wenn eine Taste gedrückt und dann losgelassen wird - es sei denn, Sie tun dies nicht Beachten Sie, dass die Einheit ständig "Hello There" spammt, während die Taste gedrückt wird.