Πρακτικός προγραμματισμός μικροελεγκτών Atmel AVR σε γλώσσα assembly. (3η έκδοση)

10.09.2021

Κάποτε είδα ένα ενδιαφέρον βίντεο στο Διαδίκτυο, έδειξε ένα παιχνίδι φιδιού που υλοποιήθηκε σε έναν μικροελεγκτή και μια μήτρα LED 8x8, και μετά βρήκα πολλά άλλα παρόμοια βίντεο που με ενδιέφεραν. Ανάμεσά τους υπήρχε και ένα βίντεο όπου το παιχνίδι Tetris συναρμολογήθηκε σε έναν «ισχυρό» μικροελεγκτή. Μετά την παρακολούθηση, αποφάσισα να αναπτύξω τη δική μου έκδοση της συσκευής, η οποία συνδυάζει και τα δύο παιχνίδια, χρησιμοποιώντας έναν μικροελεγκτή PIC16F688 και δύο πίνακες LED που εμφανίζουν τον αγωνιστικό χώρο με ανάλυση 8x16 pixel.

Το διάγραμμα της συσκευής φαίνεται παρακάτω. Οι πληροφορίες εξάγονται στους πίνακες H1, H2 σε δυναμική λειτουργία χρησιμοποιώντας μητρώα βάρδιας DD2, DD3, DD4. Οι έξοδοι των μικροκυκλωμάτων DD2, DD3 συνδέονται με τις ανόδους των μητρών. Οι κάθοδοι και των δύο μητρών συνδέονται με τους συλλέκτες των τρανζίστορ VT1-VT8, τα σήματα ελέγχου των οποίων παράγονται από το μικροκύκλωμα DD4. Ο μικροελεγκτής φορτώνει δεδομένα στον καταχωρητή DD4, όταν υπερχειλίζει, οι πληροφορίες από τον ακροδέκτη 9 μεταφέρονται στην είσοδο του καταχωρητή DD3 και, στη συνέχεια, με τον ίδιο τρόπο τα δεδομένα μεταφέρονται στον καταχωρητή DD2. Οι αντιστάσεις R1-R16 περιορίζουν το ρεύμα μέσω των LED της μήτρας. Οι αντιστάσεις R17-R23 ρυθμίζουν το ρεύμα βάσης των τρανζίστορ VT1-VT8. Ο μικροελεγκτής λειτουργεί στα 8 MHz από έναν εσωτερικό ταλαντωτή. Ο ρυθμός ανανέωσης της εικόνας είναι 100 Hz.


Μετά την ενεργοποίηση, η προφύλαξη οθόνης του παιχνιδιού "Snake" εμφανίζεται στον αγωνιστικό χώρο. Ο αριθμός 1 εμφανίζεται στην κορυφή του γηπέδου και στο κάτω μέρος υπάρχει μια εικόνα ενός τμήματος του παιχνιδιού. Όταν πατάτε το κουμπί "Έναρξη/Παύση" SB5, μεταβαίνετε στο μενού του παιχνιδιού, στο επάνω μέρος του οποίου εμφανίζεται το επίπεδο του παιχνιδιού με τη μορφή αριθμών από το 1 έως το 9. Το επίπεδο παιχνιδιού ρυθμίζεται από το SB1 "Up" κουμπί, με κάθε πάτημα ο αριθμός επιπέδου αυξάνεται διαδοχικά ανά μονάδα. Μετά τον αριθμό 9, εμφανίζεται ξανά ο αριθμός 1 Το αρχικό μήκος του φιδιού εξαρτάται από το καθορισμένο επίπεδο του παιχνιδιού, επομένως για το 1ο επίπεδο το μήκος είναι 3 πόντοι, για το 9ο επίπεδο 11 πόντοι. Στο κάτω μέρος του μενού, εμφανίζονται πληροφορίες σχετικά με την ταχύτητα της κίνησης του φιδιού. Ο αριθμός 1 αντιστοιχεί σε ελάχιστη ταχύτητα, και ο αριθμός 9 είναι ο μέγιστος. Η τιμή της ταχύτητας ορίζεται από το κουμπί SB4 "Down", παρόμοια με τη ρύθμιση του επιπέδου του παιχνιδιού. Η λάμψη των LED γύρω από την περίμετρο του γηπέδου στο μενού σημαίνει ότι έχει επιλεγεί η λειτουργία παιχνιδιού με την παρουσία ορίων γύρω από την περίμετρο του γηπέδου. Σε αυτήν τη λειτουργία, όταν το φίδι φεύγει από τον αγωνιστικό χώρο, εμφανίζεται απώλεια. Εάν στο μενού τα LED γύρω από την περίμετρο του πεδίου είναι σβηστά, τότε επιλέγεται η λειτουργία χωρίς όρια. Σε αυτή την περίπτωση, κατά την έξοδο από τον αγωνιστικό χώρο, το κεφάλι του φιδιού εμφανίζεται στην αντίθετη πλευρά του γηπέδου. Χρησιμοποιήστε τα κουμπιά SB2 «Δεξιά» και SB3 «Αριστερά» για να ρυθμίσετε την απαιτούμενη λειτουργία παιχνιδιού. Όταν μπείτε για πρώτη φορά στο μενού του παιχνιδιού, οι τιμές μήκους και ταχύτητας ορίζονται σε ένα και επιλέγεται η λειτουργία με όρια.

Αφού πατήσετε το κουμπί "Έναρξη/Παύση" από το μενού του παιχνιδιού, ένα φίδι στη βασική του θέση και ένα τυχαίο ελεύθερο σημείο εμφανίζονται στον αγωνιστικό χώρο. Το πάτημα οποιουδήποτε από τα κουμπιά "Επάνω", "Αριστερά", "Δεξιά" κάνει το φίδι να κινηθεί προς την αντίστοιχη κατεύθυνση. Αφού ξεκινήσει η κίνηση, το κουμπί «Κάτω» γίνεται επίσης διαθέσιμο για τον έλεγχο του φιδιού. Όταν χτυπάτε ένα φωτεινό σημείο, το μήκος του φιδιού αυξάνεται. Αφού συγκεντρώσετε 14 πόντους, περνάτε στο επόμενο επίπεδο του παιχνιδιού. Μετά το 9ο επίπεδο υπάρχει μετάβαση στο πρώτο επίπεδο. Εάν το φίδι χτυπήσει το σώμα του ή ξεπεράσει τον αγωνιστικό χώρο στη λειτουργία περιγράμματος, συμβαίνει απώλεια. Μετά από 3 ήττες, επιστρέφετε στο μενού του παιχνιδιού, όπου υποδεικνύονται το τρέχον επίπεδο και η ταχύτητα του παιχνιδιού. Αφού το φίδι αρχίσει να κινείται, μπορείτε να διακόψετε και να συνεχίσετε το παιχνίδι πατώντας τα κουμπιά "Έναρξη/Παύση".

