38
ΑΕΙ ΠΕΙΡΑΙΑ ΤΕΧΝΟΛΟΓΙΚΟΥ ΤΟΜΕΑ Τμήμα Μηχανικών Αυτοματισμού Τεχνολογικής Εκπαίδευσης 15/4/2017 1η Σειρά Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών Μετράει 2 μονάδες προσθετικά Παράδοση μέχρι την Πέμπτη 11/5/2017 στη θυρίδα μου στη Γραμματεία του Τμήματος ή κάτω από την πόρτα του γραφείου ΖΑ203 ή του Εργαστηρίου ΖΑ216 ή κατά τη διάρκεια των παραδόσεων θεωρίας. Γράψτε όσο περισσότερα μπορείτε, ακόμα και να δεν ολοκληρώνετε μια άσκηση. Ό,τι παραδώσετε να αντιπροσωπεύει προσωπική σας εργασία και μόνο. Οι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι. Για όλες υπάρχει ύλη με σχετικά παραδείγματα στο βιβλίο της θεωρίας. Φυσικά, τα θέματα της εξέτασης προόδου της 8/5/17 θα είναι πολύ πιο εύκολα από τις παρούσες ασκήσεις. Καλό είναι να κατεβάσετε από το site του μαθήματος (Σημειώσεις Εργαστηρίου Δομής και Λειτουργίας Μικροϋπολογιστών) τον εξομοιωτή του 8051 και να δοκιμάσετε να τρέξετε τα προγράμματα που θα γράψετε. Άσκηση 1 Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051, ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000, 00000001, 00000011, …, 01111111, 11111111, 11111110, 11111100, …10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec. Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται, μεταξύ των άλλων, και περιστροφές του περιεχομένου του συσσωρευτή Α. Με άλλα λόγια, το πρόγραμμά σας να μην είναι «μακαρόνι», ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις 1

auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

ΑΕΙ ΠΕΙΡΑΙΑ ΤΕΧΝΟΛΟΓΙΚΟΥ ΤΟΜΕΑΤμήμα Μηχανικών Αυτοματισμού Τεχνολογικής Εκπαίδευσης

1542017

1η Σειρά Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Μετράει 2 μονάδες προσθετικά

Παράδοση μέχρι την Πέμπτη 1152017στη θυρίδα μου στη Γραμματεία του Τμήματος ή κάτω από την πόρτα του γραφείου

ΖΑ203 ή του Εργαστηρίου ΖΑ216 ή κατά τη διάρκεια των παραδόσεων θεωρίαςΓράψτε όσο περισσότερα μπορείτε ακόμα και να δεν ολοκληρώνετε μια άσκηση

Ότι παραδώσετε να αντιπροσωπεύει προσωπική σας εργασία και μόνο Οι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι Για όλες υπάρχει ύλη με σχετικά

παραδείγματα στο βιβλίο της θεωρίας Φυσικά τα θέματα της εξέτασης προόδου της 8517 θα είναι πολύ πιο εύκολα από τις παρούσες ασκήσεις

Καλό είναι να κατεβάσετε από το site του μαθήματος (Σημειώσεις Εργαστηρίου Δομής και Λειτουργίας Μικροϋπολογιστών) τον εξομοιωτή του 8051 και να

δοκιμάσετε να τρέξετε τα προγράμματα που θα γράψετε

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να

1

εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα αρίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών που είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

2

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή όταν συμβεί υπερχείλιση του Τ1 πιθανόν να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits της πόρτας Ρ1 σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI)

3

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα γ1

γ3 Στο προηγούμενο ερώτημα γ2 την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα γ1

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα γ1 προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα γ1

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με

4

t (sec)

άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Και όμως έτσι εκτελείται δουλειά laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως

5

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 2: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα αρίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών που είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

2

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή όταν συμβεί υπερχείλιση του Τ1 πιθανόν να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits της πόρτας Ρ1 σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI)

3

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα γ1

γ3 Στο προηγούμενο ερώτημα γ2 την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα γ1

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα γ1 προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα γ1

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με

4

t (sec)

άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Και όμως έτσι εκτελείται δουλειά laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως

5

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 3: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή όταν συμβεί υπερχείλιση του Τ1 πιθανόν να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits της πόρτας Ρ1 σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI)

3

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα γ1

γ3 Στο προηγούμενο ερώτημα γ2 την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα γ1

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα γ1 προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα γ1

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με

4

t (sec)

άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Και όμως έτσι εκτελείται δουλειά laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως

5

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 4: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα γ1

γ3 Στο προηγούμενο ερώτημα γ2 την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα γ1

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα γ1 προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα γ1

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με

4

t (sec)

άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Και όμως έτσι εκτελείται δουλειά laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως

5

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 5: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Και όμως έτσι εκτελείται δουλειά laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως

5

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 6: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Καλή Ανάσταση

6

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 7: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

Λύσεις της 1ης Σειράς Ασκήσεων στη Δομή και Λειτουργία Μικροϋπολογιστών

Άσκηση 1

Να γράψετε κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000000 00000001 00000011 hellip 01111111 11111111 11111110 11111100 hellip10000000 και πάλι από την αρχή με ταχύτητα μια ένδειξη ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει μία-μία τις παραπάνω 16 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με σήμα Reset του 8051 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ1 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από δεξιά προς τα αριστερά και στη συνέχεια μια πλήρη διαδρομή από αριστερά προς τα δεξιά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει 1 sec Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT0

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 την ένδειξη 10000000 και μετά την ένδειξη 00000001 Κάθε ένδειξη να την εμφανίζεται στην πόρτα Ρ2 επί 05 sec Αυτή η διαδοχή εμφάνισης των δύο ενδείξεων να πραγματοποιείται συνολικά πέντε φορές και μετά η πόρτα Ρ2 να σβήνει και να γίνεται επιστροφή (RETI) Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTINT1

γ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ1 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode ο καταχωρητής R0 να μετράει από 00 έως 59 και πάλι από την αρχή με ρυθμό μια ένδειξη ανά sec Όταν γίνει R0=60 αμέσως να γίνεται R0=00 και ο καταχωρητής R1 να αυξάνεται κατά 1 Όταν ο R1 γίνει ίσος με 60 να γυρίζει αμέσως σε 00 η όλη διαδικασία να επαναλαμβάνεται από την αρχή και αυτό να πραγματοποιείται συνεχώς Οι αρχικές ενδείξεις των καταχωρητών R0 και R1 να είναι μηδενικές Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT1

Κατrsquo αυτόν τον τρόπο το ζευγάρι καταχωρητών R1-R0 θα υλοποιεί ένα ρολόϊ που θα μετράει δευτερόλεπτα (ο R0) και λεπτά της ώρας (ο R1) Οι ενδείξεις των R0 και R1 ας είναι στο δυαδικό σύστημα αρίθμησης Η συχνότητα ρολογιού του 8051 είναι 6 MHz Ο χρόνος του 1 sec μεταξύ των διαδοχικών ενδείξεων του ρολογιού να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να

7

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 8: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1

