2016-04-06 4 views
0

J'essaie de comprendre les interruptions comme moyen de synchroniser les actions sur un micro-contrôleur Teensy 6502. J'ai réussi à créer un compteur qui ajoute des bits plus rapide en déclenchant l'interruption:Programmation de base d'un microcontrôleur 6502 utilisant des interruptions

%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 

Ce que je suis en train de faire est d'imprimer « bonjour » à la console une fois par seconde et « là » lorsque l'IRQ est appuyé, déclenchant l'interruption. Aurais-je utiliser une boucle de retard comme:

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 

Ou ai-je besoin de quelque chose qui est chronométré par des interruptions? Toute orientation serait utile.

+2

Le 6502 avec lequel je travaillais n'avait pas de minuteries ou de ports intégrés, vous deviez utiliser un circuit intégré périphérique, tel qu'un 6522 VIA mappé en mémoire. Si vous utilisez une minuterie, vous devez effacer la demande d'IRQ en lisant la [fiche technique] (http://www.princeton.edu/~mae412/HANDOUTS/Datasheets/6522.pdf). L'utilisation d'une boucle logicielle pour un temps de retard est un exercice de laboratoire d'étudiant, il perd juste le temps précieux de processeur. –

+1

Je travaille avec un mincrocontroller teensy qui contrôle des LEDs. – user3050884

+0

Observation de côté mineure: 'RTI' tire le registre d'état de la pile avant de tirer le compteur de programme; vous n'avez pas besoin de 'CLI' avant. – Tommy

Répondre

0

Si votre 6502 fonctionne à 1 MHz, cela signifie qu'il exécute 1 000 000 cycles en 1 seconde. Le nombre minimum de cycles qu'une instruction peut prendre est de 2 et le maximum est de 8 (le maximum réel est de 7 mais certaines instructions ont un cycle de pénalité si l'adresse couvre une page par exemple 22FF-2300). Donc, si vous ne voulez pas compter sur une minuterie, vous pouvez trouver un moyen créatif de brûler 1 million de cycles. Évidemment, vous compterez sur les boucles. Toute bonne référence d'instruction 6502 vous donnera les temps de cycle pour chaque instruction individuelle.

Si vous contrôliez des équipements d'usine, les boucles de temporisation sans contrôle de source d'interruption, y compris NMI et RESET, est un non-non. Mais vous allez bien ici. Donc, vous le faites de la bonne façon - mais pas au bon endroit.

Je suppose que votre boucle principale imprimerait "Bonjour" une fois par seconde, et l'ISR afficherait "Là". Donc vous ne voulez pas mettre vos boucles de retard dans les ISR. Les mots «retard» et «interruption de la routine de service» ne vont généralement jamais ensemble.

Vous ne voulez probablement pas que la chose fasse quelque chose comme imprimer Hello Hello HeTherello Hello non plus.

Vous avez donc besoin de construire votre ISR pour ne rien faire mais définir un drapeau que votre boucle principale va ensuite vérifier. Votre boucle principale peut vérifier ce drapeau chaque boucle et imprimer "Là", après impression "Bonjour", si elle est définie. Il devrait alors effacer le drapeau, évidemment.

Si vous souhaitez que cela réponde au moment où vous déclenchez l'IRQ, vous devrez peut-être vérifier l'indicateur dans votre boucle de délai et terminer la boucle si le drapeau est activé. Si vous faites cela, vous devrez également implémenter l'anti-rebond - vous aurez besoin soit d'une période où le drapeau est ignoré, soit d'une programmation pour ne définir le drapeau que si un bouton appuie dessus et que la sortie est détectée - sauf si vous ne le faites pas attention à l'unité spamming "Bonjour là" constamment pendant que le bouton est pressé.