Για να βγείτε από το μενού του παιχνιδιού, πρέπει να κρατήσετε πατημένο το κουμπί "Έναρξη/Παύση" για 1 δευτερόλεπτο και μετά θα εμφανιστεί η οθόνη εκκίνησης του παιχνιδιού στον αγωνιστικό χώρο. Η εναλλαγή μεταξύ των παιχνιδιών γίνεται πατώντας οποιοδήποτε από τα κουμπιά «Πάνω», «Κάτω», «Αριστερά», «Δεξιά». Ταυτόχρονα εμφανίζεται η οθόνη εκκίνησης του αντίστοιχου παιχνιδιού.

Στο επάνω μέρος της προφύλαξης οθόνης του παιχνιδιού Tetris εμφανίζεται ο αριθμός 2, στο κάτω μέρος υπάρχει μια εικόνα ενός τμήματος του παιχνιδιού. Μεταβείτε στο μενού του παιχνιδιού πατώντας το κουμπί "Έναρξη/Παύση". Ο αριθμός των πόντων που σημείωσε ο παίκτης εμφανίζεται στην κορυφή του μενού. Οι πόντοι απονέμονται για κάθε γραμμή που διαγράφεται. Ο μετρητής σημείων μετράει μέχρι το 99, στη συνέχεια μηδενίζεται και ξεκινά ξανά. Στην αρχή του καθενός νέο παιχνίδι, ο μετρητής μηδενίζεται επίσης. Στο κάτω μέρος του μενού, εμφανίζονται πληροφορίες σχετικά με την ταχύτητα κίνησης των φιγούρων, η οποία ρυθμίζεται χρησιμοποιώντας τα κουμπιά "Πάνω" και "Κάτω", αντίστοιχα. Αφού πατήσετε το κουμπί "Έναρξη/Παύση" από το μενού, το παιχνίδι ξεκινά, εμφανίζονται τυχαίες φιγούρες στην κορυφή του γηπέδου, οι οποίες μπορούν να μετακινηθούν με τα κουμπιά "Αριστερά" και "Δεξιά" προς την κατάλληλη κατεύθυνση. Το κουμπί Πάνω περιστρέφει το σχήμα κατά 90 μοίρες δεξιόστροφα κάθε φορά που το πατάτε. Κρατώντας πατημένο το κουμπί Down, μπορείτε να επιταχύνετε την κίνηση της φιγούρας. Το κουμπί "Έναρξη/Παύση" σάς επιτρέπει να κάνετε παύση και να συνεχίσετε το παιχνίδι. Το παιχνίδι τελειώνει όταν η νέα φιγούρα δεν μπορεί να χωρέσει στον αγωνιστικό χώρο και μετά πηγαίνει στο μενού όπου μπορείτε να δείτε τον αριθμό των πόντων που έχει σημειώσει ο παίκτης. Η έξοδος από το μενού πραγματοποιείται με τον ίδιο τρόπο όπως στο παιχνίδι "Snake".

Εάν δεν πατηθεί κανένα κουμπί μέσα σε 4 λεπτά, η συσκευή μεταβαίνει σε λειτουργία χαμηλής κατανάλωσης, ο μικροελεγκτής απενεργοποιεί τις συστοιχίες LED και μεταβαίνει σε κατάσταση αναστολής λειτουργίας. Η συσκευή «ξυπνάει» αφού πατήσει το κουμπί «Έναρξη» και επιστρέφει στην προηγούμενη κατάστασή της.

Η συσκευή χρησιμοποιεί αντιστάσεις – μεγέθους 1206 για επιφανειακή τοποθέτηση. Οι πυκνωτές C2, C3 είναι κεραμικοί, μεγέθους 1206. Πίνακες LED H1, H2 – TOM-1088BG-B πράσινο χρώμα με διάμετρο LED 3mm, και ανάλυση 8x8 pixel. Τα κουμπιά είναι τυπικά απτικά.

Η πηγή τροφοδοσίας είναι ένα σταθεροποιημένο τροφοδοτικό με τάση 3,7-5 V, μπορείτε επίσης να χρησιμοποιήσετε γαλβανικές κυψέλες ή μπαταρίες, για παράδειγμα 3 μπαταρίες 1,5 V AA ή AAA συνδεδεμένες σε σειρά, για παράδειγμα χρησιμοποιώ 3 μπαταρίες ΑΑ. Η συσκευή παραμένει σε λειτουργία όταν η τάση τροφοδοσίας μειωθεί στα 3,3 V, ενώ μειώνεται η φωτεινότητα των πινάκων LED.

Καλησπέρα σε όλους! Εκπέμπω από έναν φιλόξενο κόσμο που ονομάζεται "assembler". Θα διευκρινίσω αμέσως ότι το θέμα αφορά τους μικροελεγκτές AVR - και δεν ξέρω ακόμα αν αυτή η ανάρτηση θα είναι χρήσιμη σε όσους θέλουν να χρησιμοποιήσουν το assembler για οποιαδήποτε άλλη εργασία. Το γεγονός είναι ότι κυριολεκτικά πριν από λίγες μέρες άρχισα να μαθαίνω assembler από την αρχή - πρέπει να φτιάξω μια συσκευή - και αποφάσισα να κάνω τα πάντα σε αυτό μόνος μου. Έτσι, μια ωραία μέρα το κατάλαβα Η εκμάθηση του assembler είναι απολύτως άχρηστη!Η γλώσσα συναρμολόγησης γίνεται μόνο κατανοητή! Δηλαδή, σε όλους όσους θέλουν να προγραμματίσουν σε γλώσσα assembly, συνιστώ ανεπιφύλακτα να εμβαθύνουν λεπτομερώς στο πώς λειτουργεί ΦΥΣΙΚΑ ο μικροελεγκτής και μετά να μελετήσουν τις περιπλοκές των εντολών.
Λοιπόν, μάλλον θα ξεκινήσω μια μικρή σειρά άρθρων στην οποία θα σας πω από την αρχή πώς ακριβώςΚατάλαβα ορισμένα πράγματα στον προγραμματισμό της γλώσσας συναρμολόγησης - νομίζω ότι για όσους δεν καταλαβαίνουν καθόλου τι είναι το ASM, θα είμαι ακριβώς ένας τέτοιος "μεταφραστής" από τη γλώσσα όσων είναι πολύ καλοί σε αυτό το θέμα.