Θα σας δοθεί μισή επί πλέον μονάδα αν η εμφάνιση των δευτερολέπτων και των λεπτών στους καταχωρητές R0 και R1 είναι στο δεκαδικό σύστημα αρίθμησης (δηλ στον κώδικα BCD) Εδώ μπορείτε να χρησιμοποιήσετε ρουτίνα με ετικέτα BINDEC (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δυαδικό σύστημα σε κώδικα BCD και το αποθηκεύει ως νέα τιμή στον Α και ρουτίνα με ετικέτα DECΒΙΝ (θα τη γράψετε στην Άσκηση 4) η οποία όταν κληθεί μετατρέπει το περιεχόμενο του συσσωρευτή Α από το δεκαδικό σύστημα αρίθμησης (κώδικας BCD) στο δυαδικό σύστημα ατίθμησης και το αποθηκεύει ως νέα τιμή στον Α Εδώ υποτίθεται ότι το περιεχόμενο του Α είναι μικρότερο από 100 Εναλλακτικά μπορείτε να κάνετε μια πρόσθεση αριθμών του είναι στο δεκαδικό σύστημα αρίθμησης (σε κώδικα BCD) και μετά να χρησιμοποιήσετε την εντολή DA A

δ) Υπό τον έλεγχο των διακοπών που προκαλούνται από τις υπερχειλίσεις του απαριθμητή Τ0 που θα πρέπει να είναι χρονιστής σε κατάλληλο mode το bit P37 να αναβοσβήνει συνεχώς με συχνότητα 1 Ηz Η χρονική καθυστέρηση των 05 sec μεταξύ των διαδοχικών αλλαγών τιμής του bit P37 να μη δημιουργείται λαμβάνεται με κλήση κάποιας ρουτίνας καθυστέρησης αλλά να προκύπτει από τον χρόνο που περνάει μεταξύ των διαδοχικών υπερχειλίσεων του απαριθμητή Τ0 Η σχετική ρουτίνα εξυπηρέτησης των διακοπών να ονομάζεται ROUTT0

Η αλλαγή τη ένδειξης της ώρας στο ζευγάρι καταχωρητών R1-R0 να γίνεται χωρίς καμιά καθυστέρηση που μπορεί να προέλθει από πιθανή εκτέλεση εκείνη τη στιγμή κάποιας ρουτίνας εξυπηρέτησης των διακοπών int0 ή ΙΝΤ 1 Επίσης και το αναβοσβήσιμο του bit P37 να γίνεται χωρίς καθυστέρηση Δηλ πιθανή κίνηση του άσσου στην πόρτα Ρ1 ή πιθανή διαδικασία εμφάνισης του ζεύγους των bytes 10000000 και 00000001 στην πόρτα Ρ2 να μην εμποδίζουν καθυστερούν το αναβοσβήσιμο του bit P37

Υπάρχει περίπτωση το ρολόϊ να χάσει μερικά sec επειδή πιθανόν όταν συμβεί υπερχείλιση του Τ1 μπορεί να εξυπηρετείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 To αντίθετο μπορεί να συμβεί Δηλ αν εκτελείται η ρουτίνα ROUTT1 και συμβεί υπερχείλιση του Τ0 θα καθυστερήσει λίγο η αλλαγή κατάστασης του bit P37 Τι μπορείτε να κάνετε ώστε οι υπερχειλίσεις των χρονιστών Τ0 και Τ1 να συμβαίνουν σε εντελώς ξεχωριστές και απομακρυσμένες μεταξύ τους χρονικές στιγμές οπότε ποτέ δεν θα τύχει η υπερχείλιση ενός από αυτούς να συμβεί όταν εκτελείται η ρουτίνα εξυπηρέτησης της διακοπής από υπερχείλιση του άλλου

8

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 9: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

Λύση

0000HLJMP MAIN0003HLJMP ROUTINT0000BHLJMP ROUTT00013HLJMP ROUTINT1001BHLJMP ROUTT1

Οι αρχικοποιήσεις στο ΜΑΙΝ γίνονται εδώ για όλα τα ερωτήματα της άσκησης

MAIN(0100H)MOV SP70HMOV IE10001111BSETB IT0SETΒ IT1ΜOV TMOD00010001BMOV R400HMOV R300HSETB TR1SETB TR0MOV R000HMOV R100H

MOV A00H ARXHMOV P0A

MOV R208H LOOP1LCALL WAIT

LCALL WAITRL AINC A (ή ADD A01H)MOV P0ADJNZ R2LOOP1MOV R208H

LOOP2LCALL WAITLCALL WAITCLR ACC7RL AMOV P0ADJNZ R2LOOP2SJMP ARXH

ROUTINT0(0200H)PUSH R2

PUSH ACCMOV A0000001BMOV R207H

9

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 10: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

BROX1MOV P1ALCALL WAITLCALL WAITRL ADJNZ R2BROX1MOV R208H

BROX2MOV P1ALCALL WAITLCALL WAITRR ADJNZ R2BROX2MOV P100HPOP ACCPOP R2RETI

ROUTINT1(0300H)PUSH R2MOV R205H

LOOPMOV P210000000BLCALL WAITMOV P200000001BLCALL WAITDJNZ R2LOOPMOV P200HPOP R2RETI

ROUTT1(0400H)CLR TR1MOV TL1MNH (=Β9Η)MOV TH1KLH (=3CΗ)SETB TR1INC R4CJNE R40AHFYGE1 αν δεν έχουν γίνει 10 υπερχειλίσεις του Τ1 MOV R400H φύγεINC R0CJNE R03CH(=60)FYGE1 Αν δεν έχουν περάσει 60 δευτερόλεπταMOV R000H φύγεINC R1CJNE R13CHFYGE1 Αν δεν έχουν περάσει 60 λεπτά φύγεMOV R100H

FYGE1 RETI

Για την έξτρα 05 μονάδα η ρουτίνα ROUTT1 θα είναι

10

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 11: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0LCALL DECBININC ALCALL BINDECMOV R0ACJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1LCALL DECBININC ALCALL BINDECMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

Τώρα που η ρουτίνα ROUTT1 χρησιμοποιεί τον συσσωρευτή Α στην αρχή της ρουτίνας τον σώζουμε στον σωρό και στο τέλος τον τραβάμε από τον σωρό

Εναλλακτικά στην παραπάνω ρουτίνα η αύξηση της ένδειξης των R0 και R1 κατά 1 θα μπορούσε να γίνει με εκτέλεση πρόσθεσης στο δεκαδικό σύστημα αρίθμησης Η ρουτίνα ROUTT1 θα ήταν

ROUTT1(0400H)PUSH ACCCLR TR1MOV TL1ΜΝΗ (=BBH)MOV TH1ΚLΗ (=3CH)SETB TR1INC R4CJNE R40AHFYGE1MOV R400HMOV AR0ADD A01HDA AMOV R0A

11

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 12: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

CJNE R001100000B (ή 60Η)FYGE1MOV R000HMOV AR1ADD A01HDA AMOV R1ACJNE R101100000B (ή 60Η)FYGE1MOV R100H

FYGE1POP ACCRETI

ROUTT0(0500H)CLR TR0MOV TL0MNH (=B9H)MOV TH0KLH (=3CH)SETB TR0INC R3CJNE R305HFYGE0MOV R300HCPL P37

FYGE0RETI

