Data memory and I/O registers

AVR Data Memory

Σε ένα μικροελεγκτή AVR υπάρχουν δυο τύποι μνήμης: Η μνήμη κώδικα (code memory space) και η μνήμη δεδομένων (data memory space). Ο κώδικας που γράφουμε αποθηκεύεται στην μνήμη κώδικα ενώ τα δεδομένα στην μνήμη δεδομένων. Η μνήμη δεδομένων αποτελείται από τρία είδη μνήμης: GPRs (καταχωρητές γενικού σκοπού), τη μνήμη Ι/Ο και την εσωτερική μνήμη δεδομένων  RAM. Βλέπε το ακόλουθο σχήμα:

GPRs (καταχωρητές γενικού σκοπού)
Όπως αναφέραμε σε προηγούμενη ενότητα, οι GPRs χρησιμοποιούν τα πρώτα 32 bytes της μνήμης δεδομένων. Αυτοί οι καταχωρητές παίρνουν διευθύνσεις $00 έως $1F της μνήμης δεδομένων ανεξάρτητα από τον AVR μικροελεγκτή που έχουμε.

Μνήμη Ι/Ο  (SFRs)
Η μνήμη Ι/Ο δίνει βάση για ειδικές λειτουργίες, όπως τον καταχωρητή κατάστασης, τους χρονιστές, τη σειριακή επικοινωνία, τις Ι/Ο θύρες, τον ΑDC κ.ά. Η λειτουργικότητα κάθε μιας Ι/Ο θέσης μνήμης είναι προκαθορισμένη από τον σχεδιαστή της CPU και χρησιμοποιείται για τον έλεγχο του μικροελεγκτή και των περιφερειακών. Η ΑVR  I/O μνήμη αποτελείται από 8-bit καταχωρητές.

Όλοι οι μικροελεγκτές AVR έχουν το λιγότερο 64 bytes μέγεθος Ι/Ο θέσης μνήμης. Αυτό το 64-byte τμήμα ονομάζεται standard I/O μνήμη. Για AVRs με περισσότερα χαρακτηριστικά, υπάρχει επίσης η extended I/O μνήμη το οποίο περιέχει τους καταχωρητές για τον έλεγχο των έξτρα θυρών και περιφερειακών. Σε άλλους μικροελεγκτές οι καταχωρητές Ι/Ο ονομάζονται SFRs (special function registers) στους οποίους ο κάθε ένας είναι υπεύθυνος για μια λειτουργία σε αντίθεση με τους GPRs οι οποίοι δεν έχουν ειδική λειτουργία και προορίζονται για αποθήκευση προσωρινών δεδομένων.

Εσωτερική μνήμη δεδομένων SRAM
Η εσωτερική μνήμη δεδομένων χρησιμοποιείται για την αποθήκευση δεδομένων και παραμέτρων από τους AVR προγραμματιστές και  C compilers. Κάθε θέση της SRAM μπορεί να προσπελαθεί απευθείας με την διεύθυνση της. Κάθε θέση έχει πλάτος 8-bit και μπορεί να χρησιμοποιηθεί για την αποθήκευση δεδομένων που θέλουμε, εφόσον έχουν πλάτος 8-bits. Το μέγεθος της εσωτερικής μνήμης SRAM μεταβάλλεται από τσιπ σε τσιπ.

Η μνήμη EEPROM στους μικροελεγκτές AVR
Σήμερα οι περισσότεροι  μικροελεγκτές έχουν EEPROM μνήμη που χρησιμοποιείται για μόνιμη αποθήκευση δεδομένων. Όπως γνωρίζουμε η μνήμη EEPROM δεν χάνει δεδομένα με την διακοπή της τροφοδοσίας της, ενώ η μνήμη SRAM τα χάνει. Η μνήμη EEPROM χρησιμοποιείται για την αποθήκευση δεδομένων και παραμέτρων που δεν αλλάζουν συχνά και δεν θέλουμε να χαθούν σε μια διακοπή της τροφοδοσίας.

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

Οι εντολές που έχουμε ορίσει μέχρι στιγμής  βασίζονται σε σταθερές τιμές Κ και στους καταχωρητές GPRs και οι οποίες  χρησιμοποιούν τους GPRs σαν προορισμό. Είδαμε απλά παραδείγματα χρησιμοποιώντας τις εντολές LDI και ADD νωρίτερα.

Οι μικροελεγκτές AVR επιτρέπουν άμεση πρόσβαση σε όλες τις θέσεις στη μνήμη δεδομένων. Σε αυτή την ενότητα θα δούμε τις εντολές για πρόσβαση διάφορων είδη θέσεων της μνήμης δεδομένων.

Η εντολή LDS (Load direct from data Space)