Θα πω αμέσως ότι λίγο-πολύ μπήκα σε αυτό το θέμα με την προτροπή του DIHALT - επομένως αυτά τα άρθρα θα είναι ένα είδος μετάφρασης από μια γλώσσα συναρμολόγησης-μικροελεγκτή super-duper σε μια γλώσσα κατανοητή στους περισσότερους ανθρώπους. Λοιπόν, ελπίζω οι γκουρού να με διορθώσουν καθώς προχωράει το έργο και αν ξαφνικά εξηγήσω κάτι λάθος, θα με διορθώσουν.
Έτσι, τα πρώτα συμπεράσματα για το assembler που έβγαλα πριν από μερικές μέρες με συγκλόνισαν -και κάθισα να διαβάζω άρθρα του DI DALT από τις 23:00 έως τις 5 το πρωί - μετά από τα οποία πήγα για ύπνο ικανοποιημένος και χαρούμενος Προγραμματισμός γλώσσας assembly για μικροελεγκτές.
Πώς μπορεί να εξηγηθεί αυτό ακόμα πιο απλά; Νομίζω ότι πρέπει να ξεκινήσουμε από την ίδια την ουσία.
***
Αρχικά, δεν θα μπούμε σε τεχνικές λεπτομέρειες (θα μιλήσουμε για αυτές στο επόμενο άρθρο) - απλώς φανταστείτε ότι υπάρχουν 3 χαρακτήρες:
1. Μικροελεγκτής -Αυτός είναι ο Άγγλος Στιβ, που ήρθε στο Ρώσο. Ξέρει τέλεια Αγγλική γλώσσα, αλλά δεν καταλαβαίνει καθόλου ρωσικά - ούτε μια λέξη. Αγγλικά μόνο. Έχασε το επιχείρημα και δεσμεύτηκε να κάνει ό,τι του ζητούσε ο Ρώσος χωρίς αμφιβολία.
2. Συναρμολογητής -Πρόκειται για τη μεταφράστρια Vasya, της οποίας η μητέρα είναι Αγγλίδα και ο πατέρας της Ρώσος. Γνωρίζει άριστα και αγγλικά και ρωσικά.
3. Εμείς -Αυτός είναι ένας Ρώσος στον οποίο έχει έρθει ένας Άγγλος. Λοιπόν, δηλαδή, είμαστε εμείς =) Ταυτόχρονα, ξέρουμε άριστα ρωσικά και (!!!) λίγα αγγλικά - λίγο, με λεξικό.
***
Φανταστείτε αυτή την κατάσταση - ένας Άγγλος κάθεται σε μια καρέκλα στο δωμάτιό σας. Και κάθεσαι στον υπολογιστή σου και διαβάζεις αυτή την ανάρτηση, όταν ξαφνικά άνοιξε το παράθυρό σου! Αυτό είναι κακή τύχη! Ο αέρας φυσάει, η κουρτίνα έχει γίνει πανί... Καλό θα ήταν να το κλείσουμε! Αλλά είναι πολύ τεμπέλης να σηκωθείς από την καρέκλα, να σηκώσεις τα πόδια σου από τη μονάδα συστήματος, να τα βάλεις σε παντόφλες, να αφήσεις κάτω την κούπα του καφέ σου (μπύρα) και να πας να πολεμήσεις τα στοιχεία. Και τότε ξαφνικά συνειδητοποιείς ότι έχουμε έναν Άγγλο στο δωμάτιο που έχει χάσει το στοίχημά του και ήρθε η ώρα να τον κυνηγήσουμε! Και του λες τόσο γλυκά: «Φίλε! Σε παρακαλώ, κλείσε το παράθυρο και μετά μπορείς να καθίσεις ξανά στην καρέκλα!». και κάθεται, σε κοιτάζει απορημένος και δεν κάνει τίποτα! Μπορείτε, φυσικά, να χτυπήσετε τη λαχανόσουπα - αλλά και πάλι δεν θα σας καταλάβει! Τότε καλείς τον φίλο σου τον μεταφραστή Βασίλι - έρχεται και κάθεται δίπλα στον Άγγλο σε μια καρέκλα. Και λες - Μετάφρασε: "Στιβ, πήγαινε και κλείσε το παράθυρο και μετά κάτσε στην καρέκλα!" Ο μεταφραστής μεταφράζει στα αγγλικά - ο Άγγλος καταλαβαίνει και πηγαίνει και κλείνει το παράθυρο και μετά έρχεται και κάθεται σε μια καρέκλα.
Σε αυτό το σημείο, πρέπει απλώς να κατανοήσετε τον ρόλο του assembler σε αυτήν την αλυσίδα "We-Assembler-Controller"
Δηλαδή πώς θα καταλάβαινε ο καθένας τι είναι assembler; Στη συνέχεια, διαβάστε.
***

Ας φανταστούμε λοιπόν αυτή την κατάσταση. Λέτε στη Βάσια - "Άκου, εν ολίγοις, αυτό είναι η περίπτωση - ξέχασα την αριθμομηχανή στο σπίτι, διαίρεσε το 56983 με το 2 και πες στον Στιβ να κάνει τόσα push-ups με τις γροθιές σου" και η Βάσια υπολογίζει στην αριθμομηχανή και λέει στον Στιβ στα αγγλικά «Κάνε push-ups με τις γροθιές σου 28491 φορές» Λέγεται "ΔΙΕΥΘΥΝΤΙΚΟΣ"- με άλλα λόγια, μια οδηγία είναι ένα καθήκον για τη Vasya, το αποτέλεσμα της οποίας είναι η δράση του Steve.

