15. Διακοπές με αλλαγή κατάστασης πιν – προτεραιότητα

Στον ATmega328 σε κάθε πόρτα υπάρχει μια διακοπή αλλαγής κατάστασης των πινς. Όταν η διακοπή αλλαγής κατάστασης της πόρτας είναι ενεργοποιημένη, κάθε αλλαγή στις καταστάσεις των πινς οδηγούν στη δημιουργία μιας διακοπής. Δες την ακόλουθη εικόνα. Ο καταχωρητής PCICR περιέχει τα bits ενεργοποίησης για τις πόρτες.

Για κάθε PCINT πιν της κάθε πόρτας ορίζεται και ένα bit ενεργοποίησης. Εάν το bit ενεργοποίησης γίνει 1, αλλαγές σε αυτό το πιν οδηγούν και σε μια διακοπή.

Χρησιμοποιώντας τις διακοπές αλλαγής κατάστασης των πιν

Για να χρησιμοποιήσουμε τις διακοπές αλλαγής κατάστασης πιν, τα επόμενα θα πρέπει να τεθούν σε 1.
(α) τα κατάλληλα bits των καταχωρητών PCMSKn
(β) τα PCIEn bits των σχετικών θυρών.
(γ) η σημαία Ι στον καταχωρητή κατάστασης SREG.

Παράδειγμα: Τα πιν ΡΒ0, ΡΒ2 και ΡΒ3 είναι συνδεμένα σε διακόπτες. Γράψε ένα πρόγραμμα που να κάνει το πιν PORTB.5 high όταν οποιοδήποτε από τους διακόπτες αλλάζει κατάσταση.

Απάντηση
Για να ενεργοποιήσουμε τις διακοπές που προκαλούνται με αλλαγή κατάστασης στα πινς ΡΒ0, ΡΒ2 και ΡΒ3 τα επόμενα θα πρέπει να τεθούν σε high:
(1) Tα bits 0, 2 και 3 του καταχωρητή PCMSK0 ( o PCMSK0 αντιστοιχεί στην PORTB)
(2) PCIE0 του PCICR (το PCIE0 αντιστοιχεί για την PORTB)
(3) Την σημαία Ι

.ORG   0                          ;location for reset
       JMP  MAIN
.ORG   0x06                       ;location for pin change interrupt 0
       JMP  PCINT0_ISR
MAIN:  LDI  R20, HIGH(RAMEND)
       OUT  SPH, R20
       LDI  R20, LOW(RAMEND)
       OUT  SPL, R20               ;initialize stack
       SBI  DDRB,5                 ;PB5 as output
       CBI  PORTB, 5               ;PB5 = low
       LDI  R20, 0b00001101
       STS  PCMSK0, R20            ;enable PB0, PB2, and PB3 in PCMSK0
       OUT  PORTB, R20             ;enable pull-up resistors
       LDI  R20, (1<<PCIE0)
       STS  PCICR, R20             ;enable PORTB change interrupt
       SEI                         ;enable interrupts
HERE:  JMP  HERE                   ;stay here

PCINT0_ISR:
       SBI  PORTB,5                ;PB5 = high
       RETI                        ;return

Προτεραιότητα εξυπηρέτησης διακοπών

Στην επόμενη ενότητα θα συζητήσουμε τι θα συμβεί εάν ζητηθούν δυο διακοπές την ίδια στιγμή. Ποια από τις δυο διακοπές θα εξυπηρετηθεί πρώτα;

Προτεραιότητα διακοπών

Εάν δυο διακοπές ζητηθούν την ίδια στιγμή, η διακοπή με την μεγαλύτερη προτεραιότητα θα εξυπηρετηθεί πρώτη. Η προτεραιότητα κάθε διακοπής σχετίζεται με την διεύθυνση της διακοπής στο interrupt vector table. Η διακοπή που έχει την μικρότερη διεύθυνση έχει την μεγαλύτερη προτεραιότητα. Για παράδειγμα, η διεύθυνση της εξωτερικής διακοπής 0 έχει την υψηλότερη προτεραιότητα και εάν και οι δυο αυτές διακοπές ζητηθούν την ίδια στιγμή η εξωτερική διακοπή 0 εξυπηρετείται πρώτη.

Διακοπή μέσα σε διακοπή

Τι συμβαίνει όταν ο AVR εκτελεί μια ρουτίνα ISR εξυπηρέτησης διακοπής και μια άλλη διακοπή ζητηθεί; Όταν ο AVR ξεκινά να εκτελέσει μια ρουτίνα ISR απενεργοποιεί το bit I του καταχωρητή κατάστασης SREG που προκαλεί την απενεργοποίηση όλων των διακοπών και καμία άλλη διακοπή δεν θα εξυπηρετηθεί. Όταν η εντολή RETI εκτελείται ο AVR ενεργοποιεί το bit I προκαλώντας τις άλλες διακοπές να εξυπηρετηθούν. Εάν θέλεις μια άλλη διακοπή (με οποιαδήποτε προτεραιότητα) να εξυπηρετηθεί ενώ εκείνη τη στιγμή μια άλλη διακοπή εξυπηρετείται, θα πρέπει να θέσεις το bit Ι σε 1 με την εντολή SEI. Αλλά χρειάζεται προσοχή. Για παράδειγμα σε μια low-level-triggered εξωτερική διακοπή, ενεργοποιώντας το bit I, ενώ το πιν ΙΝΤ παραμένει ενεργό (κατάσταση LOW) θα προκαλέσει την ISR να εκτελείται ξανά και ξανά μέσα στην άλλη, προκαλώντας την κατάρρευση του σωρού.