Επεξηγήσεις Αφού η συχνότητα ρολογιού του 8051 είναι 6 MHz η περίοδός του είναι Τ=16 μsec άρα η διάρκεια ενός κύκλου μηχανής είναι 12T=2 μsec Ο χρόνος 1 sec αντιστοιχεί σε 1sec(2μsec)=10000002=500000 κύκλους μηχανής Επειδή είναι 500000gt65536 και 500000=1050000 θα φροντίσουμε ο χρονιστής Τ1 να έχει κύκλο 50000 ενδείξεων και κάθε 10η υπερχείλισή του η ένδειξη του ρολογιού που υλοποιούν οι R1-R0 να αυξάνεται κατά 1 sec Θα χρησιμοποιηθεί ο καταχωρητής R4 ως μετρητής υπερχειλίσεων του Τ1 Στην αρχή της ρουτίνας ROUTT1 o T1 θα φορτώνεται με μια ένδειξη ΚLΜΝΗ τέτοια ώστε μεταξύ διαδοχικών υπερχειλίσεων του Τ1 να περνάνε 50000 κύκλοι μηχανής

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ1 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ1 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 001ΒΗ που παίρνει 2 κύκλους μηχανής (Παρένθεση Μπορεί από την υπερχείλιση του Τ1 μέχρι την έναρξη της εκτέλεσης της εντολής άλματος στη διεύθυνση 001ΒΗ να περάσει ένας ακόμα κύκλος μηχανής Αυτό γιατί η υπερχείλιση του Τ1 μπορεί να συμβεί κατά τον πρώτο κύκλο μηχανής μιας εντολής των δύο κύκλων μηχανής Πρέπει να ολοκληρωθεί η εκτέλεση της εντολής δύο κύκλων μηχανής για να ακολουθήσει το άλμα στη διεύθυνση 001ΒΗ Αν υπήρχαν και εντολές πολλαπλασιασμού MUL ή διαίρεσης DIV μπορεί να απαιτούνταν ακόμα 1 2 ή 3 κύκλοι μηχανής αφού αυτές οι δύο εντολές είναι των τεσσάρων κύκλων μηχανής Επειδή οι εντολές των δύο κύκλων μηχανής είναι το 29

12

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 13: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

των εντολών της γλώσσας του 8051 και επειδή δεν μπορούμε να ελέγξουμε το φαινόμενο υποθέτουμε ότι μετά την υπερχείλιση του Τ1 εκτελείται αμέσως η εντολή άλματος στο άνυσμα διακοπής 001BH)

To άλμα στη ρουτίνα ROUTT1 παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Με την εντολή SETB TR1 που παίρνει 1 κύκλο μηχανής ο Τ1 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ1 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε 65545ndashKLMNH=50000 οπότε KLMNH= 15545=3CB9H δηλ είναι KLH=3CH και MNH=B9H

Για την έξτρα 05 μονάδα Τώρα που στην αρχή της ρουτίνας ROUTT1 έχει προστεθεί η εντολή PUSH ACC η οποία για την εκτέλεσή της απαιτεί 2 κύκλους μηχανής οι τέσσερες πρώτες εντολές της ρουτίνας ROUTT1 παίρνουν 2+1+2+2=7 κύκλους μηχανής και φορτώνουν τον Τ1 με την τιμή KLMNH Η συνέχεια του υπολογισμού της σταθεράς KLMNH είναι ίδιος με προηγουμένως Το τελικό αποτέλεσμα είναι KLMNH=3CBBH

Για τη ρουτίνα ROUTT0 o υπολογισμός της σταθεράς KLMNH είναι όπως στην αρχική ρουτίνα ROUTT1 Το αποτέλεσμα είναι KLMNH=3CB9H

Οι διακοπές από τις υπερχειλίσεις των Τ1 και Τ0 πρέπει να διακόπτουν την εκτέλεση των ρουτινών ROUTINT0 και ROUTINT1 αν τύχει κάποια από αυτές να εκτελείται όταν υπερχειλίσει ο Τ1 ή ο Τ0 Για να εξασφαλίσουμε κάτι τέτοιο αρκεί να κάνουμε ψηλής προτεραιότητας τις διακοπές από τις υπερχειλίσεις του Τ1 και από τις υπερχειλίσεις του Τ0 και να αφήσουμε σε χαμηλή προτεραιότητα τις διακοπές

int0 και ΙΝΤ 1 Δεν ξεχνάμε ότι με Reset του 8051 όλες οι διακοπές του 8051 γίνονται χαμηλής προτεραιότητας Έτσι πριν τον βρόχο του κυρίως προγράμματος προσθέτουμε τις εντολές SETB PT1 και SETB PT0

Αν εκτελείται η ρουτίνα ROUTT0 που αναβοσβήνει το bit P37 και υπερχειλίσει ο Τ1 η υπερχείλιση του Τ1 δεν θα διακόψει την εκτέλεση της ρουτίνας ROUTT0 και ο 8051 θα τη βάλει σε αναμονή κάνοντας TF1=1 διότι και οι δύο διακοπές είναι ίδιας (ψηλής) προτεραιότητας Η ενημέρωση της ένδειξης του ρολογιού θα καθυστερήσει μέχρι να ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0 Τότε θα αρχίσει η εκτέλεση της ρουτίνας ROUTT1 Έτσι το ρολόϊ R1-R0 θα καθυστερήσει (θα χάσει) τον χρόνο που απαιτεί η ROUTT0 ή μέρος αυτής για την ολοκλήρωσή της

Το ίδιο με παραπάνω θα συμβεί και αν υπερχειλίσει ο Τ0 ενώ εκτελείται η ρουτίνα ROUTT1 Θα καθυστερήσει λίγο η αλλαγή της τιμής του bit P37

13

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 14: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

Αντιμετώπιση του προβλήματος Όπως είναι το κυρίως πρόγραμμα και οι ρουτίνες ROUTT1 και ROUTT0 με το ξεκίνημα του κυρίως προγράμματος είναι Τ0=Τ1=0000Η Οι χρονιστές Τ1 και Τ0 ξεκινούν να μετρούν μόλις εκτελεστούν οι εντολές SETB TR1 και SETB TR0 Αφού αυτές οι δύο εντολές είναι διαδοχικές στο πρόγραμμα η ένδειξη του Τ0 θα διαφέρει πάντα (θα έπεται) μόλις κατά 1 από την ένδειξη του Τ1 Έτσι μόλις υπερχειλίσει ο Τ1 με τον επόμενο κύκλο μηχανής θα υπερχειλίσει ο Τ0 Επομένως δεν υπάρχει ενδεχόμενο όταν υπερχειλίσει ο Τ1 να εκτελείται η ρουτίνα ROUTT0 και να καθυστερήσει το ρολόϊ R1-R0 Αντίθετα η ρουτίνα ROUTT0 πάντα θα περιμένει να ολοκληρωθεί η ρουτίνα ROUTT1 και έτσι η αλλαγή τιμής του bit P37 θα καθυστερεί λίγο Βέβαια η καθυστέρηση θα είναι μερικά μsec αφού η ρουτίνα ROUTT1 δεν περιλαμβάνει κάποιον βρόχο ή δεν καλεί κάποια ρουτίνα καθυστέρησης ώστε να καθυστερήσει η ολοκλήρωση της εκτέλεσής της

Ένα απλός τρόπος οι υπερχειλίσεις των Τ1 και Τ0 να συμβαίνουν σε εντελώς ξεχωριστές μεταξύ τους χρονικές στιγμές και οι ρουτίνες ROUTT1 και ROUTT0 να μην εμπλέκονται χρονικά μεταξύ τους είναι ο εξής Επειδή οι δύο χρονιστές Τ1 και Τ0 υπερχειλίζουν κάθε 50000 κύκλους μηχανής ο καθένας αρκεί να βάλουμε τον έναν από αυτούς να τρέχει αρκετούς κύκλους μηχανής (π χ 20000=4Ε20Η κύκλους μηχανής) πριν τον άλλον Προς τούτο στο κυρίως πρόγραμμα πριν την εντολή ΜOV TMOD00010001B θα γράψουμε τις εντολές MOV TH14EH και MOV TL120H που φορτώνουν τον χρονιστή Τ1 με την ένδειξη 4E20H Έτσι η ένδειξη του Τ1 θα προηγείται της ένδειξης του Τ0 κατά 4Ε20Η=20000 οπότε μέχρι να υπερχειλίσει ο Τ0 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT1 και επίσης μέχρι να υπερχειλίσει ο Τ1 θα έχει ολοκληρωθεί η εκτέλεση της ρουτίνας ROUTT0