Υπάρχει μια άλλη κατάσταση - λέτε στον Vasya "Πες στον Steve να κάνει 28491 push-ups" και ο Vasya απλώς μεταφράζει τα λόγια σου στα αγγλικά. Λέγεται ΧΕΙΡΙΣΤΗΣ

Είναι απλό - υπάρχει οδηγία και υπάρχει χειριστής. Ο χειριστής είναι η άμεση οδηγία σας στον Steve τι να κάνει - η Vasya εδώ μεταφράζει το αίτημά σας μόνο στα αγγλικά. Και η Οδηγία είναι έργο για τον ίδιο τον Βάσια - και ο Βάσια κάνει πρώτα αυτό που του είπατε και μετά, ανάλογα με το αποτέλεσμα, λέει στον Στιβ κάτι.

Τώρα θα βασανίζουμε τακτικά τον Άγγλο! Πρώτα όμως πρέπει να γνωρίσουμε καλύτερα τον μεταφραστή μας Βάσια. Πρέπει να γνωρίζετε τα εξής - η Βάσια πάντα σας υπακούει αδιαμφισβήτητα - αυτό που του είπαν, το κάνει. Η αριθμομηχανή του Vasya δεν έχει δεκαδικά ψηφία - αν κοιτάξετε το παράδειγμα με push-ups, τότε 56983 \ 2 = 28491,5 - αλλά τα πάντα του Vasya μετά την αποκοπή της υποδιαστολής - και βλέπει μόνο έναν ακέραιο - και δεν πειράζει είτε θα υπάρχουν 28491.000001 είτε θα υπάρχουν 28491.9999999 - για τον Vasya αυτό είναι ένα μεγάλο θέμα θα είναι 28491 και στις δύο περιπτώσεις. Τίποτα δεν είναι στρογγυλεμένο. Περισσότερο σημαντικές πληροφορίεςγια τη Βάσια. Ο Βάσια είναι σκληρός - δεν τον νοιάζει το γεγονός ότι ο Στιβ γαμιέται να κάνει push-up είκοσι οκτώ χιλιάδες φορές. Του είπαν ότι η Βάσια μετέφρασε. Και όχι μόνο μετέφρασε, αλλά και με ανάγκασε να κάνω αυτό που ζητήσατε. Έτσι, αν ο Steve πεθάνει στο εικοσιτρείς χιλιάδες πεντακόσια δέκατα τρία push-up, θα είναι αποκλειστικά δικό σου λάθος.

Στην πραγματικότητα, αυτό είναι όλο προς το παρόν. Στην επόμενη ανάρτηση θα εμβαθύνουμε - προς το παρόν αρκεί να το καταλάβουμε. Απλώς φανταστείτε αυτήν την κατάσταση και καταλάβετε τι είναι τι, ποιος παίζει τι ρόλο και πώς διαφέρει η οδηγία από τον χειριστή.
Και μετά θα προσπαθήσουμε να ονομάσουμε τα πάντα με το σωστό τους όνομα και να υπολογίσουμε χονδρικά πώς λειτουργεί ο assembler με έναν μικροελεγκτή όπως ένας ενήλικας.


Ελπίζω λοιπόν ο ευσυνείδητος αναγνώστης να έχει ήδη συναρμολογήσει έναν προγραμματιστή, έναν πειραματικό πίνακα και επίσης να έχει εγκαταστήσει και να ρυθμίσει το απαιτούμενο λογισμικό.

Τώρα, έχοντας γράψει το πρώτο άρθρο της σειράς, καταλαβαίνω ότι ενθουσιάστηκα λίγο και έκανα το ίδιο λάθος με τους προκατόχους μου, βάζοντας τη φράση «για αρχάριους». Θα ήταν πιο ακριβές να διατυπωθεί το θέμα "Για αρχάριους στον προγραμματισμό γλώσσας συναρμολόγησης", δηλαδή, υποθέτω ότι ο αναγνώστης έχει ήδη μια τουλάχιστον επιφανειακή κατανόηση του τι είναι ένας μικροελεγκτής, διαφορετικά θα μας πάρει πολύ χρόνο για να εξοικειωθείτε με αυτό το θέμα. Για όσους δεν είναι καθόλου εξοικειωμένοι με αυτά, μπορώ να προτείνω μια απολύτως υπέροχη σειρά άρθρων του S. Ryumik, κατά τη γνώμη μου " Μικροελεγκτές AVR», δημοσιεύτηκε στο περιοδικό Radioamator (Nos. 1-11 για το 2005). Σε αυτόν τον κύκλο, ο ATmega8 επιλέχθηκε ως βασικός ελεγκτής, αλλά γενικά λειτουργικές μονάδεςΟ παραπάνω ελεγκτής και το ATtiny13 είναι πρακτικά το ίδιο.

Για να εξοικειωθείτε άμεσα με τον μικροελεγκτή ATtiny13, προτείνω το βιβλίο της A.V. Evstifeev "Μικροελεγκτές AVR της μικροσκοπικής οικογένειας. Εγχειρίδιο χρήστη" (Μ.: Εκδοτικός οίκος "Dodeka-XXI", 2007. - 432 σελ.). Περιέχει μεταφρασμένα και συστηματοποιημένα φύλλα δεδομένων για όλη τη γκάμα ελεγκτών της μικροσκοπικής οικογένειας και, κατά τη γνώμη μου, θα πρέπει να αποτελεί αναφορά στην επιφάνεια εργασίας για όσους ασχολούνται με τον προγραμματισμό μικροελεγκτών.

Ωστόσο, καθώς προχωρά η ιστορία, θα δώσω κάποιες πληροφορίες σχετικά με τους κόμβους και τις μονάδες του ελεγκτή που θα χρησιμοποιηθούν στα γραπτά προγράμματα.

Όλα αυτά όμως είναι μια λυρική παρέκβαση. Ας επιστρέψουμε κατευθείαν στην ιστορία.

Το χειριστήριο ATtiny13, παρά το μικρό του μέγεθος, έχει πολύ καλά λειτουργικά χαρακτηριστικά. Και ο μικρός αριθμός των ακίδων αντισταθμίζεται περισσότερο από τον αριθμό των λειτουργιών που εκτελεί το καθένα από αυτά. Το pinout και η περιγραφή των pins παρουσιάζονται παρακάτω:

