Οι μικροελεγκτές AVR με τις εντολές ROL και ROR εκτελούν περιστροφή ή μετατόπιση κατά ένα bit διαμέσου της σημαίας κρατουμένου. Παρακάτω θα εξετάσουμε αυτές τις εντολές διότι χρησιμοποιούνται ευρέως στον προγραμματισμό.
Περιστροφή διαμέσου του κρατουμένου:
Υπάρχουν δυο εντολές περιστροφής στους AVR που εμπλέκουν τη σημαία κρατουμένου, αυτές είναι οι ROR και ROL.
Η εντολή περιστροφής ROR
ROR Rd ; rotate Rd right through carry
Με την εντολή ROR τα bits ενός καταχωρητή περιστρέφονται από αριστερά προς δεξιά, η σημαία κρατουμένου εισέρχεται στο MSB και το LSB εξέρχεται στη σημαία κρατουμένου. Με άλλα λόγια στη ROR η C μετακινείται στο MSB και το LSB μετακινείται στο C. Στην πραγματικότητα η σημαία C δρα σαν να είναι μέρος του καταχωρητή κάνοντας σε μέγεθος 9-bit τον καταχωρητή. Μελετήστε τον ακόλουθο κώδικα:
CLC ; make C=0 (carry is 0)
LDI R20, 0x26 ; R20 = 0010 0110
ROR R20 ; R20 = 0001 0011 C=0
ROR R20 ; R20 = 0000 1001 C=1
ROR R20 ; R20 = 1000 0100 C=1
Η εντολή περιστροφής ROL
ROL Rd ; rotate Rd left through carry
Η άλλη εντολή περιστροφής είναι η ROL. Στην ROL τα bits μετατοπίζονται από δεξιά προς αριστερά και η σημαία C εισέρχεται στο LSB και το MSB εισέρχεται στη σημαία κρατουμένου C. Με άλλα λόγια στην ROL η σημαία C μετακινείται στο LSB και το MSB μετακινείται στο C. Δες το ακόλουθο απόσπασμα κώδικα. Ας το πούμε ξανά, η σημαία κρατουμένου δρα σαν να ήταν μέρος του καταχωρητή κάνοντας τον σαν 9-bit καταχωρητή.
SEC ; make C = 1
LDI R20, 0x15 ; R20 = 0001 0101
ROL R20 ; R20 = 0010 1011 C = 0
ROL R20 ; R20 = 0101 0110 C = 0
ROL R20 ; R20 = 1010 1100 C = 0
ROL R20 ; R20 = 0101 1000 C = 1
Παράδειγμα
Γράψε ένα πρόγραμμα που να βρίσκει τον αριθμό των 1ς σε ένα δοσμένο byte
LDI R20, 0x97
LDI R30, 0 ; Ο αριθμός των 1ς
LDI R16, 8 ; Ο αριθμός των bits σε ένα byte
AGAIN:
ROR R20 ;Δεξιά περιστροφή του R20 και η μεταφορά του LSB στη σημαία C
BRCC NEXT ; Εάν C = 0 πήγαινε στην ετικέτα NEXT
INC R30 ; Αύξηση του R30
NEXT:
DEC R16 ; Μείωση του R16
BRNE AGAIN ; Εάν ο R16 δεν είναι μηδέν πήγαινε στην ετικέτα AGAIN
ROR R20 ; Άλλη μια φορά για να μείνει ο R20 ανεπηρέαστος
HERE: JMP HERE ; Σταμάτησε εδώ
Σειριακή μετάδοση δεδομένων
Κάποιες φορές απαιτείται η σειριακή μετάδοση δεδομένων, δηλαδή η μετάδοση ενός bit κάθε φορά από ένα πιν του μικροελεγκτή. Αυτό μπορούμε να επιτύχουμε με δυο τρόπους:
1] Χρησιμοποιώντας τη σειριακή θύρα. Με τη αυτοματοποιημένη χρήση της, ο προγραμματιστής έχει λιγότερο έλεγχο στη σειριακή μετάδοση δεδομένων. Ο τρόπος λειτουργίας της σειριακής θύρας περιγράφεται σε επόμενο κεφάλαιο.
2] Σειριακή μετάδοση δεδομένων με τη βοήθεια κώδικα που γράφουμε εμείς για να έχουμε τον έλεγχο της σειριακής μετάδοσης δεδομένων κατά την διάρκεια των εκπεμπόμενων παλμών και διαστημάτων.
Εντολές μετατόπισης δεδομένων:
Υπάρχουν τρεις εντολές για μετατόπιση δεδομένων μέσα σε καταχωρητες GPRs του AVR. Αυτές είναι οι LSL, LSR και ASR
Η εντολή μετατόπισης LSL
LSL Rd ; logical shift left
Στην LSL καθώς τα bits του καταχωρητή μετατοπίζονται από δεξιά προς αριστερά και το 0 εισέρχεται στο LSB καθώς και το MSB εξέρχεται και πηγαίνει στη σημαία κρατουμένου. Με άλλα λόγια στην εντολή LSL το 0 μετακινείται στο LSB και το MSB μετακινείται στη σημαία C.
Σημειώστε ότι αυτή η εντολή πολλαπλασιάζει τα περιεχόμενα του καταχωρητή με το 2 υποθέτοντας ότι η σημαία κρατουμένου C μετά την εντολή LSL δεν τίθεται σε 1. Μελετήστε τον ακόλουθο κώδικα:
CLC ; make C = 0 (carry is 0)
LDI R20, 0x26 ; R20 = 0010 0110 (38) C = 0
LSL R20 ; R20 = 0100 1100 (76) C = 0
LSL R20 ; R20 = 1001 1000 (152) C = 0
LSL R20 ; R20 = 0011 0000 (48) C = 1
; as C = 1 and content of R20 is not multiplied by 2
Η εντολή μετατόπισης LSR
LSR Rd ; logical shift right
Η δεύτερη εντολή μετατόπισης είναι η LSR. Με την LSR τα bits ενός καταχωρητή μετατοπίζονται από αριστερά προς δεξιά. Το ψηφίο 0 εισάγεται στο MSB και το LSB εξέρχεται προς την σημαία κρατουμένου. Με άλλα λόγια με την εντολή LSR το ψηφίο 0 εισέρχεται στο MSB και το LSB μετακινείται στην σημαία κρατουμένου C. Σημειώστε ότι με αυτή την εντολή τα περιεχόμενα του καταχωρητή διαιρούνται δια δυο και η σημαία κρατουμένου περιέχει το υπόλοιπο της διαίρεσης. Εξετάστε τον ακόλουθο κώδικα:
LDI R20, 0x26 ; R20 = 0010 0110 (38)
LSR R20 ; R20 = 0001 0011 (19) C = 0
LSR R20 ; R20 = 0000 1001 (9) C = 1
LSR R20 ; R20 = 0000 0100 (4) C = 1
Η εντολή LSR δεν μπορεί να χρησιμοποιηθεί για διαίρεση προσημασμένων αριθμών δια του δυο.
Η εντολή ASR
ASR Rd ; arithmetic shift right
Η τρίτη εντολή μετατόπισης είναι η ASR, η οποία σημαίνει αριθμητική μετατόπιση προς δεξιά. Με αυτή την μετατόπιση, δηλαδή με την ASR μπορούμε να κάνουμε διαίρεση δια του δύο στους προσημασμένους αριθμούς. Στην εντολή ASR καθώς τα bits του καταχωρητή μετατοπίζονται από αριστερά προς δεξιά, το MSB κρατείται το ίδιο και το LSB εξέρχεται προς το κρατούμενο C. Με άλλα λόγια το MSB δεν αλλάζει αλλά αντιγράφεται στο D6, το D6 μετακινείται στο D5, το D5 μετακινείται στο D4 κ.τ.λ. Μελετήστε τον ακόλουθο κώδικα:
LDI R20, 0xD0 ; R20 = 1101 0000 (-48) C = 0
ASR R20 ; R20 = 1110 1000 (-24) C = 0
ASR R20 ; R20 = 1111 0100 (-12) C = 0
ASR R20 ; R20 = 1111 1010 (-6) C = 0
ASR R20 ; R20 = 1111 1101 (-3) C = 0
ASR R20 ; R20 = 1111 1110 (-1) C = 1
Παράδειγμα
Υπέθεσε ότι ο καταχωρητής R20 έχει τον αριθμό -6. Δείξε ότι ο LSR δεν μπορεί να χρησιμοποιηθεί για να διαιρέσει τον R20 δια δυο. Γιατί;
LDI R20, 0xFA ; R20 = 1111 1010 (-6)
LSR R20 ; R20 = 0111 1101 (+125)
; -6 divided by 2 is not +125 and
; the answer is not correct
Επειδή η εντολή LSR μετατωπίζει το bit προσήμου , αλλάζει το πρόσημο του αριθμού και επομένως δεν μπορεί να χρησιμοποιηθεί για προσημασμένους αριθμούς.
Παράδειγμα
Υπέθεσε ότι ο καταχωρητής R20 έχει τον αριθμό 48. Δείξε πως μπορούμε να χρησιμοποιήσουμε την ROR για να διαιρέσουμε τον R20 με το 8.
; to divide a number by 8 we can
; shift it 3 bits to the right.
; without LSR we have to ROR 3 times and
; clear carry flag before each rotation
LDI R20, 0x30 ; R20 = 0011 0000 (48)
CLC ;clear carry flag
ROR R20 ; R20 = 0001 1000 (24)
CLC ;clear carry flag
ROR R20 ; R20 = 0000 1100 (12)
CLC ;clear carry flag
ROR R20 ; R20 = 0000 0110 (6)
;48 divided by 8 is 6 and
; the answer is correct
Η εντολή εναλλαγής SWAP
SWAP Rd ; swap nibbles
Μια άλλη χρήσιμη εντολή είναι η SWAP, η οποία δουλεύει για τους καταχωρητές γενικού σκοπού από R0 έως R31. Η εντολή αυτή εναλλάσσει το χαμηλότερο nibble ενός καταχωρητή GPR με το υψηλότερο nibble. Με άλλα λόγια, τα χαμηλότερα 4 bits τοποθετούνται στα υψηλότερα 4 bits και τα υψηλότερα 4 bits τοποθετούνται στα χαμηλότερα 4 bits. Δείτε το ακόλουθο παράδειγμα:
Παράδειγμα
1] Βρείτε τα περιεχόμενα του καταχωρητή R20 στο ακόλουθο απόσπασμα κώδικα:
LDI R20, 0x72
SWAP R20
2] Αν δεν υπήρχε η εντολή SWAP πως θα μπορούσατε να εναλλάξετε τα nibbles; Γράψετε ένα μικρό πρόγραμμα που θα μπορούσατε να κάνετε αυτό.
Απάντηση
1] LDI R20, 0x72 ; R20 = 0x72 = 0b01110010
SWAP R20 ; R20 = 0x27 = 0b00100111
2] LDI R20, 0x72
LDI R16, 4
LDI R21, 0
BEGIN:
CLC
ROL R20
ROL R21
DEC R16
BRNE BEGIN
OR R20, R21
HERE: JMP HERE