Επειδή έχουμε αφήσει τις διακοπές int0 και ΙΝΤ 1 σε χαμηλή προτεραιότητα η μία δεν μπορεί να διακόψει την εκτέλεση της ρουτίνας εξυπηρέτησης της άλλης και ο 8051 θα τη βάζει σε αναμονή Αν βρίσκονται και οι δύο σε αναμονή θα εκτελεστεί πρώτα η ρουτίνα ROUTINΤ0 λόγω μεγαλύτερης εσωτερικής προτεραιότητας έναντι της ROUTINT1

Άσκηση 2

Να γραφεί κυρίως πρόγραμμα στη γλώσσα του 8051 ο βρόχος του οποίου θα εκτελείται συνεχώς και θα εμφανίζει στην πόρτα Ρ0 του 8051 τη διαδοχή ενδείξεων 00000001 00000010 hellip 01000000 10000000 01000000 00100000 hellip00000010 και πάλι από την αρχή συνεχώς με ταχύτητα μια ένδειξη ανά sec Δηλ ένας άσσος να πηγαινοέρχεται από άκρη σε άκρη της πόρτας Ρ0 με ταχύτητα μια θέση ανά sec Οι παραπάνω ενδείξεις να δημιουργούνται με κάποιον βρόχο ή βρόχους όπου θα γίνονται μεταξύ των άλλων και περιστροφές του περιεχομένου του συσσωρευτή Α Με άλλα λόγια το πρόγραμμά σας να μην είναι laquoμακαρόνιraquo ήτοι να μη φορτώνει

14

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 15: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

μία-μία τις παραπάνω 14 ενδείξεις στην πόρτα Ρ0 με ενδιάμεση κλήση κάποιας ρουτίνας καθυστέρησης Το κυρίως πρόγραμμα να ξεκινά με το σήμα Reset του 8051 τη χρονική στιγμή t=0 Έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec

α) Αν φθάσει στον ακροδέκτη Ρ32 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT0 της οποίας να αναβοσβήνει πέντε φορές με συχνότητα 1 Hz όλα μαζί τα bits της πόρτας Ρ1 και μετά να γίνεται επιστροφή (RETI) αφήνοντας τα bits σβηστά

β) Αν φθάσει στον ακροδέκτη Ρ33 αρνητικό μέτωπο τάσης να προκαλείται διακοπή του προγράμματος του 8051 η ρουτίνα εξυπηρέτησης ROUT1 της οποίας να εμφανίζει στην πόρτα Ρ2 του 8051 έναν άσσο να κάνει μια πλήρη διαδρομή από αριστερά προς τα δεξιά στη συνέχεια μια πλήρη διαδρομή από δεξιά προς τα αριστερά και μετά να σβήνει και να γίνεται επιστροφή (RETI) Σε κάθε θέση ο άσσος να παραμένει επί 1 sec

γ) Στους ακροδέκτες Ρ32 και Ρ33 του 8051 οδηγούμε τις παρακάτω κυματομορφές τάσης (μην σας ενοχλεί που δεν έχει τηρηθεί σωστή χρονική κλίμακα)

γ1 Τι θα παρατηρήσετε στις πόρτες Ρ0 Ρ1 και Ρ2 με την εξέλιξη του χρόνου και γιατί Απαντήστε αναλυτικά δικαιολογώντας την απάντησή σας

γ2 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε προσθέστε την εντολή CLR IT0 και επαναλάβετε το προηγούμενο ερώτημα α

γ3 Στο προηγούμενο ερώτημα β την εντολή CLR IT0 αντικαταστήστε την με την εντολή CLR IT1 και επαναλάβετε το ερώτημα α

15

t (sec)

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 16: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

γ4 Αμέσως πριν τον βρόχο του κυρίως προγράμματος που γράψατε στο ερώτημα α προσθέστε τις εντολές CLR IT0 και CLR IT1 και επαναλάβετε το ερώτημα α

Λύση

0000HLJMP MAIN0003HLJMP ROUT00013HLJMP ROUT1

MAIN(0100H)MOV SP70HSETB IT0SETΒ IT1MOV IE10000101B

MOV A00000001ΒLOOPMOV P0A

MOV R207H LOOP1LCALL WAIT

LCALL WAITRL AMOV P0ADJNZ R2LOOP1MOV R207H

LOOP2LCALL WAITLCALL WAITRR AMOV P0ADJNZ R2LOOP2SJMP LOOP

ROUT0(0200H)PUSH R2

MOV R205H BROXMOV P1FFH

LCALL WAITMOV P100HLCALL WAITDJNZ R2BROXPOP R2RETI

Χρόνος εκτέλεσης της ROUT0=5 sec

ROUT1(0300H)PUSH R2

16

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 17: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές ακμοπυροδότητες

PUSH ACCMOV R207H

MOV A10000000B BROX1MOV P2A

LCALL WAITLCALL WAITRR ADJNZ R2BROX1MOV R208H

BROX2MOV P2ALCALL WAITLCALL WAITRL ADJNZ R2BROX2

MOV P200HPOP ACCPOP R2RETI

Χρόνος εκτέλεσης της ROUT1=15 sec

γ1) Στο παρόν και στα υπόλοιπα ερωτήματα κανένα από τα δύο σήματα διακοπής ΙΝΤ 0 και ΙΝΤ 1 δεν διακόπτει τη ρουτίνα εξυπηρέτησης της άλλης διακοπής διότι και οι δύο διακοπές είναι ίδιας (χαμηλής) προτεραιότητας

Μέχρι τον χρόνο t=34 sec δεν έχει φθάσει στον 8051 κανένα σήμα διακοπής (κανένα αρνητικό μέτωπο τάσης στους ακροδέκτες Ρ32 και Ρ33) οπότε εκτελείται

17

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 18: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

το κυρίως πρόγραμμα που εμφανίζει έναν άσσο να κινείται στην αρχή από δεξιά προς τα αριστερά στην πόρτα Ρ0 με ταχύτητα μια θέση ανά sec

t=34 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο γίνεται αμέσως δεκτό καλείται η ρουτίνα ROUT0 και αρχίζει το αναβοσβήσιμο των bits της πόρτας Ρ1 Κανονικά η εκτέλεση της ROUT0 θα τελειώσει τη χρονική στιγμή 34+5=84

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 και t=74 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=84 Ολοκληρώνεται η εκτέλεση της ROUT0 και αρχίζει η εξυπηρέτηση της διακοπής ΙΝΤ 1 η οποία είναι σε αναμονή Γίνεται IE1=0 και καλείται η ρουτίνα ROUT1 Κανονικά η εκτέλεση της ROUT1 θα τελειώσει τη χρονική στιγμή 84+15=234

t=92 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο μπαίνει σε αναμονή κάνοντας IE0=1

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1

t=127 και t=131 Δεν συμβαίνει τίποτα γιατί τα μέτωπα τάσης είναι θετικά

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=164 Φθάνει σήμα διακοπής ΙΝ Τ 0 το οποίο ξανακάνει IE0=1