Ο πίνακας προέρχεται από το προαναφερθέν βιβλίο του A.V. Evstifeeva.

Όπως μπορείτε να δείτε, κάθε pin μπορεί να εκτελέσει τουλάχιστον τρεις λειτουργίες ή ακόμα και πολλές περισσότερες. Αρχικά δεν θα εξετάσουμε εναλλακτικές λειτουργίες, αλλά μόνο τη βασική - ψηφιακή είσοδο/έξοδο.

Όπως φαίνεται από το σχήμα και τον πίνακα, όλοι οι ακροδέκτες, με εξαίρεση τους ακροδέκτες ισχύος, έχουν το όνομα PB ακολουθούμενο από έναν σειριακό αριθμό. Τι σημαίνει αυτό; Όλες οι ακίδες του ελεγκτή συνδυάζονται σε 8 κομμάτια για ευκολία στην εργασία μαζί τους και σε κάθε ομάδα 8 ακίδων εκχωρούνται τρεις ειδικοί καταχωρητές I/O. Γενικά, η έννοια των καταχωρητών είναι βασική όταν εργάζεστε με ελεγκτές, ειδικά σε assembler. Ας ρίξουμε μια πιο προσεκτική ματιά σε καθένα από τα τρία προαναφερθέντα μητρώα. Όλα είναι κελιά ενός byte στη μνήμη του ελεγκτή. Κάθε bit αντιστοιχεί σε μία από τις εξόδους του ελεγκτή και ο αριθμός bit στον καταχωρητή συμπίπτει με τον αριθμό εξόδου (για παράδειγμα, το 0ο bit είναι υπεύθυνο για την έξοδο PB0, το 1ο bit είναι υπεύθυνο για την έξοδο PB1, κ.λπ.). Όλοι οι καταχωρητές έχουν το δικό τους όνομα, με το οποίο γίνεται πρόσβαση κατά τη σύνταξη προγραμμάτων. Τι είδους ονόματα είναι αυτά;

1. Ο καταχωρητής DDRB είναι υπεύθυνος για την κατεύθυνση μετάδοσης πληροφοριών κάθε ακίδας ελεγκτή. Εάν οποιοδήποτε bit αυτού του καταχωρητή είναι "0", τότε η αντίστοιχη έξοδος θα είναι είσοδος και εάν "1", τότε η έξοδος. Επιπλέον, κάθε έξοδος διαμορφώνεται μεμονωμένα και οπουδήποτε στο πρόγραμμα. Αυτό σημαίνει ότι κάτω από διαφορετικές συνθήκες ή σε διαφορετικούς χρόνους, η ίδια ακίδα μπορεί να διαμορφωθεί ως είσοδος ή ως έξοδος, ανεξάρτητα από τις άλλες ακίδες.

2. Ο καταχωρητής PINB περιέχει την τρέχουσα κατάσταση όλων των ακίδων: εάν εφαρμόζεται τάση στον ακροδέκτη, τότε γράφεται ένα λογικό "1" στο αντίστοιχο bit, εάν δεν υπάρχει τάση, γράφεται ένα λογικό "0". Αυτός ο καταχωρητής χρησιμοποιείται κυρίως για την ανάγνωση της κατάστασης μιας ακίδας που βρίσκεται σε λειτουργία εισαγωγής.

3. Ο καταχωρητής PORTB εκτελεί διπλή λειτουργία ανάλογα με την κατεύθυνση μεταφοράς πληροφοριών. Εάν ο ακροδέκτης λειτουργεί ως ψηφιακή έξοδος, τότε η εγγραφή ενός «1» σε οποιοδήποτε bit του καταχωρητή PORTB προκαλεί την εμφάνιση τάσης στον αντίστοιχο ακροδέκτη και η γραφή «0» προκαλεί την εξαφάνιση της τάσης. Έτσι, στη λειτουργία εξόδου, αυτός ο καταχωρητής είναι που καθορίζει την κατάσταση κάθε ακίδας. Στη λειτουργία ψηφιακής εισόδου, η εγγραφή ενός λογικού "1" σε οποιοδήποτε bit προκαλεί τη σύνδεση της ενσωματωμένης αντίστασης έλξης στην αντίστοιχη ακίδα και την εγγραφή ενός "0" για την απενεργοποίησή της. Τι είδους είναι αυτή η "αντίσταση έλξης" και για ποιο σκοπό προορίζεται; Εάν η ακίδα λειτουργεί ως ψηφιακή είσοδος, τότε η αντίσταση του buffer εισόδου είναι αρκετά υψηλή και το ρεύμα εισόδου είναι αρκετά μικρό. Επομένως, οποιαδήποτε ηλεκτρική παρεμβολή μπορεί να οδηγήσει σε αυθόρμητη αλλαγή της εξόδου σε αυθαίρετη κατάσταση. Για να αποφευχθεί αυτό, μια αντίσταση με αντίσταση πολλών δεκάδων kilo-ohms συνδέεται μεταξύ της εισόδου και της πηγής ρεύματος, «ανεβάζοντας» το δυναμικό εισόδου στην τάση τροφοδοσίας (εξ ου και το όνομα). Το ρεύμα που ρέει μέσω αυτής της αντίστασης είναι αρκετά μικρό ώστε να μην παρεμβαίνει στο υπόλοιπο κύκλωμα, αλλά αρκετά μεγάλο για να αποτρέπει την τυχαία εναλλαγή πείρων. Συχνά θα χρησιμοποιούμε αντιστάσεις έλξης όταν εργαζόμαστε με κουμπιά, γιατί όταν δεν πιέζονται, οι ακίδες με τις οποίες συνδέονται ουσιαστικά «κρέμονται» στον αέρα και υπόκεινται σε παρεμβολές.

Πρέπει να αναφερθεί ότι κατά την ενεργοποίηση όλοι οι καταχωρητές επαναφέρονται στο 0 και κάθε ακροδέκτης λειτουργεί ως ψηφιακή είσοδος χωρίς αντίσταση έλξης.

Τώρα που έχουμε τουλάχιστον κάποια ιδέα για το ΤΙ χρειάζεται για να δουλέψουμε με εισόδους ελεγκτή, ήρθε η ώρα να μάθουμε ΠΩΣ να εργάζεστε μαζί τους.

