Εργαστήριο Δομής και Λειτουργίας Μικροϋπολογιστών Βοήθημα εκτέλεσης εργαστηριακής άσκησης 4: Ρουτίνες καθυστέρησης Άσκηση 1 (σύνοψη της εκφώνησης) [Συγγραφή ρουτίνας καθυστέρησης] Γράψτε ένα πρόγραμμα στον εξομοιωτή του Εργαστηρίου ώστε να «αναβοσβήνει» όλα μαζί τα bits της πόρτας P1 με συχνότητα περίπου 1Hz. Ένα bit θεωρείται «αναμμένο» όταν έχει τιμή 1 και «σβηστό» όταν έχει τιμή 0. (Σε επίπεδο hardware θα μπορούσαμε να οδηγήσουμε τις εξόδους της πόρτας P1 σε ισάριθμα LED, ώστε να παρατηρήσουμε τις εναλλαγές μεταξύ ανάμματος και σβησίματος). Για την πραγματοποίηση του ζητούμενου προγράμματος, θα χρειαστούμε ένα κυρίως πρόγραμμα και μία υπορουτίνα. Η υπορουτίνα θα καθυστερεί τον 8051, δηλαδή θα τον αναγκάζει να μην κάνει τίποτα, για ένα μικρό χρονικό διάστημα. Με τον τρόπο αυτόν οι εναλλαγές ανάμεσα σε σβήσιμο και άναμμα θα μπορούν να γίνονται αρκούντως αργά ώστε να είναι παρατηρήσιμες. Κυρίως πρόγραμμα (να γραφεί ξεκινώντας από τη διεύθυνση 0100h) ΜΑΙΝ1: Επιλέξτε ως ενεργό την ομάδα καταχωρητών 0, κάνοντας RS1=0, RS0=0 με όποιον τρόπο σας είναι ευκολότερος (για παράδειγμα ANL PSW, #11100111B το οποίο θα εμφανιστεί στον εξομοιωτή ως ANL PSW, #E7H). Κάντε τον stack pointer να δείχνει τη θέση μνήμης 60h. LOOP1: (Αυτό το loop θα εκτελείται συνεχώς!). Φορτώστε την πόρτα P1 μόνο με άσσους Καλέστε την υπορουτίνα καθυστέρησης, η οποία αρχίζει με την εντολή που έχει ετικέτα KATHY (η υπορουτίνα θα πρέπει να παράγει καθυστέρηση περίπου μισού δευτερολέπτου). Φορτώστε την πόρτα P1 μόνο με μηδενικά. Καλέστε τη ρουτίνα καθυστέρησης ΚΑΤΗΥ. Κάντε jump στην εντολή που έχει ετικέτα LOOP1. Υπορουτίνα (να γραφεί ξεκινώντας από τη διεύθυνση 0000h) [Συγγραφή ρουτίνας καθυστέρησης με χρήση διπλού βρόχου] KATHY: Φυλάξτε στη στοίβα την τιμή του PSW. Αυτή είναι πάντοτε μια καλή προγραμματιστική τεχνική. Φυλάξτε στη στοίβα την τιμή του καταχωρητή R2, της ομάδας καταχωρητών 0, δηλαδή την τιμή του καταχωρητή που βρίσκεται στη διεύθυνση 02h. Η υπορουτίνα χρησιμοποιεί αυτόν τον καταχωρητή, οπότε καλού-κακού προστατεύουμε την τιμή του. Για τον ίδιο λόγο φυλάξτε στη στοίβα την τιμή του καταχωρητή R3, της ομάδας καταχωρητών 0, δηλαδή την τιμή του καταχωρητή που βρίσκεται στη διεύθυνση 03h. Η υπορουτίνα μας θα περιέχει δύο βρόχους, εμφωλευμένους τον έναν μέσα στον άλλον. Ως μετρητή του εξωτερικού βρόχου, διαλέγουμε τον R2 της ομάδας καταχωρητών 0. Αρχικοποιούμε τον R2 με μια τιμή της αρεσκείας μας, π.χ. την 32h. 1
Εισαγωγή εντολής NOP Εισαγωγή εντολής NOP Εισαγωγή εντολής NOP (Σχόλιο: Οι τρεις εντολές NOP που εισήχθησαν παραπάνω έχουν να κάνουν με την τελευταία άσκηση του σημερινού μαθήματος. Επί της ουσίας «αφήνουν χώρο» στη ROM για εντολές που θα προσθέσουμε αργότερα!) LEX: Αρχή του εξωτερικού βρόχου! Η πρώτη εντολή του εξωτερικού βρόχου είναι εκείνη που αρχικοποιεί τον μετρητή του εσωτερικού βρόχου. Ως μετρητή του εσωτερικού βρόχου, διαλέγουμε τον R3 της ομάδας καταχωρητών 0. Αρχικοποιούμε τον R3 με μια τιμή της αρεσκείας μας, π.χ. την 30h. LES: Αρχή του εσωτερικού βρόχου! Τεμπέλιασε, μην κάνεις τίποτα! Είσαι κουρασμένος, μην κάνεις τίποτα! Ξεκουράσου λίγο ακόμη, μην κάνεις τίποτα! Ελάττωσε τον μετρητή του εσωτερικού βρόχου κατά 1 και, αν αυτός δεν είναι μηδέν, κάνε μία ακόμη επανάληψη του εσωτερικού βρόχου, διαφορετικά συνέχισε στην επόμενη (αμέσως παρακάτω) εντολή. Ελάττωσε τον μετρητή του εξωτερικού βρόχου κατά 1 και, αν αυτός δεν είναι μηδέν, κάνε μία ακόμη επανάληψη του εξωτερικού βρόχου, διαφορετικά συνέχισε στην επόμενη (αμέσως παρακάτω) εντολή. Όταν τελειώσει η εκτέλεση και των δύο βρόχων, άρχισε να αποκαθιστάς τις τιμές που είχες φυλάξει στη στοίβα. Πρώτα αποκατάστησε τον καταχωρητή R3, της ομάδας καταχωρητών 0 (δηλ. POP 03h) Αποκατάστησε τον καταχωρητή R2, της ομάδας καταχωρητών 0 (δηλ. POP 02h) Αποκατάστησε τον καταχωρητή PSW. Επέστρεψε από την υπορουτίνα καθυστέρησης στο κυρίως πρόγραμμα. Εκτελέστε το κυρίως πρόγραμμα με χρήση του πλήκτρου F1 και παρατηρήστε το αναβοσβήσιμο της πόρτας P1. Αν αυτό δεν γίνεται με ρυθμό περίπου 1 Hz, πειραματιστείτε με διαφορετικές τιμές στις αρχικοποιήσεις του εξωτερικού και του εσωτερικού βρόχου καθυστέρησης. Άσκηση 2 (σύνοψη της εκφώνησης) Γράψτε πρόγραμμα στον εξομοιωτή του 8051, ώστε αυτό να κινεί κυκλικά έναν άσσο στην πόρτα P1 με ταχύτητα περίπου μία θέση ανά δευτερόλεπτο. Το πρόγραμμά σας γράψτε το ξεκινώντας από τη διεύθυνση 0200h της ROM. Για την υλοποίηση της ζητούμενης διαδικασίας, θα γράψουμε μόνο το κυρίως πρόγραμμα. Η υπορουτίνα KATHY θα χρησιμοποιηθεί αμετάβλητη από την προηγούμενη Άσκηση. Κυρίως πρόγραμμα (να γραφεί ξεκινώντας από τη διεύθυνση 0200h) MAIN2: Επιλέξτε την ομάδα καταχωρητών 0 με όποιον τρόπο σας είναι ευκολότερος (για παράδειγμα CLR RS1, CLR RS0) Αρχικοποιήστε τον stack pointer ώστε αυτός να δείχνει στη θέση μνήμης με διεύθυνση 60h. 2
Αρχικοποιήστε την πόρτα P1, ώστε το MSB της να είναι άσσος και όλα τα υπόλοιπα bit της να είναι μηδενικά (δηλ. στην πόρτα P1 θα πρέπει να φορτωθεί η τιμή 10000000B, ισοδύναμα η τιμή 80h) Αρχικοποιήστε τον συσσωρευτή Α με την ίδια τιμή. LOOP2: (Αυτό το loop θα εκτελείται συνεχώς!). Ολισθήστε κυκλικά τον συσσωρευτή μία θέση δεξιά. (Θυμηθείτε ότι οι εντολές ολίσθησης μπορούν να εφαρμοστούν μόνο στον συσσωρευτή). Τοποθετήστε την τρέχουσα τιμή του συσσωρευτή στην πόρτα P1. Καλέστε τη ρουτίνα καθυστέρησης. Καλέστε τη ρουτίνα καθυστέρησης (ξανά!), ώστε να επιτευχθεί καθυστέρηση 1 sec συνολικά και από τις δύο κλήσεις. Μεταβείτε στην αρχή του βρόχου LOOP2 για μία ακόμη επανάληψη. Εκτελέστε το κυρίως πρόγραμμα με χρήση του πλήκτρου F1 και παρατηρήστε τον άσσο καθώς αυτός ολισθαίνει κυκλικά προς τα δεξιά στην πόρτα P1. Άσκηση 3 (σύνοψη της εκφώνησης) Γράψτε ένα πρόγραμμα, παρόμοιο με εκείνο της Άσκησης 2, στο οποίο ένας άσσος θα κινείται κυκλικά στην πόρτα P1. Η φορά της κίνησης του άσσου θα εξαρτάται από το MSB της πόρτας P2. Αν αυτό είναι 1, τότε ο άσσος θα ολισθαίνει στην πόρτα P1 προς τα δεξιά. Αν αυτό είναι 0, τότε ο άσσος θα ολισθαίνει στην πόρτα P1 προς τα αριστερά. Για την υλοποίηση της ζητούμενης διαδικασίας, θα γράψουμε μόνο κυρίως πρόγραμμα. Η υπορουτίνα KATHY θα χρησιμοποιηθεί αμετάβλητη από την προηγούμενη Άσκηση. Κυρίως πρόγραμμα (να γραφεί ξεκινώντας από τη διεύθυνση 0300h) MAIN3: Επιλέξτε την ομάδα καταχωρητών 0 με όποιον τρόπο σας είναι ευκολότερος (για παράδειγμα MOV PSW, #00000000B). Αρχικοποιήστε τον stack pointer ώστε να δείχνει στη θέση μνήμης με διεύθυνση 60h Αρχικοποιήστε την πόρτα P2 τοποθετώντας σε αυτήν μόνο άσσους. Αρχικοποιήστε την πόρτα P1 τοποθετώντας σε αυτήν έναν άσσο στο MSB της και μηδέν παντού αλλού. Αρχικοποιήστε τον συσσωρευτή όπως και την P1. LOOP3: (Αυτό το loop θα εκτελείται συνεχώς!). Αν το MSB της πόρτας P2 είναι άσσος, τότε κάνε jump στην εντολή με ετικέτα DEXIA, όπου και θα πραγματοποιηθεί κυκλική δεξιά ολίσθηση του περιεχομένου του συσσωρευτή. Η εντολή που το κάνει είναι η JB P2.7, DEXIA, η οποία ανήκει στην ομάδα εντολών χειρισμού μεμονωμένων bit του 8051). Διαφορετικά, αν δηλαδή το MSB της P2 είναι μηδέν, κάνε κυκλική αριστερή ολίσθηση του περιεχομένου του συσσωρευτή. Έχουμε τελειώσει με την κυκλική αριστερή ολίσθηση, κάνε jump στην εντολή με ετικέτα ΝΕΧΤ για να ενημερωθεί η πόρτα P1 κατάλληλα. DEXIA: Κάνε κυκλική δεξιά ολίσθηση στο περιεχόμενο του συσσωρευτή. Στην επόμενη εντολή θα ενημερωθεί η πόρτα P1. NEXT: Ενημέρωσε την πόρτα P1, βάζοντας σε αυτήν την τρέχουσα τιμή του συσσωρευτή. 3
Κάλεσε την υπορουτίνα καθυστέρησης. Κάλεσε την υπορουτίνα καθυστέρησης (ξανά!), ώστε να επιτευχθεί καθυστέρηση 1 sec συνολικά και από τις δύο κλήσεις. Επίστρεψε τον έλεγχο του προγράμματος στην αρχή του βρόχου LOOP3. Αφού εξασφαλίσετε ότι ο Program Counter (PC) έχει λάβει τη διεύθυνση της αρχικής εντολής του προγράμματος, δηλαδή την τιμή 0300h, τοποθετήστε τον κέρσορα στο MSB της πόρτας P2. Πατήστε το πλήκτρο F1, ώστε να αρχίσει να εκτελείται το κυρίως πρόγραμμα. Ο άσσος ολισθαίνει στην πόρτα Ρ1 κυκλικά προς τα δεξιά. Καθώς το πρόγραμμα τρέχει, αλλάξτε την τιμή του MSB της πόρτας P2 σε μηδέν. Ο άσσος θα αρχίσει τώρα να ολισθαίνει στην πόρτα Ρ1 κυκλικά προς τα αριστερά. Συνεχίστε τους πειραματισμούς μεταβάλλοντας την τιμή του MSB της πόρτας P2 και παρατηρώντας τη φορά της κίνησης του άσσου στην πόρτα P1. Άσκηση 4 (σύνοψη της εκφώνησης) Τροποποιήστε το πρόγραμμα της Άσκησης 3, ώστε τα υπόλοιπα τα υπόλοιπα 7 bits της πόρτας Ρ2 να καθορίζουν την ταχύτητα της κίνησης του άσσου. Για αυτό το σκοπό, αν αυτά τα 7 bits συνιστούν έναν αριθμό, έστω x, η καθυστέρηση που προκαλεί η ρουτίνα καθυστέρησης να είναι ανάλογη του αριθμού x. Μεγάλο x μεγάλη καθυστέρηση μικρή ταχύτητα κίνησης. Μικρό x μικρή καθυστέρηση μεγάλη ταχύτητα κίνησης. Για την υλοποίηση της ζητούμενης διαδικασίας, θα γράψουμε μόνο κατάλληλη υπορουτίνα καθυστέρησης, επί της ουσίας θα κάνουμε μία παραλλαγή της ΚΑΤΗΥ. Το κυρίως πρόγραμμα θα παραμείνει αμετάβλητο, όπως στην Άσκηση 3. Τα bullets που εμφανίζονται με italics, αντιστοιχούν σε εντολές ίδιες με εκείνες που χρησιμοποιήσαμε κατά τη συγγραφή της αρχικής KATHY. Τροποποίηση της υπορουτίνας KATHY KATHY: Φυλάξτε στη στοίβα την τιμή του PSW. Αυτή είναι πάντοτε μια καλή προγραμματιστική τεχνική. Φυλάξτε στη στοίβα την τιμή του καταχωρητή R2, της ομάδας καταχωρητών 0, δηλαδή την τιμή του καταχωρητή που βρίσκεται στη διεύθυνση 02h. Η υπορουτίνα χρησιμοποιεί αυτόν τον καταχωρητή, οπότε καλού-κακού προστατεύουμε την τιμή του. Για τον ίδιο λόγο φυλάξτε στη στοίβα την τιμή του καταχωρητή R3, της ομάδας καταχωρητών 0, δηλαδή την τιμή του καταχωρητή που βρίσκεται στη διεύθυνση 03h. Η υπορουτίνα μας θα περιέχει δύο βρόχους, εμφωλευμένους τον έναν μέσα στον άλλον. Ως μετρητή του εξωτερικού βρόχου, διαλέγουμε τον R2 της ομάδας καταχωρητών 0. Αρχικοποιούμε τον R2 όχι με μια τιμή της αρεσκείας μας, όπως στην αρχική ΚΑΤΗΥ, αλλά με την τιμή της πόρτας P2. Αυτό συμβαίνει διότι η εκφώνηση ζητά τα 7 λιγότερο σημαντικά bits της πόρτας P2 να καθορίζουν την τιμή της καθυστέρησης, δηλαδή προγραμματιστικά την τιμή του R2. Η διαδικασία καθορισμού του R2 ολοκληρώνεται με την αμέσως επόμενη εντολή. 4
Με χρήση κατάλληλης εντολής λογικών πράξεων και μάσκας, μηδενίζουμε το MSB του R2, ενώ παράλληλα διατηρούμε αμετάβλητα τα υπόλοιπα 7 bits του. LEX: Αρχή του εξωτερικού βρόχου! Η πρώτη εντολή του εξωτερικού βρόχου είναι εκείνη που αρχικοποιεί τον μετρητή του εσωτερικού βρόχου. Ως μετρητή του εσωτερικού βρόχου, διαλέγουμε τον R3 της ομάδας καταχωρητών 0. Αρχικοποιούμε τον R3 με μια τιμή της αρεσκείας μας, π.χ. την 30h. LES: Αρχή του εσωτερικού βρόχου! Τεμπέλιασε, μην κάνεις τίποτα! Είσαι κουρασμένος, μην κάνεις τίποτα! Ξεκουράσου λίγο ακόμη, μην κάνεις τίποτα! Ελάττωσε τον μετρητή του εσωτερικού βρόχου κατά 1 και, αν αυτός δεν είναι μηδέν, κάνε μία ακόμη επανάληψη του εσωτερικού βρόχου, διαφορετικά συνέχισε στην επόμενη (αμέσως παρακάτω) εντολή. Ελάττωσε τον μετρητή του εξωτερικού βρόχου κατά 1 και, αν αυτός δεν είναι μηδέν, κάνε μία ακόμη επανάληψη του εξωτερικού βρόχου, διαφορετικά συνέχισε στην επόμενη (αμέσως παρακάτω) εντολή. Όταν τελειώσει η εκτέλεση και των δύο βρόχων, άρχισε να αποκαθιστάς τις τιμές που είχες φυλάξει στη στοίβα. Πρώτα αποκατάστησε τον καταχωρητή R3, της ομάδας καταχωρητών 0. Αποκατάστησε τον καταχωρητή R2, της ομάδας καταχωρητών 0. Αποκατάστησε τον καταχωρητή PSW. Επίστρεψε από την υπορουτίνα καθυστέρησης στο κυρίως πρόγραμμα. Τοποθετήστε στον Program Counter (PC) την τιμή 0300h, δηλαδή τη διεύθυνση της πρώτης εντολής του κυρίως προγράμματος της Άσκησης 3. Στη συνέχεια, τοποθετήστε τον κέρσορα στην πόρτα P2 και εκκινήστε το πρόγραμμα πατώντας F1. Επειδή η πόρτα P2 αρχικοποιείται προγραμματιστικά με άσσους κατά την εκτέλεση του κυρίως προγράμματος της Άσκησης 3, ο άσσος κινείται αργά στην πόρτα P1. Καθώς το πρόγραμμα εκτελείται, δοκιμάστε να μηδενίσετε χειροκίνητα κάποιους από τους 7 λιγότερο σημαντικούς άσσους της πόρτας P2. Θα παρατηρήσετε ότι η κίνηση του άσσου στην πόρτα P1 επιταχύνεται! Συνεχίστε κάνοντας και άλλες αλλαγές του δεδομένου της πόρτας Ρ2. 5