t=234 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=234+5=284 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και εξυπηρετείται η διακοπή ΙΝΤ 1 που βρίσκεται σε αναμονή Γίνεται ΙΕ1=0 και καλείται η ρουτίνα ROUT1 Ένας άσσος κάνει ένα πηγαινέλα στην πόρτα Ρ2

t=284+15=434 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και γίνεται επιστροφή στο κυρίως πρόγραμμα Συνεχίζεται η μετακίνηση του άσσου στην πόρτα Ρ0

18

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 19: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164 t (sec)

Διακοπές επιπεδοπυροδότητες

Διακοπές ακμοπυροδότητες

γ2) Τώρα οι διακοπές Ι ΝΤ 0 είναι επιπεδοπυροδότητες Από τον χρόνο t=0 μέχρι τον χρόνο t=23 sec δεν έχει φθάσει στον 8051 σήμα διακοπής ΙΝΤ 1 αλλά φθάνουν (μετά την εκτέλεση της εντολής CLR IT0) συνεχώς σήματα διακοπής ΙΝΤ 0 Καλείται η ρουτίνα ROUT0 και τα bits της πόρτας Ρ1 αναβοσβήνουν Η συνεχής έλευση σημάτων διακοπής ΙΝΤ 0 δεν έχει καμία συνέπεια στην εκτέλεση της ρουτίνας ROUT0 Αυτά κάνουν ΙΕ0=1 διότι οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες

t=23 Σταματάνε να έρχονται σήματα διακοπής ΙΝΤ 0 στον 8051 Γίνεται ΙΕ0=0 αλλά η εκτέλεση της ρουτίνας ROUT0 συνεχίζεται μέχρι τη χρονική στιγμή 5

t=28 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=34 Φθάνει νέο σήμα διακοπής ΙΝΤ 0 το οποίο κάνει αμέσως ΙΕ0=1 και αυτή η τιμή διατηρείται ενόσω ο ακροδέκτης Ρ32 παραμένει σε λογικό 0 μιας και οι διακοπές ΙΝΤ 0 είναι επιπεδοπυροδότητες Συνεχίζεται η εκτέλεση της ρουτίνας ROUT0 μέχρι τη χρονική στιγμή 5

t=5 O 8051 βλέπει ότι είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο μπαίνει σε αναμονή κάνοντας IE1=1 διότι και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 Η (δεύτερη) εκτέλεση της ρουτίνας ROUT0 που άρχισε τη χρονική στιγμή 5 συνεχίζεται

t=74 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

19

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 20: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές ακμοπυροδότητες

Διακοπές επιπεδοπυροδότητες

t=92 Ξαναφθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1 ενώ συνεχίζεται η δεύτερη εκτέλεση της ρουτίνας ROUT0

t=10 Τελειώνει η δεύτερη εκτέλεση της ρουτίνας ROUT0 και αυτή ξανακαλείται αφού εκείνη τη στιγμή είναι ΙΕ0=1 και οι διακοπές ΙΝΤ 0 έχουν μεγαλύτερη εσωτερική προτεραιότητα από τις διακοπές ΙΝΤ 1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=127 Δεν συμβαίνει τίποτα γιατί το μέτωπο τάσης στον ακροδέκτη Ρ33 είναι θετικό

t=131 Γίνεται ΙΕ0=0

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο ξανακάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Τότε ο 8051 βλέπει να είναι ΙΕ0=0 και ΙΕ1=1 οπότε καλεί τη ρουτίνα ROUT1 και κάνει ΙΕ1=0 Αυτή η ρουτίνα κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι ΙΕ0=1 και ΙΕ1=0 Καλεί τη ρουτίνα ROUT0 που τελειώνει τη χρονική στιγμή 30+5=35 Τότε εξακολουθεί να είναι ΙΕ0=1 οπότε ξανακαλείται η ROUT0 και αυτό συμβαίνει συνέχεια αφού ο ακροδέκτης Ρ32 διατηρείται σε λογικό 0 Οι ακροδέκτες της πόρτας Ρ1 αναβοσβήνουν συνεχώς

γ3) Τώρα οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες Τον χρόνο t=0 (μετά την εκτέλεση της εντολής CLR IT1) υπάρχει σήμα διακοπής ΙΝΤ 1 αφού είναι

20

t (sec)

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 21: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

74

0

+5 Volt

34

Ρ32

6823 92

0

+5 Volt

51

Ρ33

11428 148 t (sec)127

131 164

Διακοπές επιπεδοπυροδότητες

Διακοπές επιπεδοπυροδότητες

Ρ33=0 Καλείται η ρουτίνα ROUT1 η οποία κανονικά θα τελειώσει τη χρονική στιγμή 15

Τις χρονικές 34 και 92 έρχονται σήματα διακοπής ΙΝΤ 0 τα οποία κάνουν ΙΕ0=1 Μέχρι τον χρόνο 127 έχουν έλθει και παρέλθει δύο σήματα διακοπής ΙΝΤ 1 αφού αυτές οι διακοπές είναι επιπεδοπυροδότητες

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο κάνει ΙΕ1=1

t=15 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1

t=164 Έρχεται σήμα διακοπής ΙΝΤ 0 το οποίο κάνει ΙΕ0=1

t=15+5=20 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται πρώτα η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Γίνεται ΙΕ0=0 και καλείται η ρουτίνα ROUT0 που αναβοσβήνει πέντε φορές τα bits της πόρτας Ρ1 Αυτή η εκτέλεση της ρουτίνας ROUT0 κανονικά θα τελειώσει τη χρονική στιγμή 20+5=25

t=25 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 και ο 8051 καλεί και εκτελεί συνεχώς τη ρουτίνα ROUT1 αφού οι διακοπές ΙΝΤ 1 είναι επιπεδοπυροδότητες και ο ακροδέκτης Ρ33 παραμένει σε λογικό 0 Ένας άσσος θα κάνει συνεχή πηγαινέλα στην πόρτα Ρ2

γ4) Τώρα και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι επιπεδοπυροδότητες

t=0 Μόλις αρχίζει το κυρίως πρόγραμμα είναι ΙΕ0=ΙΕ1=1 διότι μετά το reset οι διακοπές ΙΝΤ 1 και ΙΝΤ 0 είναι επιπεδοπυροδότητες Όμως δεν καλείται καμιά

21

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 22: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

ρουτίνα εξυπηρέτησης διακοπών αφού οι διακοπές είναι ακόμα απενεργοποιημένες Μετά την εκτέλεση των εντολών SETB IT0 και SETB IT1 είναι ΙΕ0=ΙΕ1=0 διότι οι διακοπές γίνονται ακμοπυροδότητες και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται σε λογικό 0 (δεν έχει φθάσει κάποιο αρνητικό μέτωπο τάσης) Μόλις εκτελείται η εντολή CLR IT0 καλείται η ρουτίνα ROUT0 διότι η διακοπή ΙΝΤ 0 έγινε επιπεδοπυροδότητη και ο ακροδέκτης Ρ32 βρίσκεται σε λογικό 0 Εξακολουθεί να είναι ΙΕ0=1 διότι συνεχίζει να είναι Ρ32=0 αλλά να είναι και ΙΕ1=0 διότι οι διακοπές ΙΝΤ 1 δεν έχουν ξαναγίνει επιπεδοπυροδότητες Κανονικά η ρουτίνα ROUT0 θα ολοκληρωθεί τη χρονική στιγμή 5

t=23 Γίνεται ΙΕ0=0

t=28 Εξακολουθεί να είναι ΙΕ1=0