Ας γράψουμε το πρώτο μας πρόγραμμα εργασίαςσε συναρμολογητή. Πρώτα θα δώσω πλήρης αλγόριθμοςδημιουργώντας ένα νέο έργο, στο μέλλον θα το παραλείψω, εστιάζοντας μόνο στο κείμενο του ίδιου του προγράμματος.

1. Μεταβείτε στο φάκελο asm και δημιουργήστε έναν νέο φάκελο σε αυτόν. Μετονομάστε το σε ένα όνομα που μας ταιριάζει. Για να γίνω συγκεκριμένος, θα αναφερθώ σε αυτούς με τον αριθμό βήματος μας. Σε αυτή την περίπτωση "βήμα 2".

2. Κάντε δεξί κλικ στο αρχείο build.bat και αλλάξτε τη διαδρομή προς το αρχείο προέλευσης, δείχνοντας τον φάκελο που δημιουργήθηκε πρόσφατα (βήμα 2). Μετά από αυτό το περιεχόμενό μου μοιάζει με αυτό:

"F:\Prog\AVR\asm\avrasm32 -fI %F:\Prog\AVR\asm\step2\main.asm
παύση"

Μπορεί να διαφέρει για εσάς ανάλογα με το πού αποσυσκευάσατε το αρχείο.

3. Μεταβείτε στο φάκελο Asmedit και εκτελέστε το πρόγραμμα ASM_Ed.exe

4. Στο παράθυρο που ανοίγει, γράψτε το κείμενο του προγράμματος. Θα σταθώ σε αυτό το σημείο πιο αναλυτικά, αφού είναι το κύριο στο σημερινό μας μάθημα, καθώς και στα επόμενα.

Τι είναι το κείμενο ενός προγράμματος assembler; Μπορεί να περιλαμβάνει πολλά στοιχεία γραμμένα σύμφωνα με ορισμένους κανόνες:

Οδηγίες συναρμολόγησης με ή χωρίς τελεστές ανάλογα με τη σύνταξη των εντολών. Ανάμεσα στο όνομα της εντολής και στον πρώτο τελεστή πρέπει να υπάρχει είτε ένα κενό, ένα tab ή οποιοσδήποτε αριθμός και των δύο. Οι τελεστές χωρίζονται με κόμμα, το οποίο μπορεί επίσης να προηγείται ή να ακολουθείται από έναν αυθαίρετο αριθμό διαστημάτων ή καρτελών.

Οδηγίες, καθεμία από τις οποίες αρχίζει με ".".

Ετικέτες, οι οποίες είναι θέσεις στο πρόγραμμα που ονομάζονται αυθαίρετα από τον χρήστη και στις οποίες μπορεί να χρειαστεί να πλοηγηθεί. Κάθε ετικέτα τελειώνει με έναν χαρακτήρα ":";

Σχόλια που ξεκινούν με ";". Όλο το κείμενο από την αρχή του σχολίου έως το τέλος της γραμμής αγνοείται κατά τη δημιουργία του αρχείου hex και μπορεί να είναι εντελώς αυθαίρετο.

Κενές γραμμές για καλύτερη δομή και αναγνωσιμότητα του προγράμματος.

Δεν μπορεί να υπάρχουν περισσότερες από μία εντολές σε κάθε γραμμή. Ωστόσο, επιτρέπεται η ταυτόχρονη παρουσία μιας ετικέτας σε μια γραμμή ακολουθούμενη από μια εντολή και ένα σχόλιο.

Χρησιμοποιώντας αυτούς τους κανόνες, θα γράψουμε ένα πρόγραμμα που θα ανάψει το LED2 ενώ το κουμπί SB1 είναι πατημένο και θα το απενεργοποιήσουμε εάν το κουμπί αφεθεί. Το κείμενο του προγράμματος παρουσιάζεται παρακάτω:

.συμπεριλάβετε "F:\Prog\AVR\asm\Appnotes\tn13def.inc"
sbi DDRB, 4 ;РВ4 - έξοδος (LED2)
sbi PORTB, 2 Ενεργοποιήστε την αντίσταση έλξης στο PB2 (κουμπί SB1)
sbic PINB, 2 ;Εάν PB2=0 (πατήθηκε το κουμπί), παραλείψτε το επόμενο. γραμμή
sbi PORTB, 4 ;Εγκατάσταση PB4 σε 1 (σβήσιμο του LED)
sbis PINB, 2 ;Εάν PB2=1 (το κουμπί απελευθερώθηκε), παραλείψτε το επόμενο. γραμμή
cbi PORTB, 4 ;Ρύθμιση PB4 σε 0 (LED αναμμένη)

Ας το δούμε πιο αναλυτικά. Η πρώτη γραμμή περιέχει την οδηγία "συμπεριλάβετε", γραμμένη σύμφωνα με τους παραπάνω κανόνες με μια τελεία στην αρχή. Σκοπός του είναι να συμπεριλάβει το αρχείο που καθορίζεται πίσω από αυτό στο κείμενο του προγράμματος. Όπως είπα στο πρώτο βήμα, θα χρειαστούμε το αρχείο "tn13def.inc". Σε αυτή τη γραμμή, θα χρειαστεί να αλλάξετε τη διαδρομή προς τη θέση του φακέλου Appnotes στον υπολογιστή σας. Γιατί πρέπει να συμπεριλάβουμε αυτό το αρχείο; Ένας περίεργος αναγνώστης μπορεί να το ψάξει και να διαβάσει το περιεχόμενό του, αλλά πιθανότατα θα καταλάβει ελάχιστα από αυτό στην αρχή. Προς το παρόν, θα πω ότι περιέχει μια αντιστοιχία μεταξύ των ονομάτων των καταχωρητών, τα οποία ο assembler δεν γνωρίζει από προεπιλογή, με τις φυσικές τους διευθύνσεις στον ελεγκτή.

Οι ακόλουθες γραμμές είναι εντολές assembler. Ο προσεκτικός αναγνώστης θα παρατηρήσει ότι χρησιμοποιούνται συνολικά τέσσερις διαφορετικές εντολές. Ας δούμε τον σκοπό του καθενός.