Η εντολή LDS έχει την ακόλουθη σύνταξη:

LDS Rd, K  ;  φόρτωση του καταχωρητή  Rd με τα περιεχόμενα της θέσης Κ  (0 < d <31)
                       ;  K είναι μια διεύθυνση μεταξύ  $0000  έως   $FFFF

Η εντολή LDS προκαλεί τη CPU να φορτώσει ένα byte από μια διεύθυνση της μνήμης δεδομένων σε ένα καταχωρητή GPR. Μετά που αυτή η εντολή εκτελεστεί ο καταχωρητής GPR θα έχει την ίδια τιμή με εκείνη της διεύθυνσης Κ της μνήμης δεδομένων. Η θέση στη μνήμη δεδομένων μπορεί να είναι οποιαδήποτε μέρος της μνήμης δεδομένων. Μπορεί να είναι ένας Ι/Ο καταχωρητής, μια θέση στην εσωτερική μνήμη RAM ή ένας καταχωρητής γενικού σκοπού (GPR)

Παράδειγμα

Με την εντολή «LDI R20, 0x01» φορτώνονται τα περιεχόμενα της θέσης με διεύθυνση 0x01 στον καταχωρητή γενικού σκοπού R20. Όπως μπορείς να δεις η θέση 1 της μνήμης δεδομένων αντιστοιχεί στο κομμάτι των GPRs και είναι η διεύθυνση του καταχωρητή R1. Επομένως η εντολή αντιγράφει τον R1 στον R20.

Παράδειγμα

Στην επόμενη εντολή φορτώνονται στον καταχωρητή R8 τα περιεχόμενα της θέσης μνήμης δεδομένων με διεύθυνση 0x310

 LDS  R8,  0x310  ;   load R8 with the contents of location $310

Η εντολή  STS  (Store direct to data  Space)

Η εντολή STS έχει την ακόλουθη σύνταξη:   

STS  K,  Rr  ;  αποθήκευσε τα περιεχόμενα του καταχωρητή Rr  στη θέση Κ της μνήμης δεδομένων
                         ; Κ  είναι μια διεύθυνση μεταξύ  $0000 έως   $FFFF

Η εντολή  STS  προκαλεί  τη CPU να αποθηκεύσει τα περιεχόμενα του καταχωρητή GPR σε μια θέση της μνήμης δεδομένων. Μετά την εκτέλεση αυτής της εντολής η θέση στην μνήμη δεδομένων θα έχει την ίδια τιμή με εκείνη του καταχωρητή GPR. Η θέση μπορεί να είναι η διεύθυνση οποιοδήποτε μέρους της μνήμης δεδομένων, όπως ένας Ι/Ο καταχωρητής, μια θέση στην εσωτερική μνήμη RAM ή ένας καταχωρητής GPR.

Παράδειγμα

Με την εντολή  «STS  0x01,  R12»  αντιγράφονται τα δεδομένα του καταχωρητή R12 στη θέση 1 της μνήμης δεδομένων. Όπως μπορείς να δεις η θέση 1 της μνήμης δεδομένων αντιστοιχεί στο κομμάτι της GPRs και είναι η διεύθυνση του καταχωρητή R1. Αυτή η εντολή αντιγράφει τον καταχωρητή R12 στον R1.

Παράδειγμα

Στην επόμενη εντολή αποθηκεύονται τα περιεχόμενα του καταχωρητή R24 στη θέση 0x253 της μνήμης δεδομένων που ανήκει στην εσωτερική μνήμη RAM

STS  0x253, R24  ;   store  R24  to data space location  0x253

Η εντολή ΙΝ (IN  from  I/O θέση)

Η εντολή ΙΝ έχει την ακόλουθη σύνταξη:

ΙΝ  Rd,  A  ;  φόρτωσε μια Ι/Ο θέση μνήμης σε ένα καταχωρητή GPR  (0≤d≤31)  ,  (0≤A≤63)

Η εντολή ΙΝ προκαλεί τη CPU να φορτώσει ένα byte από ένα Ι/Ο καταχωρητή σε ένα GPR. Μετά που αυτή η εντολή εκτελεστεί ο καταχωρητής GPR θα έχει την ίδια τιμή όπως ο καταχωρητής Ι/Ο. Για παράδειγμα η εντολή  ΙΝ  R18,  0x15  θα αντιγράψει τα περιεχόμενα της θέσης με διεύθυνση 15 (σε hex) της Ι/Ο θέσης μνήμης στον καταχωρητή R18. Όπως μπορείς να δεις στο παρακάτω σχήμα, η Ι/Ο μνήμη έχει δυο διευθύνσεις την Ι/Ο διεύθυνση και την διεύθυνση της μνήμης δεδομένων.