t=34 Ξαναγίνεται ΙΕ0=1

t=5 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT0 γίνεται επιστροφή στην εντολή CLR IT1 η οποία εκτελείται και κάνει τις διακοπές ΙΝΤ 1 επιπεδοπυροδότητες αλλά παραμένει ΙΕ1=0 αφού ο ακροδέκτης Ρ33 βρίσκεται σε λογικό 1 Ξανακαλείται η ρουτίνα ROUT0 Αυτή η εκτέλεση θα τελειώσει τη χρονική στιγμή 5+5=10

t=51 Φθάνει σήμα διακοπής ΙΝΤ 1 οπότε γίνεται IE1=1 Η εκτέλεση της ρουτίνας ROUT0 δεν διακόπτεται αφού και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 είναι ίδιας (χαμηλής) προτεραιότητας

t=68 Γίνεται ΙΕ0=0 διότι ο ακροδέκτης Ρ32 ανέβηκε σε λογικό 1

t=74 Γίνεται ΙΕ1=0 διότι ο ακροδέκτης Ρ33 ανέβηκε σε λογικό 1

t=92 Ξαναγίνεται ΙΕ0=1 διότι ο ακροδέκτης Ρ32 κατέβηκε σε λογικό 0

t=10 Ολοκληρώνεται η δεύτερη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει να είναι ΙΕ0=1 και ξανακαλεί τη ρουτίνα ROUT0 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 10+5=15

t=114 Φθάνει σήμα διακοπής ΙΝΤ 1 διότι ο ακροδέκτης Ρ33 κατέβηκε σε λογικό 0 Αυτό δεν γίνεται αμέσως δεκτό αλλά γίνεται IE1=1

t=127 Γίνεται ΙΕ1=0 διότι το δυναμικό του ακροδέκτη Ρ33 έγινε ψηλό

t=131 Γίνεται ΙΕ0=0 διότι το δυναμικό του ακροδέκτη Ρ32 έγινε ψηλό

t=148 Φθάνει σήμα διακοπής ΙΝΤ 1 το οποίο δεν γίνεται αμέσως δεκτό αλλά κάνει IE1=1

t=15 Ολοκληρώνεται η τρίτη εκτέλεση της ρουτίνας ROUT0 Ο 8051 βλέπει ότι είναι ΙΕ1=1 και καλεί τη ρουτίνα ROUT1 η εκτέλεση της οποίας κανονικά θα τελειώσει τη χρονική στιγμή 15+15=30

22

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 23: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

t=164 Φθάνει σήμα διακοπής ΙΝΤ 0 το οποίο κάνει IE0=1

t=30 Ολοκληρώνεται η εκτέλεση της ρουτίνας ROUT1 και ο 8051 βλέπει να είναι σε αναμονή και οι δύο διακοπές ΙΝΤ 0 και ΙΝΤ 1 Εξυπηρετείται η ΙΝΤ 0 διότι αυτή έχει μεγαλύτερη εσωτερική προτεραιότητα Επειδή και οι δύο ακροδέκτες Ρ32 και Ρ33 βρίσκονται συνεχώς σε λογικό 0 είναι συνεχώς ΙΕ0=1 και ΙΕ1=1 οπότε μετά την ολοκλήρωση της εκτέλεσης της ρουτίνας ROUT0 ξανακαλείται η ίδια ρουτίνα Οι ακροδέκτες της πόρτας Ρ1 θα αναβοσβήνουν συνεχώς

Άσκηση 3

Από τη διεύθυνση 0100H και κάτω να γράψετε κυρίως πρόγραμμα ο βρόχος του οποίου θα αναβοσβήνει συνεχώς όλα μαζί τα bits της πόρτας Ρ0 με συχνότητα 1 Hz Το κυρίως πρόγραμμα να αρχίζει με Reset του 8051 Θεωρήστε ότι έχετε έτοιμη ρουτίνα καθυστέρησης με ετικέτα WAIT η οποία όταν κληθεί προκαλεί καθυστέρηση 05 sec Στα ερωτήματα που ακολουθούν η συχνότητα ρολογιού του 8051 είναι 24 MHz

α) Συμπληρώστε το πρόγραμμα που μόλις γράψατε ώστε ο απαριθμητής Τ0 να γίνει χρονιστής σε mode 1 και να τρέχει συνεχώς Με κάθε υπερχείλιση του Τ0 να προκαλείται διακοπή του κυρίως προγράμματος η ρουτίνα εξυπηρέτησης της οποίας να ονομάζεται ROUT0 να αρχίζει από τη διεύθυνση 0200Η και με τις διαδοχικές κλήσεις της να προκαλεί συνεχές αναβοσβήσιμο του MSB της πόρτας Ρ1 Δηλ μια υπερχείλιση του Τ0 να ανάβει το bit P17 αν αυτό είναι σβηστό ή να το σβήνει αν αυτό είναι αναμμένο Με άλλα λόγια με κάθε υπερχείλιση του Τ0 να αλλάζει τιμή το bit P17 Για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά ο χρόνος μεταξύ των διαδοχικών αλλαγών τιμής του bit P17 να είναι αυτός μεταξύ των υπερχειλίσεων του Τ0 Ποιος είναι ο ρυθμός αναβοσβησίματος του bit P17

β) Τώρα θέλουμε το bit P17 να αναβοσβήνει με συχνότητα 1 Hz Κάντε τις απαραίτητες τροποποιήσεις στο κυρίως πρόγραμμα ή και στη ρουτίνα ROUT0 ώστε να πετύχετε αυτή τη συχνότητα αναβοσβησίματος του Ρ17 Πάλι για το αναβοσβήσιμο του bit P17 να μην καλείται καμιά ρουτίνα καθυστέρησης

γ) Αφού πετύχατε ότι ζητάει το Ερώτημα β κάντε τις απαραίτητες τροποποιήσεις ώστε επί πλέον αυτών και με τη βοήθεια των διαδοχικών υπερχειλίσεων του απαριθμητή Τ1 στους ακροδέκτες της πόρτας Ρ2 να εμφανίζεται πρώτα το byte 11110000Β και μετά το byte 00001111Β και η ίδια διαδοχή ενδείξεων να επαναλαμβάνεται συνεχώς με διάρκεια εμφάνισης καθενός byte 05 sec Η ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 να ονομάζεται ROUT1 και να αρχίζει από τη διεύθυνση 0300Η Για το πέρασμα του χρόνου των 05 sec να μην καλείται καμιά ρουτίνα καθυστέρησης αλλά αυτός ο χρόνος να προκύπτει από τον χρόνο μεταξύ των υπερχειλίσεων του Τ1

Αφού τα κάνετε όλα αυτά παρατηρήστε την ευχέρεια που μας παρέχουν οι διακοπές που οφείλονται στις υπερχειλίσεις των απαριθμητών Ενώ ο 8051 ασχολείται και τρέχει το κυρίως πρόγραμμα στο laquoυπόβαθροraquo τρέχουν οι απαριθμητές του και ο 8051 ασχολείται με τις αντίστοιχες ρουτίνες εξυπηρέτησης μόνο για λίγο όσο χρειάζεται για να εκτελεστούν αυτές οι ρουτίνες εξυπηρέτησης Κι όμως έτσι εκτελείται δουλειά

23

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 24: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

laquoισοδύναμηraquo με τη δουλειά του κυρίως προγράμματος με το οποίο ο 8051 ασχολείται laquoσυνέχειαraquo