Η εντολή sbi έχει δύο τελεστές: ο πρώτος είναι το όνομα καταχωρητή και ο δεύτερος ο αριθμός bit. Ως αποτέλεσμα της εκτέλεσής του, το καθορισμένο bit στον καθορισμένο καταχωρητή ορίζεται σε "1".

Η εντολή cbi είναι παρόμοια σε σύνταξη με την παραπάνω και εκτελεί την ακριβώς αντίθετη λειτουργία - επαναφέρει το καθορισμένο bit στον καθορισμένο καταχωρητή στο "0".

Η εντολή sbis είναι επίσης παρόμοια σε σύνταξη με την παραπάνω. Ωστόσο, σε αντίθεση με αυτούς, δεν εκτελεί καμία λειτουργία με καταχωρητές, αλλά ελέγχει μόνο την κατάσταση του καθορισμένου bit στον καθορισμένο καταχωρητή και εάν είναι ίσο με "1", παρακάμπτει τη γραμμή που ακολουθεί την εντολή. Διαφορετικά, εκτελείται η γραμμή που ακολουθεί, όπως και όλες οι άλλες μετά από αυτήν.

Η εντολή sbiс είναι το αντίθετο της εντολής sbis. Παραλείπει την επόμενη γραμμή εάν το καθορισμένο bit καταχωρητή είναι "0".

Τώρα, συνοψίζοντας όλα τα παραπάνω, ας προσπαθήσουμε να κατανοήσουμε τον αλγόριθμο του προγράμματος. Για να ξεκινήσω, θα το κάνω αυτό κυριολεκτικά γραμμή προς γραμμή.

1 γραμμή. Η οδηγία περιλαμβάνει το αρχείο tn13def.inc, το οποίο περιέχει ορισμούς καταχωρητών.

2η γραμμή. Η εντολή sbi θέτει το "1" στο bit 4 του καταχωρητή DDRB, μεταβάλλοντας έτσι τον ακροδέκτη PB4 στην έξοδο. Αν κοιτάξετε το διάγραμμα της πλακέτας (Εικ. 1 του προηγούμενου βήματος), μπορείτε να δείτε ότι το LED2 είναι συνδεδεμένο σε αυτόν τον ακροδέκτη. Μετά την εντολή και το σύμβολο ";" έχει γραφτεί ένα σχόλιο που εξηγεί εν συντομία το νόημα των ενεργειών που εκτελούνται στη γραμμή.

3 γραμμή. Η ίδια εντολή sbi θέτει το "1" στο bit 2 του καταχωρητή PORTB, συνδέοντας την εσωτερική αντίσταση έλξης στον ακροδέκτη PB2, στον οποίο είναι συνδεδεμένο το κουμπί SB1. Εφόσον δεν αλλάξαμε την κατάσταση του bit 2 του καταχωρητή DDRB, αυτή η ακίδα θα παραμείνει ως είσοδος, κάτι που πραγματικά χρειαζόμαστε.

4 γραμμή. Η εντολή sbic ελέγχει την παρουσία ενός λογικού "0" στην είσοδο PB2 χρησιμοποιώντας τον καταχωρητή PINB. Αν κοιτάξετε προσεκτικά το διάγραμμα, μπορείτε να δείτε ότι τα κουμπιά, όταν πατηθούν, κλείνουν τον αντίστοιχο ακροδέκτη με το κοινό καλώδιο. Αυτή είναι μια τυπική τεχνική, καθώς όταν απελευθερώνεται το κουμπί, υπάρχει ένα λογικό "1" στην έξοδο λόγω της αντίστασης έλξης και όταν πατηθεί το κουμπί, εμφανίζεται ένα λογικό "0" λόγω της σύνδεσης του έξοδο προς κοινό σύρμα. Έτσι, εάν υπάρχει ένα λογικό «0» στον ακροδέκτη PB2, δηλαδή πατηθεί το κουμπί, παραλείπουμε την επόμενη γραμμή και εάν το κουμπί απελευθερωθεί, τότε το εκτελούμε.

5 γραμμή. Σε αυτό, η εντολή sbi ορίζει ένα λογικό "1" στο bit 4 του καταχωρητή PORTB, απενεργοποιώντας έτσι το LED2. Ένας οξυδερκής αναγνώστης μπορεί να αναρωτηθεί γιατί το LED σβήνει αν εφαρμόσουμε τάση στην έξοδο. Η απάντηση βρίσκεται στο σχέδιο. Το LED συνδέεται με την άνοδο στο καλώδιο τροφοδοσίας και η κάθοδος στην έξοδο του ελεγκτή. Επομένως, εάν εφαρμόσετε τάση στην έξοδο, τα δυναμικά της ανόδου και της καθόδου θα είναι ίσα και το LED θα σβήσει. Εάν ένα λογικό "0" εξέρχεται στην έξοδο, τότε θα εφαρμοστεί τάση στο LED και θα ανάψει. Έτσι, ένα ζεύγος γραμμών 4 και 5 σβήνει το LED2 όταν απελευθερωθεί το κουμπί.

6 γραμμή. Το νόημα είναι αντίθετο με το 4ο. Η εντολή sbis ελέγχει την παρουσία ενός λογικού «1» στην είσοδο PB2, δηλαδή ελέγχει εάν το κουμπί έχει απελευθερωθεί. Εάν το κουμπί απελευθερωθεί, η επόμενη γραμμή παραλείπεται και η επόμενη γραμμή πηγαίνει στην επόμενη. Επειδή όμως η 7η γραμμή είναι η τελευταία, υπάρχει μετάβαση στη 2η γραμμή. Εάν πατηθεί το κουμπί, τότε εκτελείται η γραμμή 7.

7 γραμμή. Απέναντι από το 5ο. Η εντολή cbi επαναφέρει το bit 4 του καταχωρητή PORTB στο "0", ενεργοποιώντας έτσι το LED2. Έτσι, ένα ζεύγος γραμμών 6 και 7 ανάβει το LED2 όταν πατηθεί το κουμπί SB1.

Όπως μπορείτε να δείτε, δεν κάναμε κάτι ιδιαίτερα δύσκολο. Χρησιμοποιώντας γνώση μόνο 3 καταχωρητών και 4 οδηγιών, γράψαμε το πρώτο μας πρόγραμμα. Τι να την κάνεις μετά; Αν δεν το έχετε ξεχάσει ακόμα, συνεχίζουμε να γράφουμε τον αλγόριθμο δημιουργίας προγράμματος.