Κάθε θέση στη μνήμη δεδομένων έχει μοναδική διεύθυνση που ονομάζεται data memory address. Κάθε Ι/Ο καταχωρητής έχει σχετική διεύθυνση με την αρχή της Ι/Ο μνήμης, που ονομάζεται Ι/Ο διεύθυνση.

Στην εντολή ΙΝ, ο Ι/Ο καταχωρητής αναφέρεται προς την Ι/Ο διεύθυνση. Για παράδειγμα η εντολή  ΙΝ R18,  0x06  αντιγράφει τα περιεχόμενα της θέσης $06 της Ι/Ο μνήμης (της οποίας η διεύθυνση της μνήμης δεδομένων είναι 0x26) στον καταχωρητή  R18. Όπως φαίνεται στον πίνακα η Ι/Ο διεύθυνση  0x06 ανήκει στον Ι/Ο καταχωρητή PINC και έτσι η εντολή αυτή αντιγράφει τα περιεχόμενα του PINC της θύρας C στον καταχωρητή R18.

Παράδειγμα

Στην επόμενη εντολή ο καταχωρητής R17 φορτώνεται με τα περιεχόμενα της θέσης 0x03 της Ι/Ο μνήμης.

ΙΝ  R17,  0x03 ;  load R17 with location $3 (R17 = PINB)

Για να δουλέψουμε με τους Ι/Ο καταχωρητές πιο εύκολα χρησιμοποιούμε τα ονόματα τους αντί για τις Ι/Ο διευθύνσεις τους. Για παράδειγμα, η επόμενη εντολή φορτώνει τον καταχωρητή R22 με τα περιεχόμενα PIND

IN R22, PIND  ;  load R22  with  PIND

Όπως αναφέραμε νωρίτερα μπορούμε να χρησιμοποιήσουμε την LDS εντολή για να αντιγράψουμε τα περιεχόμενα μιας θέσης της μνήμης δεδομένων σε ένα καταχωρητή GPR. Αυτό σημαίνει ότι μπορούμε να φορτώσουμε ένα Ι/Ο καταχωρητή σε ένα καταχωρητή γενικού σκοπού GPR χρησιμοποιώντας μια εντολή LDS. Η χρήση της εντολής ΙΝ για το διάβασμα ενός Ι/Ο καταχωρητή προσφέρει πλεονεκτήματα έναντι της εντολής LDS, τα εξής:
1] H CPU εκτελεί την εντολή ΙΝ γρηγορότερα από την LDS. Αυτό οφείλεται στο ότι η εντολή ΙΝ εκτελείται σε ένα κύκλο μηχανής σε αντίθεση με την LDS που εκτελείται σε δυο.
2] Η εντολή ΙΝ είναι μια 2-byte εντολή ενώ η LDS είναι 4-byte εντολή. Δηλαδή η εντολή ΙΝ καταλαμβάνει λιγότερη μνήμη προγράμματος.
3] Όταν χρησιμοποιούμε την εντολή ΙΝ μπορούμε να χρησιμοποιούμε τα ονόματα των Ι/Ο καταχωρητών ενώ στην εντολή LDS όχι.

Η εντολή OUT  ( OUT  to  I/O location)

Η εντολή OUT έχει την ακόλουθη σύνταξη:

OUT  A,  Rr  ;  αποθήκευσε τον καταχωρητή Rr  στη  Ι/Ο θεση Α  (0≤r≤31)  ,  (0≤A≤63)

Η εντολή OUT προκαλεί τη CPU να αποθηκεύσει τον καταχωρητή  GPR  στον  Ι/Ο καταχωρητή. Μετά που η εντολή εκτελεστεί, ο Ο/Ι καταχωρητής θα έχει την ίδια τιμή όπως ο GPR. Για παράδειγμα η εντολή  OUT  PORTB,  R12  αντιγράφει τα περιεχόμενα του R12  στο  PORTB  (θέση  0x05 της Ι/Ο μνήμης).

Παράδειγμα

Το επόμενο κομμάτι κώδικα αντιγράφει την τιμή  0xB6  στον καταχωρητή  SPL

       LDI   R17,  0xB6  ;  load R17  with  0xB6
       OUT  SPL,  R17   ;  out  R17  to  SPL

Σημείωση: θα πρέπει να θυμόμαστε ότι δεν υπάρχει εντολή που να αντιγράφει αριθμητικές τιμές κατευθείαν σε ένα Ι/Ο καταχωρητή ούτε σε μια SRAM θέση.

Παράδειγμα

Το επόμενο κομμάτι κώδικα αντιγράφει τον καταχωρητή PINC στη θύρα PORTD

     IN  R21,  PINC ;  load R21 with the contents of I/O reg  PINC
     OUT  PORTD,  R21  ;  out  R21  to  PORTD