δ) Τροποποιήστε ότι γράψατε παραπάνω ώστε οι απαριθμητές να κάνουν την ίδια δουλειά αλλά να λειτουργούν σε mode 2 Εδώ θα χρειαστείτε 16-bit μετρητές υπερχειλίσεων των απαριθμητών Τ0 και Τ1 Ως έναν τέτοιον μετρητή μπορείτε να χρησιμοποιήσετε τον καταχωρητή DPTR και ως έναν ακόμα ένα ζευγάρι 8-bit καταχωρητών π χ το ζευγάρι R2R3 Στον καταχωρητή R3 να αποθηκεύονται τα bits 7-0 δηλ το χαμηλής τάξης byte της ένδειξης του μετρητή και στον καταχωρητή R2 να αποθηκεύονται τα bits 15-8 δηλ το ψηλής τάξης byte της ένδειξης του μετρητή

Δείτε την ευκολία που μας παρέχει εδώ το mode 1 των απαριθμητών σε σύγκριση με το mode 2

Λύση

Συχνότητα αναβοσβησίματος της πόρτας Ρ0=1 Hz rArr περίοδος αναβοσβησίματος =1 sec rArr ΟΝ=05 sec και OFF=05 sec

0000HLJMP MAIN000BHLJMP ROUT0001BHLJMP ROUT1

α) MAIN(0100H)MOV SP70HSETB ET0SETB ET1SETB EAMON TMOD00000001BSETB TR0

LOOPMOV P0FFHLCALL WAITMOV P000HLCALL WAITSJMP LOOP

ROUT0(0200H)CPL P17RETI

Ο απαριθμητής Τ0 έχει γίνει χρονιστής σε mode 1 και τρέχει Έχουμε fclock=24 MHz rArr T=124 μsec rArr 12T=05 μsec ήτοι ένας κύκλος μηχανής του 8051 διαρκεί 05 μsec Το πλήθος των ενδείξεων του Τ0 σε mode 1 είναι 65536 Επομένως από υπερχείλιση σε υπερχείλιση του Τ0 περνάνε 65536 κύκλοι μηχανής που διαρκούν 65536times05=32768 μsec Κάθε 32768 msec αλλάζει κατάσταση ο ακροδέκτης Ρ17 Συνεπώς αυτός αναβοσβήνει συνεχώς με περίοδο 65536 msec ήτοι με συχνότητα (165536) kHz=(100065536) Hz=1526 Hz ήτοι 1526 αναβοσβησίματα ανά sec

24

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 25: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

β) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ0 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ0 να περιλαμβάνει 50000 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ0

Ο καταχωρητής R4 θα είναι μετρητής των υπερχειλίσεων του Τ0 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο Τ0 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R400H και η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)CLR TR0 MOV TH0KLH (=3CH)

MOV TL0MNH (=B9CH)SETB TR0INC R4CJNE R420 (ή 14Η) FYGE0ΜOV R400HCPL P17

FYGE0RETI

Ας δούμε πόσοι κύκλοι μηχανής περνάνε από τη στιγμή που ο Τ0 παίρνει τιμή FFFFH μέχρι να ξαναπάρει αυτήν την τιμή Για να πάει ο Τ0 από την τιμή FFFFH στην τιμή 0000Η (δηλ για να γίνει υπερχείλιση αυτού) περνάει 1 κύκλος μηχανής Ακολουθεί άλμα στη διεύθυνση 000ΒΗ που παίρνει 2 κύκλους μηχανής Ύστερα γίνεται άλμα στη ρουτίνα ROUT0 που παίρνει άλλους 2 κύκλους μηχανής Οι τρεις πρώτες εντολές της ρουτίνας ROUT0 παίρνουν 1+2+2=5 κύκλους μηχανής και φορτώνουν τον Τ0 με την τιμή KLMNH Με την εντολή SETB TR0 που παίρνει 1 κύκλο μηχανής ο Τ0 laquoξεπαγώνειraquo και αποκτά τιμή KLMNH+1 Στη συνέχεια με κάθε κύκλο μηχανής αυξάνει την ένδειξή του κατά 1 μέχρι να ξαναπάρει τιμή FFFFH Για να πάει ο Τ0 από την ένδειξη KLMNH+1 μέχρι την ένδειξη FFFFH περνάνε FFFFHndash(KLMNH+1)=65534ndashKLMNH κύκλοι μηχανής Έτσι συνολικά από ένδειξη FFFFH μέχρι ένδειξη FFFFH του Τ1 περνάνε 1+2+2+5+1+65534ndashKLMNH=65545ndashKLMNH Θέλουμε να είναι 65545ndashKLMNH=50000 οπότε είναι KLMNH=15545=3CB9H Για αυτόν τον λόγο στη ROUT0 ο T0 θα φορτώνεται με 3CB9H Δηλ οι εντολές MOV TH0KLH και MOV TL0MNH θα είναι MOV TH03CH και MOV TL0B9H αντίστοιχα

γ) Την εντολή MOV TMOD00000001B την κάνουμε MOV TMOD00010001B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt65536 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του Τ1 Επειδή είναι 1000000= 20times50000 θα φροντίσουμε ο κύκλος ενδείξεων του Τ1 να περιλαμβάνει 50000

25

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 26: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 20 υπερχειλίσεις του Τ1 Μάλιστα κάθε 20 υπερχειλίσεις του Τ1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής R5 θα είναι μετρητής υπερχειλίσεων του Τ1 Μέσα στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ1 ο Τ1 θα φορτώνεται με κάποια σταθερά KLMNH και μετά θα αφήνεται να τρέξει μέχρι να υπερχειλίσει Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV R500H και η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)CLR TR1MOV TH1KLH (=3CH)

MOV TL1MNH (=B9CH)SETB TR1INC R5CJNE R520 (ή 14Η) FYGE1ΜOV R500HΧRL P2FFH

FYGE1RETI

Όπως στο ερώτημα β βρίσκουμε ότι πρέπει να είναι KLH=3CH και MNH=B9H

δ)

δα) Αν ο απαριθμητής Τ0 είναι σε mode 2 ο TL0 μετράει από KLH μέχρι FFH και πάλι από την αρχή συνεχώς όπου KLH είναι το περιεχόμενο του καταχωρητή TH0 (σταθερά επαναφόρτωσης) Με Reset ο TH0 παίρνει περιεχόμενο 00H οπότε ο κύκλος ενδείξεων του TL0 είναι από 00H μέχρι FFH και πάλι από την αρχή Περιλαμβάνει 256 ενδείξεις Έτσι ο TL0 υπερχειλίζει κάθε 256 κύκλους μηχανής που αντιστοιχούν σε 256times05=128μsec Στο κυρίως πρόγραμμα η εντολή MOV TMOD00000001B πρέπει να γίνει MOV TMOD00000010B

Η περίοδος αναβοσβησίματος του bit P17 είναι 256 μsec άρα η συχνότητά του είναι 1(256 μsec)=(1256) MHz=3906 kHz

δβ) Επιθυμητή συχνότητα αναβοσβησίματος του P17 =1 Hz rArr περίοδος αναβοσβησίματος=1 sec rArr ΟΝ=05 sec και OFF=05 sec O χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL0 Επειδή είναι 1000000= 4000times250 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL0 να περιλαμβάνει 250 ενδείξεις και το bit Ρ17 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του Τ0 H σταθερά επαναφόρτωσης του TH0 πρέπει να είναι ίση με 256ndash250=6 Επομένως στο κυρίως πρόγραμμα θα πρέπει να κάνουμε την αρχικοποίηση MOV TH006H