5. Έχοντας γράψει το κείμενο του προγράμματος στο παράθυρο του προγράμματος επεξεργασίας, επιλέξτε το στοιχείο μενού «Αρχείο» και στη λίστα που ανοίγει, κάντε κλικ στο «Αποθήκευση ως...». Στο παράθυρο αποθήκευσης αρχείων, επιλέξτε το φάκελο step2 που δημιουργήσαμε και καθορίστε το όνομα αρχείου "main", καθώς αυτό είναι το όνομα που καθορίσαμε στο αρχείο "build.bat".

Μετά την αποθήκευση, το παράθυρο του προγράμματος θα πρέπει να μοιάζει με αυτό:

6. Δημιουργήστε ένα αρχείο hex. Για να το κάνετε αυτό, κάντε κλικ στο κουμπί "II" στη γραμμή εργαλείων. Θα πρέπει να εμφανιστεί το ακόλουθο παράθυρο:

Μας ειδοποιεί ότι η συναρμολόγηση ολοκληρώθηκε χωρίς σφάλματα και δημιουργήθηκε το αρχείο firmware “main.hex” με όγκο 6 λέξεων, δηλαδή 12 byte. Σημειώνω ότι ένα παρόμοιο πρόγραμμα στο C θα είχε τουλάχιστον 5πλάσιο όγκο.

7. Έχοντας μεταβεί στο φάκελο step2, βρίσκουμε μια προσθήκη σε αυτόν με τη μορφή ενός νέου αρχείου main.hex, το οποίο μπορεί τώρα να ραφτεί στον ελεγκτή με οποιονδήποτε προγραμματιστή, κάτι που πρέπει να γίνει για να δείτε τα αποτελέσματα του το πρόγραμμα που γράψαμε. Αφού αναβοσβήνει ο ελεγκτής, εάν το κύκλωμα έχει συναρμολογηθεί σωστά, όλα θα πρέπει να λειτουργούν σύμφωνα με τον αλγόριθμο που αναπτύξαμε: όταν απελευθερωθούν τα κουμπιά, το LED2 θα πρέπει να είναι σβηστό και ενώ το κουμπί SB1 είναι πατημένο, θα πρέπει να είναι αναμμένο.

Πριν από το επόμενο βήμα, σας προτείνω να κάνετε τις ακόλουθες εργασίες:

1. Προσθέστε στην επεξεργασία του προγράμματος το πάτημα του κουμπιού SB2 με τον αντίθετο αλγόριθμο: όταν απελευθερωθεί το κουμπί SB2, το LED1 θα πρέπει να ανάβει και όταν πατηθεί, θα πρέπει να είναι σβηστό.

2. Γράψτε ένα πρόγραμμα για τον έλεγχο του LED2 χρησιμοποιώντας και τα δύο κουμπιά. Όταν πατηθεί το κουμπί SB1, το LED θα πρέπει να ανάβει και να παραμένει αναμμένο μέχρι να πατηθεί το κουμπί SB2, το οποίο το σβήνει μέχρι το επόμενο πάτημα του SB1.

Ένας κλώνος του διάσημου Tetris, γραμμένος σε γλώσσα assembly. Ταιριάζει εξ ολοκλήρου στον τομέα εκκίνησης των 512 byte (απαιτεί μόνο 446 byte χώρου, που είναι ακριβώς το μέγιστο μέγεθος του bootloader στο MBR).

Το MBR είναι μια ενότητα που περιέχει τον κώδικα και τα δεδομένα που είναι απαραίτητα για την επακόλουθη φόρτωση του λειτουργικού συστήματος και βρίσκεται στους πρώτους φυσικούς τομείς. Τα πρώτα 446 byte του δίσκου δίνονται στον κώδικα του bootloader. Σε αυτό το μέρος είναι γραμμένο το TetrOS.

Φυσικά, λόγω τέτοιων ιδιοτήτων, φορτώνεται πριν από οποιαδήποτε λειτουργικό σύστημα- δεν απαιτεί κανένα λειτουργικό σύστημα, λειτουργεί μόνο του. Ναι, ναι, καλά ακούσατε, το TetrOS είναι το δικό του bootloader.

Έτσι φαίνεται στην οθόνη:

Και ο πηγαίος κώδικας στον τομέα εκκίνησης μοιάζει με αυτό:

Και ναι είναι όλοιπηγή. Θυμάστε ότι ζυγίζει μόνο 446 byte;

Μπορείτε να εκτελέσετε αυτό το «θαυματουργό λειτουργικό σύστημα» κάτω από το qemu ή ακόμα και να το εγκαταστήσετε πραγματικά στο διαμέρισμα εκκίνησης ενός δίσκου ή μιας μονάδας flash.

Εκτόξευση

Απλώς εγκαταστήστε το qemu:

sudo apt-get install qemu

και τρέξε:

Φόρτωση σε μονάδα flash USB

Αντιγράψτε την εικόνα σε μια μονάδα flash. Ας υποθέσουμε ότι εάν η μονάδα flash είναι προσαρτημένη ως /dev/sde, θα χρειαστεί να εκτελέσετε την ακόλουθη εντολή για να γράψετε στον τομέα εκκίνησης TetrOS:

sudo dd if=tetros.img of=/dev/sde

Περιγραφή παιχνιδιού

Ο προγραμματιστής κατάφερε να στριμώξει ένα όχι και τόσο βαρετό σχέδιο σε μόλις 512 byte μνήμης. Κάθε τούβλο στο παιχνίδι έχει το δικό του χρώμα, ελέγχεται από κουμπιά, σε περίπτωση ήττας το παιχνίδι τελειώνει, τα τουβλάκια δημιουργούνται τυχαία... Το BolgenOS δεν ήταν καν κοντά!

Δυστυχώς, λόγω του μεγέθους, ορισμένα χαρακτηριστικά έπρεπε να εγκαταλειφθούν. Το παιχνίδι δεν έχει βαθμολογία, επανεκκινήστε το παιχνίδι χωρίς επανεκκίνηση ή εμφανίστε ποιο θα είναι το επόμενο τούβλο.