Το ζευγάρι καταχωρητών R2R3 θα είναι μετρητής υπερχειλίσεων του Τ0 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του Τ0 ο R2R3 θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αλλάζει κατάσταση το bit

26

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 27: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

P17 Η αύξηση του R2R3 κατά 1 θα γίνεται αυξάνοντας τον R3 κατά 1 και ελέγχοντας αν αυτός έφτασε την τιμή 00H Αν όχι θα επιστρέφει Αν ναι θα αυξάνει την ένδειξη του R2 κατά 1 και μετά θα επιστρέφει Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και τις αρχικοποιήσεις MOV R200H και MOV R300H Η ρουτίνα ROUT0 θα είναι

ROUT0(0200H)INC R3CJNE R3Α0ΗFYGE0CJNE R20FHFYGE0MOV R300HMOV R200HCPL P17RETI

FYGE0CJNE R300HFYGEINC R2

FYGERETI

δγ) ) Στο κυρίως πρόγραμμα την εντολή MOV TMOD00000010B την κάνουμε MOV TMOD00100010B και στις αρχικοποιήσεις προσθέτουμε την εντολή SETB TR1 Διάρκεια εμφάνισης καθεμιάς ένδειξης στην πόρτα Ρ2=05 sec Όπως πριν ο χρόνος των 05 sec αντιστοιχεί σε (05 sec)(05 μsec)=1000000 κύκλους μηχανής Επειδή είναι 1000000gt256 οι 1000000 κύκλοι μηχανής δεν καλύπτονται από έναν κύκλο ενδείξεων του ΤL1 Επειδή είναι 1000000= 4000times256 θα φροντίσουμε ο κύκλος ενδείξεων του ΤL1 να περιλαμβάνει 250 ενδείξεις και η πόρτα Ρ2 να αλλάζει κατάσταση κάθε 4000=0FA0H υπερχειλίσεις του ΤL1 Μάλιστα κάθε 4000 υπερχειλίσεις του ΤL1 να αναστρέφονται τα bits της πόρτας Ρ2 μιας και οι ενδείξεις 11110000Β και 00001111Β είναι η μία ανάστροφη της άλλης Στο κυρίως πρόγραμμα θα κάνουμε και την αρχικοποίηση MOV P211110000B

Ο καταχωρητής DPTR θα είναι μετρητής υπερχειλίσεων του ΤL1 Στη ρουτίνα εξυπηρέτησης των διακοπών από τις υπερχειλίσεις του ΤL1 ο DPTR θα αυξάνεται κατά 1 και θα ελέγχεται αν έφτασε την τιμή 0FA0H Αν ναι θα αναστρέφεται η ένδειξη της πόρτας Ρ2 Στο κυρίως πρόγραμμα θα πρέπει να κάνουμε και την αρχικοποίηση MOV DPTR0000H Η ρουτίνα ROUT1 θα είναι

ROUT1(0300H)INC DPTRMOV ADPLCJNE AΑ0ΗFYGEMOV ADPHCJNE A0FHFYGEMOV DPTR0000HXRL P2FFH

FYGERETI

Άσκηση 4

α) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα BINDEC η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον 8-bit δυαδικό αριθμό και θα το

27

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 28: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

μετατρέπει στο δεκαδικό σύστημα αρίθμησης σε κώδικα BCD Η μορφή του θα είναι ΕΔΜ όπου τα ψηφία των δεκάδων (Δ) και των μονάδων (Μ) θα παίρνουν τιμές από 0=0000 μέχρι 9=1001 ενώ το ψηφίο των εκατοντάδων (Ε) θα παίρνει τιμές 0 1 ή 2 Τα bits του ψηφίου Μ να καταλαμβάνουν τις θέσεις 3-0 του συσσωρευτή Α τα bits του ψηφίου Δ να καταλαμβάνουν τις θέσεις 7-4 του Α και το ψηφίο Ε να αποθηκεύεται στον καταχωρητή R0 Αν το περιεχόμενο του Α έχει τιμή από 99 (=63H) και κάτω όπως συμβαίνει στην Άσκηση 1 το ψηφίο Ε να παίρνει τιμή 0 και το περιεχόμενο του καταχωρητή R0 να αγνοείται

β) Γράψτε στη γλώσσα του 8051 ρουτίνα με ετικέτα DECΒΙΝ η οποία θα θεωρεί το περιεχόμενο του συσσωρευτή Α ως απροσήμαστον διψήφιο αριθμό του δεκαδικού συστήματος αρίθμησης σε κώδικα BCD με τιμή από 00 έως 99 στη μορφή ΔΜ όπου Δ είναι το ψηφίο των δεκάδων και Μ το ψηφίο των μονάδων και παίρνουν τιμές από 0=0000 μέχρι 9=1001 θα το μετατρέπει στο δυαδικό σύστημα αρίθμησης και θα αποθηκεύει το αποτέλεσμα ως νέο περιεχόμενο στον Α Αν το αρχικό περιεχόμενο του Α δεν είναι νόμιμος αριθμός του δεκαδικού συστήματος δηλ αν κάποιο από τα ψηφία Δ και Μ έχει τιμή πάνω από 1001=9 να αποθηκεύεται στον συσσωρευτή Α το byte FFH

Στην παραπάνω Άσκηση θα σας βοηθήσουν οι εντολές πολλαπλασιασμού (MUL) και διαίρεσης (DIV)

Λύση

α) Πρώτα θα διαιρέσουμε το περιεχόμενο του Α δια 100 για να λάβουμε το ψηφίο των εκατοντάδων Ε (πηλίκο της διαίρεσης) Το υπόλοιπο της διαίρεσης θα το διαιρέσουμε δια 10 για να λάβουμε το ψηφίο των δεκάδων (πηλίκο της διαίρεσης) και το ψηφίο των μονάδων (υπόλοιπο της διαίρεσης) Η ρουτίνα BINDEC ακολουθεί

BINDECPUSH BMOV B100 (ή 64H)DIV ABMOV R0AMOV ABMOV B0AHDIV ABSWAP A για να πάνε τα bits του ψηφίου των δεκάδων Δ στη ADD AB (ή ORL AB) σωστή τους θέσηPOP BRET

β) DECBINPUSH B

PUSH R1MOV BAσώζουμε το περιεχόμενο του Α στον ΒANL A11110000B αρχίζει ο έλεγχος αν το ψηφίο Δ είναι νόμιμοSWAP A

28

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29

Page 29: auto.teipir.grauto.teipir.gr/.../default/files/1i_seira_askiseon_8051_m… · Web viewΟι ασκήσεις μπορεί να φαίνονται δύσκολες αλλά δεν είναι

CLR CSUBB A0AHJNC FYGE αν είναι Δge10 φύγε και κάνε Α=FFHMOV ABANL A00001111B αρχίζει ο έλεγχος αν το ψηφίο των μονάδων Μ CLR C είναι νόμιμοSUBB A0AHJNC FYGE αν είναι Μge10 φύγε και κάνε Α=FFHMOV ABANL B00001111B ξεχωρίζουμε το ψηφίο των μονάδων ΜMOV R1BANL A11110000B ξεχωρίζουμε το ψηφίο των δεκάδων ΔSWAP A αυτό γίνεται για να γίνει το περιεχόμενο του Α ίσο με MOV B0AH Δ και όχι 16Δ που είναι τώραMUL AB δημιουργία του γινομένου 10ΔADD AR1 δημιουργία του 10Δ+Μ που είναι το αποτέλεσμαPOP R1POP BRET

FYGEMOV AFFHRET

29