Πληκτρολόγιο Matrix με οκτώ κουμπιά. Σύνδεση πληκτρολογίου matrix σε μικροελεγκτές AVR

10.09.2021

Ήρθε η ώρα να σας πούμε πώς να οργανώσετε μια έρευνα για ένα τέτοιο πληκτρολόγιο. Να σας υπενθυμίσω ότι το πληκτρολόγιο αποτελείται από σειρές που κρέμονται σε θύρες και στήλες που σαρώνονται από άλλη θύρα. Ο κωδικός είναι γραμμένος για τον ελεγκτή ATMega8535, αλλά λόγω του γεγονότος ότι τα πάντα καθορίζονται εκεί με τη μορφή μακροεντολών, μπορεί να μεταφερθεί γρήγορα σε οποιονδήποτε άλλο ελεγκτή κλάσης Mega, καθώς και για τα πιο σύγχρονα Μικροσκοπικός. Αν και στην περίπτωση του ΜικροσκοπικόςΜπορεί να υπάρχουν κάποιες δυσλειτουργίες λόγω του ελλιπούς συνόλου εντολών τους. Θα πρέπει να το τροποποιήσετε λίγο με ένα αρχείο.

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

Τώρα εν συντομία για τα αρχεία:
keyboard_define.inc— αρχείο διαμόρφωσης πληκτρολογίου.
Αυτό το αρχείο αποθηκεύει όλους τους ορισμούς μακροεντολών που χρησιμοποιούνται από το πληκτρολόγιο. Εδώ ορίζουμε ποιες ακίδες του μικροελεγκτή συνδέονται σε ποια γραμμή. Μία λεπτότητα - έξοδοι σε στήλες ( θύρα σάρωσης) πρέπει να είναι ένα διαδοχικό σύνολο γραμμών μιας θύρας. Δηλαδή, για παράδειγμα, τα πόδια 0,1,2,3 ή 4,5,6,7 , ή 3,4,5,6 . Δεν έχει σημασία ποιο λιμάνι, το κύριο πράγμα είναι ότι είναι συνεπές.
Νομίζω ότι δεν θα υπάρξουν προβλήματα με την αναγνώριση των ποδιών, αλλά όσον αφορά την παράμετρο ΜΑΣΚΑ ΚΛΕΙΔΙΟΥΘέλω να σας πω κάτι ιδιαίτερο.
Αυτή είναι η μάσκα με την οποία θα αναγνωριστεί η σαρωμένη θύρα. Θα πρέπει να περιέχει 6 μονάδες και ένα 0. Το μηδέν έχει οριστεί στην άκρα δεξιά θέση της θύρας σάρωσης.

Παράδειγμα:
Η θύρα σάρωσης μου κρέμεται στα bit 7,6,5,4, το δεξιό bit της θύρας σάρωσης είναι το bit 4, επομένως η μάσκα είναι 0b11101111 - το μηδέν βρίσκεται στην 4η θέση. Εάν οι γραμμές σάρωσης κρέμονται στα πόδια 5,4,3,2, τότε η μάσκα θα είναι ήδη 0b11111011 - μηδέν στη δεύτερη θέση. Το γιατί όλα αυτά θα εξηγηθεί παρακάτω.

Υπάρχει επίσης μια μάσκα ενεργών γραμμών της θύρας σάρωσης - SCANMSK. Σε αυτό, οι μονάδες στέκονται μόνο απέναντι από τις γραμμές των στηλών. Οι στήλες μου έχουν οριστεί στο πιο σημαντικό τετράδιο της θύρας, έτσι η μάσκα σάρωσης μοιάζει 0b11110000.

Στην ενότητα προετοιμασίας, πρέπει να θυμάστε να διαμορφώσετε τα σκέλη της θύρας σάρωσης για έξοδο και τα σκέλη της συσκευής ανάγνωσης για είσοδο με ένα pull-up. Στη συνέχεια, εισαγάγετε τον κώδικα χειρισμού πληκτρολογίου κάπου με τη μορφή μιας κανονικής υπορουτίνας. Είναι εύκολο στη χρήση - καλούμε την υπορουτίνα για ανάγνωση από το πληκτρολόγιο και όταν επιστρέψουμε, έχουμε έναν κωδικό σάρωσης του κλειδιού στον καταχωρητή R16.

Αυτός ήταν ο κωδικός δοκιμής μου:

Κύριο:SEI ; Ενεργοποίηση διακοπών.

RCALL KeyScan ; Σάρωση του πληκτρολογίου
CPI R16.0; Εάν επιστραφεί το 0, σημαίνει ότι δεν έγινε πάτημα
BREQ Main ; Σε αυτή την περίπτωση, πηγαίνετε στην αρχή
RCALL CodeGen ; Εάν επιστραφεί ο κωδικός σάρωσης, τότε τον μεταφέρουμε στο
; Κωδικός ASCII.

MOV R17,R16; Φόρτωση στο μητρώο λήψης του χειριστή LCD
RCALL DATA_WR ; Το εμφανίζουμε στην οθόνη.

RJMP Main ; Ας τα διορθώσουμε όλα.

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

Τώρα θα σας πω πώς λειτουργεί Διαδικασία KeyScan

Def COUNT = R18
KeyScan: LDI COUNT,4 ; Ας σαρώσουμε 4 στήλες
LDI R16, ΜΑΣΚΑ ΚΛΕΙΔΙ ; Τοποθετήστε τη μάσκα στη σάρωση της στήλης 0.

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

KeyLoop: IN R17,COL_PORT ; Παίρνουμε την προηγούμενη τιμή από το λιμάνι
ORI R17,SCANMSK ; Ορίσαμε τα bit του σαρωμένου τμήματος σε 1.


Στην αρχή φόρτωση δεδομένων από το μητρώο θύραςγια να έχετε διαθέσιμη την αρχική διαμόρφωση θύρας. Πρέπει επίσης να ορίσουμε όλα τα bit σάρωσης της θύρας στο 1, αυτό γίνεται μέσω της λειτουργίας Ήμε μάσκα σάρωσης. Στο τμήμα που στάθηκαν οι μονάδες μετά την επιχείρηση Ήμε μάσκα 11110000 (το νόημα μου SCANMASK) όλα τα bit θα γίνουν ένα και όπου υπήρχε μηδέν θα παραμείνει αμετάβλητο.

ΚΑΙ R17,R16; Επαναφορά του bit της σαρωμένης στήλης
OUT COL_PORT,R17 ; Βγάζουμε το δημιουργημένο byte από τη θύρα.


Τώρα τοποθετούμε πάνω στο δημιουργημένο byte μάσκα ενεργής στήλης. Αρχικά έχει ένα μηδέν στην πρώτη θέση, και όλα τα υπόλοιπα είναι ένα. Ως αποτέλεσμα, οι άλλες τιμές θύρας δεν θα αλλάξουν, αλλά το 0 θα εμφανιστεί στην πρώτη στήλη, στη συνέχεια η μάσκα θα μετακινηθεί και η όλη λειτουργία θα επαναληφθεί ξανά. Ως αποτέλεσμα, το μηδέν θα βρίσκεται ήδη στην επόμενη στήλη και ούτω καθεξής. Έτσι, οργανώνουμε ένα «τρέχον» μηδέν στη θύρα σάρωσης, ενώ άλλα, εξωτερικά, bits της θύρας παραμένουν αμετάβλητα. Στη συνέχεια, ο παραγόμενος αριθμός φορτώνεται στον καταχωρητή θύρας και τα πόδια δέχονται τα αντίστοιχα επίπεδα τάσης.

NOP ; Καθυστέρηση για αλλαγή ποδιών.
ΟΧΙ
ΟΧΙ
ΟΧΙ

SBIS ROW0_PIN,ROW0 ; Έλεγχος ποια γραμμή έχει πατηθεί
RJMP bt0

SBIS ROW1_PIN,ROW1
RJMP bt1

SBIS ROW2_PIN,ROW2
RJMP bt2

SBIS ROW3_PIN,ROW3
RJMP bt3


Σειρά ΟΧΙείναι απαραίτητο για να δοθεί χρόνος στο πόδι να φτάσει στο επιθυμητό επίπεδο πριν τον έλεγχο. Το γεγονός είναι ότι ένα πραγματικό κύκλωμα έχει μια ορισμένη τιμή χωρητικότητας και επαγωγής, που κάνει αδύνατο να αλλάξει αμέσως το επίπεδο, υπάρχει ακόμα μια μικρή καθυστέρηση. Και σε ταχύτητες 8 MHz και άνω, ο επεξεργαστής κάνει κλικ σε εντολές με τέτοια ταχύτητα που η ένταση στο πόδι δεν έχει υποχωρήσει ακόμα και ελέγχουμε ήδη την κατάσταση της εξόδου. Έριξα λοιπόν μερικές κενές επεμβάσεις. Στα 8 MHz όλα λειτουργούν μια χαρά. Επί υψηλότερη συχνότητα, πιθανώς, θα χρειαστεί να εγκαταστήσετε πέντε ή έξι ακόμη ΟΧΙή βάλτε σε ένα απλό βρόχο. Ωστόσο, εδώ πρέπει να εξετάσετε τι θα είναι πιο οικονομικό byte byte.
Μετά τους βρόχους υπάρχουν τέσσερις έλεγχοι ανά γραμμή. Και μετάβαση στην κατάλληλη επεξεργασία εκδήλωσης.

ROL R16 ; Μετατόπιση της μάσκας σάρωσης
ΑΡΙΘΜΟΣ ΔΕΚΕΜΒΡΙΟΥ ; Μείωση του μετρητή στηλών
BRNE KeyLoop ; Αν δεν τα έχουμε περάσει όλα ακόμα, κάντε μια ακόμη επανάληψη

CLR R16; Εάν δεν υπήρχαν κλικ, επιστρέφουμε 0
ΜΟΥΣΚΕΥΩ
.undef COUNT

Εδώ η μάσκα μετακινείται προς τα αριστερά χρησιμοποιώντας την εντολή κυκλικής μετατόπισης. ROL. Μετά μειώνουμε τον μετρητή επανάληψης (αρχικά ίσος με τέσσερις, αφού έχουμε τέσσερις στήλες). Εάν δεν υπήρχαν κλικ, τότε στο τέλος και των τεσσάρων επαναλήψεων πέφτουμε από τον βρόχο και επαναφέρουμε τον καταχωρητή R16και επιστρέφουμε.


bt0: ANDI R16,SCANMSK ; Δημιουργία κωδικού σάρωσης
ORI R16.0x01; Το επιστρέφουμε στο μητρώο 16
ΜΟΥΣΚΕΥΩ

Και εδώ είναι ένα από τα πιθανά άκρα όταν πατηθεί. Εδώ δημιουργείται ένας κωδικός σάρωσης που θα επιστραφεί στο μητρώο R16.Αποφάσισα να μην ασχοληθώ, αλλά όπως πάντα, να βάλω μια ντουζίνα byte και να το κάνω όσο το δυνατόν πιο γρήγορο και σύντομο. Λοιπόν, τι έχουμε όταν φτάνουμε σε αυτό το κομμάτι κώδικα. Και έχουμε μία από τις επιλογές θύρας σάρωσης ( 1110,1101,1011,0111 ), και γνωρίζουμε επίσης τον αριθμό γραμμής με τον οποίο φτάσαμε εδώ. Αυτό το συγκεκριμένο κομμάτι μπορεί να επιτευχθεί μόνο από την πρώτη γραμμή χρησιμοποιώντας την εντολή RJMP bt0.
Ας φτιάξουμε λοιπόν έναν κωδικό σάρωσης από τον συνδυασμό σάρωσης και τον αριθμό γραμμής! Δεν ειπώθηκε νωρίτερα! Αρχικά, πρέπει να εξαγάγουμε τον συνδυασμό σάρωσης από την τιμή της θύρας - αποθηκεύεται στον καταχωρητή R16, οπότε δεν χρειάζεται να το παραλάβετε από το λιμάνι. Προωθούμε τη λειτουργία ΚΑΙ την τιμή R16διά μέσου SCANMASKκαι ό,τι ήταν κάτω από τα περνούσε χωρίς αλλαγές, και όπου υπήρχαν μηδενικά, μηδενιζόταν. Ωχ, και εμφανίστηκε ένα κομμάτι σάρωσης - το πιο σημαντικό τσιμπολόγημα. Τώρα ας επικολλήσουμε τον αριθμό γραμμής εκεί - με τη λειτουργία Ή. Κάποτε, πήραμε μια κατασκευή σαν [σάρωση][γραμμή]
Το αφήνουμε λοιπόν στο μητρώο R16, και εμείς οι ίδιοι φεύγουμε! Το ίδιο με τις υπόλοιπες γραμμές. Κοιτάξτε την πηγή, δεν θα τα επαναλάβω εδώ.

Αποκωδικοποίηση κωδικού σάρωσης.
Ωραία, υπάρχει ένας κωδικός σάρωσης, αλλά τι να τον κάνω; Δεν μπορείς να τον κολλήσεις πουθενά. Ξέρουμε ότι τέτοιου είδους χάλια 01110001 αυτός είναι ένας κωδικός, αλλά μερικοί οθόνη υγρού κρυστάλλουη οθόνη ή ένα τυπικό τερματικό θα μας κάνει ένα ανατριχιαστικό αστείο και θα μας πει όλα όσα πιστεύει για το σύστημα σημειογραφίας μας - βλέπετε ASCIIδώστε το. Εντάξει, θα είναι ASCII.

Τι πρέπει να κάνω; Περάστε ολόκληρη τη δομή ΠΕΡΙΠΤΩΣΗπού να εκχωρήσετε έναν κωδικό για κάθε σάρωση ASCIIΜε πιέζει ένας φρύνος - είναι τόσοι πολλοί οι έλεγχοι που πρέπει να γίνουν! Πόσα bytes θα χρειαστούν για όλες αυτές τις ανοησίες; Και η μνήμη μας δεν είναι καουτσούκ, οκτώ κιλομπάιτ και δύο byte ανά εντολή, αυτό είναι στην καλύτερη περίπτωση. Θα μπορούσα να τα κάνω όλα αυτά σωστά στον χειριστή πληκτρολογίου. ΟΧΙ!!! ΣΤΗ ΦΩΤΙΑ!!! Θα πάμε με το δικό μας δρόμο.
Εντάξει, τι έχουμε σε απόθεμα; Η μέθοδος του πίνακα μετάβασης δεν λειτουργεί λόγω της τρομερής διαταραχής των κωδικών σάρωσης. Έξυσα την κολοκύθα, έψαξα το διαμέρισμα... και μετά με ξημέρωσε. Φυσικά!!! Βάναυση δύναμη!!!

Κώδικας σάρωσης ωμής δύναμης.
Έτσι, έχουμε έναν τρομερά δύσπεπτο κώδικα σάρωσης, καθώς και ένα λεπτό τραπέζι ASCIIχαρακτήρες. Πώς να διασταυρώσετε ένα φίδι με έναν σκαντζόχοιρο; Είναι απλό! Ας τοποθετήσουμε στη μνήμη έναν πίνακα συμβόλων σε έναν σύνδεσμο [κωδικός σάρωσης]:, και στη συνέχεια θα εκτελέσουμε κάθε απαιτούμενο κωδικό σάρωσης μέσω αυτού του πίνακα και, εάν υπάρχει αντιστοιχία, θα αντικαταστήσουμε τον απαιτούμενο στην έξοδο ASCIIαπό τη δέσμη. Ένα κλασικό παράδειγμα προγραμματισμού - χαμένο στο χρόνο, αλλά κερδισμένο στη μνήμη.

Έτσι φαίνεται:

CodeGen:LDI ZH,High(Code_Table*2) ; Φορτωμένη διεύθυνση πίνακα κωδικών
LDI ZL,Low(Code_Table*2) ; Υψηλά και χαμηλά byte

Εδώ φορτώσαμε τη διεύθυνση του πίνακα μας στον καταχωρητή ευρετηρίου. Πολλαπλασιάζοντας επί δύο ώστε η διεύθυνση να είναι σε byte, γιατί Σε ένα περιβάλλον μεταγλωττιστή, ο χώρος κώδικα αντιμετωπίζεται με λέξεις.

Brute: LPM R17,Z+; Πήρα τον πρώτο χαρακτήρα από τον πίνακα - κωδικό σάρωσης

CPI R17.0xFF ; Αν το τέλος του τραπεζιού
BREQ CG_Exit ; Μετά βγαίνουμε έξω

CPI R16.0; Αν μηδέν,
BREQ CG_Exit ; μετά βγαίνουμε έξω

CP R16,R17; Το σύγκρισα με τον κωδικό σάρωσης του κλειδιού.
BREQ Ίσο ; Αν είναι ίσο, τότε πάμε να αντικαταστήσουμε τον κωδικό ascii

Φορτώστε τον πρώτο κωδικό σάρωσης από τον πίνακα και γράψτε τον στο μητρώο R17, αυξάνοντας ταυτόχρονα τη διεύθυνση στο μητρώο Ζ(επιλέγοντας το επόμενο κελί του πίνακα) και πρώτα απ' όλα συγκρίνετε με FFείναι ο κωδικός για το τέλος του πίνακα. Αν το τραπέζι έχει τελειώσει, τότε φεύγουμε από εδώ. Εάν δεν έχουμε ταξινομήσει ολόκληρο τον πίνακα, τότε αρχίζουμε να συγκρίνουμε την τιμή εισόδου (στον καταχωρητή R16) στην αρχή με μηδέν (χωρίς πάτημα), εάν εξέλθει και το μηδέν. Και με έναν κωδικό σάρωσης από τον πίνακα. Εάν η σάρωση πίνακα ταιριάζει με τη σάρωση εισόδου, μεταβείτε στο Ισος.

LPM R17,Z+; Αύξηση Z κατά 1
RJMP Brute; Επαναλάβετε τον κύκλο

Και αν δεν βρεθεί τίποτα, τότε καλούμε ξανά την εντολή LPM R17,Z+μόνο για να αυξηθεί αυτή Ζπρος ένα - πρέπει να προχωρήσουμε ASCIIκωδικό και πάρτε τον επόμενο κωδικό σάρωσης από τον πίνακα. Μόλις INC Ζδεν θα λειτουργήσει γιατί Ζεδώ διπλό byte. ZL και ZH. Σε ορισμένες περιπτώσεις είναι αρκετό INC ZL, αλλά αυτό συμβαίνει όταν είμαστε απολύτως βέβαιοι ότι η διεύθυνση είναι κοντά στην αρχή και το χαμηλό byte δεν θα ξεχειλίσει (διαφορετικά, αντί για τη διεύθυνση 00000001:00000000, θα λάβουμε απλώς 000000000:0000000, κάτι που είναι θεμελιωδώς εσφαλμένο) , και την εντολή LPMθα κάνει τα πάντα για εμάς, οπότε εδώ αποθηκεύσαμε μερικά ακόμη byte. Μετά θα επιστρέψουμε στην αρχή του κύκλου, και εκεί θα είναι ξανά LPMπου θα κατεβάσει τον επόμενο κωδικό σάρωσης.

Ίσο: LPM R16,Z ; Φόρτωση κώδικα ASCII από τη μνήμη.
RET ; Ας πάμε πίσω

Αν υπήρχε σύμπτωση, τότε ως αποτέλεσμα LPM Z+εδώ Ζδείχνει στο επόμενο κελί - με ASCIIκώδικας. Το φορτώνουμε στο μητρώο R16και βγες έξω.

CG_Exit: CLR R16 ; Επαναφορά 0 = επιστροφή 0
RET ; Ας πάμε πίσω

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



; ΣΤΑΤΙΚΑ ΣΤΟΙΧΕΙΑ
;========================================
Κωδικός_Πίνακας: .db 0x71,0x31 ;1
.db 0xB1,0x32 ;2
.db 0xD1,0x33 ;3
.db 0x72,0x34 ;4
.db 0xB2,0x35 ;5
.db 0xD2,0x36 ;6
.db 0x73,0x37 ;7
.db 0xB3,0x38 ;8
.db 0xD3,0x39 ;9
.db 0x74,0x30 ;0
.db 0xFF,0 ;END

Υπάρχει απλώς ένας πίνακας στατικών δεδομένων στην άκρη της μνήμης. Όπως μπορείτε να δείτε, τα δεδομένα ομαδοποιούνται σε δύο byte - scancode/ASCII

Χάρη σε τέτοιες εκτροπές, ολόκληρο το πρόγραμμα, με την επεξεργασία του πληκτρολογίου, την αποκωδικοποίηση του κωδικού σάρωσης, την ανάγνωση/εγγραφή στην ένδειξη LCD και την επαναφορά της μνήμης RAM (που απαιτείται για να βεβαιωθείτε ότι η μνήμη είναι μηδενική) χρειάστηκε μόνο 354 byte. Ποιος μπορεί να κάνει λιγότερα;

Εάν είναι απαραίτητο να χρησιμοποιήσετε ένα πληκτρολόγιο με μεγάλο αριθμό κουμπιών σε μια συσκευή, για παράδειγμα, σε μια κλειδαριά συνδυασμού, χρησιμοποιείται συχνά ένα πληκτρολόγιο matrix. Εάν συνδέσετε 12 κουμπιά με τον συνηθισμένο τρόπο, θα χρειαστείτε 12 ακίδες μικροελεγκτή συν ένα κοινό καλώδιο, αλλά η μήτρα χρησιμοποιεί μόνο μία θύρα ελεγκτή, η οποία βοηθά στην αποθήκευση των ακίδων του ελεγκτή. Τα κουμπιά σε ένα τέτοιο πληκτρολόγιο συνδέονται με κοινές στήλες και σε κοινές σειρές, οι γραμμές της θύρας του μικροελεγκτή χωρίζονται σε είσοδο PB7-PB4 και έξοδο PB3-PB0. Σε κάθε στιγμή του χρόνου το σήμα χαμηλό επίπεδο(λογικό μηδέν) παρέχεται μόνο σε μία σειρά κουμπιών, τα υπόλοιπα πρέπει να παρέχονται σε μια λογική. Αυτό θα εξαλείψει την ασάφεια στον προσδιορισμό του αριθμού του πατημένου κουμπιού. Τα δυαδικά σήματα που υπάρχουν στις στήλες του πληκτρολογίου διαβάζονται μέσω της θύρας εισόδου του μικροελεγκτή.

Πρέπει να οργανώσουμε έναν ατελείωτο βρόχο στο πρόγραμμα. ΣΕ ειδική λειτουργίαΚάνουμε δημοσκόπηση στο πληκτρολόγιο, αναλύουμε τα δεδομένα που λαμβάνονται και εμφανίζουμε τα αποτελέσματα στον δείκτη. Η μέτρηση πληκτρολογίου αποτελείται από διαδοχική σάρωση κάθε γραμμής για το σκοπό αυτό, εφαρμόζεται ένα λογικό μηδέν στην αντίστοιχη γραμμή της θύρας εξόδου (ισοδύναμο κοινό σύρμα), οι υπόλοιπες σειρές θα πρέπει να είναι ψηλές, μετά την οποία ο κώδικας διαβάζεται από τη θύρα εισόδου στην οποία συνδέονται οι στήλες. Εάν διαβαστούν όλα, τότε δεν πατιέται κανένα πλήκτρο, διαφορετικά ο κωδικός περιέχει πληροφορίες για τα πλήκτρα που πατήθηκαν. Αξίζει να σημειωθεί ότι ο κωδικός ανάγνωσης περιέχει όχι μόνο τον αριθμό της κλειστής επαφής, αλλά και πληροφορίες σχετικά με το πάτημα πολλών κουμπιών ταυτόχρονα, επομένως είναι καλύτερο να αποθηκεύσετε τον κωδικό ανάγνωσης απευθείας στη μνήμη του ελεγκτή και όχι το τελειωμένο κουμπί αριθμός. Για να αποθηκεύσετε τον αναγνωσμένο κώδικα, πρέπει να εισαγάγετε έναν ειδικό αλγόριθμο και μεταβλητές.

Παρακάτω είναι ένα παράδειγμα προγράμματος στο οποίο όταν πατάτε ένα συγκεκριμένο πλήκτρο, εμφανίζεται η τιμή του δείκτης επτά τμημάτων. Ο μικροελεγκτής Atmega8 λειτουργεί από έναν εσωτερικό ταλαντωτή συχνότητας 8MHz.

/*** Σύνδεση πληκτρολόγιο matrixσε μικροελεγκτές AVR ***/ #include #συμπεριλαμβάνω // Πίνακας τιμών για τη θύρα εξόδου unsigned char key_tab = (0b11111110, 0b11111101, 0b11111011, 0b11110111); // Συνάρτηση ψηφοφορίας πληκτρολογίου ανυπόγραφο char scan_key(void) ( unsigned char key_value = 0; unsigned char i; for(i = 0;i< 4;i++) { PORTB = key_tab[i]; // выводим лог. 0 в порт вывода _delay_us(10); switch (PINB & 0xF0) { case 0b11100000: key_value = 1 + i * 3; return (key_value); case 0b11010000: key_value = 2 + i * 3; return (key_value); case 0b10110000: key_value = 3 + i * 3; return (key_value); default: break; } } return (key_value); } int main(void) { // массив цифр для индикатора unsigned char num = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0); // Порт вывода DDRB &= ~(1 << PB7)|(1 << PB6)|(1 << PB5)|(1 << PB4); // Порт ввода PORTB = 0xF0; // Устанавливаем лог. 1 в порт ввода DDRD = 0xFF; // Выход на индикатор PORTD = 0x00; _delay_ms(10); while(1) { // Выводим значение нажатой кнопки на индикатор if(scan_key()==1) PORTD = num; if(scan_key()==2) PORTD = num; if(scan_key()==3) PORTD = num; if(scan_key()==4) PORTD = num; if(scan_key()==5) PORTD = num; if(scan_key()==6) PORTD = num; if(scan_key()==7) PORTD = num; if(scan_key()==8) PORTD = num; if(scan_key()==9) PORTD = num; if(scan_key()==11) PORTD = num; } }

Αρχείο για το άρθρο "Σύνδεση πληκτρολογίου matrix σε μικροελεγκτές AVR"
Περιγραφή: Project AVRStudio και Proteus
Μέγεθος αρχείου: 37,33 KB Αριθμός λήψεων: 1 905
  1. Μελετήστε τα χαρακτηριστικά λειτουργίας των παράλληλων θυρών ενός μικροελεγκτή.
  2. Μελετήστε τα διαγράμματα για τη σύνδεση κουμπιών και πληκτρολογίου matrix στον μικροελεγκτή.
  3. Μάθετε να προσδιορίζετε την κατάσταση των κουμπιών χρησιμοποιώντας το πρόγραμμα.
  4. Μάθετε πώς να κάνετε εντοπισμό σφαλμάτων προγραμμάτων στον πάγκο εργαστηρίου LESO1.
  5. Μάθετε πώς λειτουργεί το πληκτρολόγιο matrix.

2 Προκαταρκτική προετοιμασία για εργασία

  1. Χρησιμοποιώντας τις σημειώσεις διαλέξεων και τη συνιστώμενη βιβλιογραφία, μελετήστε τα κυκλώματα των παράλληλων θυρών μικροελεγκτών.
  2. Χρησιμοποιώντας τις σημειώσεις της διάλεξης και τη συνιστώμενη βιβλιογραφία, μελετήστε τα διαγράμματα για τη σύνδεση κουμπιών και πληκτρολογίων σε παράλληλες θύρες.
  3. Μελετήστε την αρχιτεκτονική του μικροελεγκτή ADuC842.
  4. Μελετήστε το σχηματικό διάγραμμα της εργαστηριακής βάσης LESO1.
  5. Δημιουργήστε έναν αλγόριθμο για το πρόγραμμα: όταν πατάτε ένα κουμπί, ανάλογα με την επιλογή, ανάβει ένας συνδυασμός LED, που αντιστοιχεί σε δυαδική μορφή με τον αριθμό του κουμπιού. Όταν απελευθερωθεί το κουμπί, τα LED θα πρέπει να σβήσουν.
  6. Γράψτε ένα πρόγραμμα στη γλώσσα προγραμματισμού C.

3 Σύντομες θεωρητικές πληροφορίες

3.1 Χρήση πληκτρολογίου matrix για την εισαγωγή πληροφοριών σε ένα σύστημα μικροεπεξεργαστή

Για την υλοποίηση της αλληλεπίδρασης του χρήστη με το σύστημα μικροεπεξεργαστή, χρησιμοποιούνται διάφορες συσκευές εισόδου-εξόδου. Στην απλούστερη περίπτωση, ένα κουμπί μπορεί να λειτουργήσει ως συσκευή εισόδου, η οποία είναι ένας στοιχειώδης μηχανισμός που κλείνει και ανοίγει τις επαφές υπό την επίδραση μιας εξωτερικής μηχανικής δύναμης. Το διάγραμμα σύνδεσης του κουμπιού στη γραμμή εισόδου της θύρας παράλληλης εισόδου του μικροελεγκτή φαίνεται στο σχήμα 1. Όταν οι επαφές του κουμπιού S1 είναι ανοιχτές μέσω της αντίστασης R1, λαμβάνεται ένα υψηλό λογικό επίπεδο «1» στην είσοδο του ελεγκτή Όταν οι επαφές είναι κλειστές, η είσοδος συνδέεται με το κοινό καλώδιο, το οποίο αντιστοιχεί στο λογικό επίπεδο "0". Εάν η παράλληλη θύρα του μικροελεγκτή έχει ενσωματωμένη γεννήτρια ρεύματος, τότε το κύκλωμα μπορεί να κάνει χωρίς αντίσταση R1.

Εικόνα 1 – Σύνδεση ενός μόνο κουμπιού σε παράλληλη θύρα

Το μειονέκτημα του παραπάνω διαγράμματος είναι ότι η σύνδεση κάθε κουμπιού απαιτεί ξεχωριστή παράλληλη γραμμή θύρας. Δεδομένου ότι είναι συχνά απαραίτητη η εισαγωγή πληροφοριών από μεγάλο αριθμό κουμπιών, για να μειωθεί ο αριθμός των γραμμών I/O, χρησιμοποιείται ένα πληκτρολόγιο, το οποίο είναι ένας δισδιάστατος πίνακας κουμπιών οργανωμένων σε σειρές και στήλες (Εικόνα 2).

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

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


Εικόνα 2 – Σύνδεση πληκτρολογίου matrix σε παράλληλη θύρα

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


Σχήμα 3 – Διαγράμματα χρονισμού της λειτουργίας της θύρας εξόδου

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

Το πρόγραμμα για τον μικροελεγκτή εξαρτάται αυστηρά από το διάγραμμα κυκλώματος της συσκευής που αναπτύσσεται. Είναι αδύνατο να γράψετε ένα πρόγραμμα για μια συσκευή μικροελεγκτή χωρίς να έχετε μπροστά σας το διάγραμμα κυκλώματος της. Επομένως, πριν ξεκινήσετε να εργάζεστε στο σχηματικό διάγραμμα της βάσης εκπαίδευσης LESO1, θα πρέπει να μελετήσετε τη μέθοδο σύνδεσης του πληκτρολογίου και των LED στον μικροελεγκτή: προσδιορίστε σε ποιες θύρες συνδέονται τα LED, οι στήλες και οι σειρές του πληκτρολογίου. Στη συνέχεια, χρησιμοποιώντας τον πίνακα SFR, πρέπει να μάθετε τις διευθύνσεις μητρώου των εμπλεκόμενων θυρών I/O.

Το πρόγραμμα που ελέγχει τον μικροελεγκτή ξεκινά όταν η συσκευή είναι ενεργοποιημένη και δεν ολοκληρώνει τη δουλειά του μέχρι να απενεργοποιηθεί η τροφοδοσία. Επομένως, το πρόγραμμα πρέπει να έχει έναν άπειρο βρόχο. Το σώμα του βρόχου θα πρέπει να μετρήσει το πληκτρολόγιο, να αναλύσει τα δεδομένα που λαμβάνονται και να εξάγει το αποτέλεσμα στο LED. Η μέτρηση του πληκτρολογίου αποτελείται από διαδοχική σάρωση κάθε στήλης, για αυτό εφαρμόζεται ένα λογικό μηδέν (ισοδύναμο με ένα κοινό καλώδιο) στην αντίστοιχη γραμμή της θύρας εξόδου, οι υπόλοιπες στήλες πρέπει να έχουν υψηλό επίπεδο τη θύρα εισόδου στην οποία συνδέονται οι σειρές. Εάν διαβαστούν όλα, τότε δεν πατιέται κανένα πλήκτρο, διαφορετικά ο κωδικός περιέχει πληροφορίες για τα πλήκτρα που πατήθηκαν. Αξίζει να σημειωθεί ότι ο κωδικός ανάγνωσης περιέχει όχι μόνο τον αριθμό της κλειστής επαφής, αλλά και πληροφορίες σχετικά με το πάτημα πολλών κουμπιών ταυτόχρονα, επομένως είναι καλύτερο να αποθηκεύσετε τον κωδικό ανάγνωσης απευθείας στη μνήμη του ελεγκτή και όχι το τελειωμένο κουμπί αριθμός. Για να αποθηκεύσετε τον αναγνωσμένο κωδικό, πρέπει να εισαγάγετε μια ειδική μεταβλητή.

Όταν γράφετε ένα πρόγραμμα, πρέπει να θυμάστε τα χαρακτηριστικά της παράλληλης θύρας P1σε μικροελεγκτή ADuC842. Αυτή η θύρα έχει διαμορφωθεί από προεπιλογή για την είσοδο αναλογικών σημάτων (λειτουργία ADC). Για να αλλάξετε τη θύρα σε λειτουργία ψηφιακής εισόδου, πρέπει να γραφτεί ένα λογικό μηδέν στο αντίστοιχο bit της θύρας. Αυτό πρέπει να γίνει μία φορά κατά την προετοιμασία του μικροελεγκτή. Η θύρα δεν διαθέτει εσωτερικό τρανζίστορ ενίσχυσης και επομένως, όταν εισάγετε διακριτές πληροφορίες μέσω αυτής, δεν είναι απαραίτητο να γράψετε μια λογική στα bit.

4 Ανάθεση για εργασία στο εργαστήριο

  1. Χρησιμοποιώντας το σχηματικό διάγραμμα, καθορίστε σε ποιες θύρες του μικροελεγκτή συνδέονται τα LED, καθώς και τις στήλες και τις σειρές του πληκτρολογίου.
  2. Χρησιμοποιήστε τον πίνακα των καταχωρητών ειδικών συναρτήσεων (SFR) για να προσδιορίσετε τις διευθύνσεις καταχωρητών των απαιτούμενων θυρών.
  3. Εισαγάγετε το ενσωματωμένο περιβάλλον προγραμματισμού Keil-C.
  4. Δημιουργήστε και ρυθμίστε σωστά το έργο.
  5. Εισαγάγετε το κείμενο του προγράμματος σύμφωνα με την εργασία: Όταν πατάτε το κουμπί, ανάλογα με την επιλογή, ανάβει ο συνδυασμός LED, που αντιστοιχεί σε δυαδική μορφή με τον αριθμό του κουμπιού. Όταν απελευθερωθεί το κουμπί, τα LED θα πρέπει να σβήσουν.
  6. Μεταφράστε το πρόγραμμα και διορθώστε τα συντακτικά λάθη.
  7. Κατεβάστε το ληφθέν *.γοητεύωαρχείο στο εργαστηριακό περίπτερο LESO1.
  8. Βεβαιωθείτε ότι το πρόγραμμα λειτουργεί σωστά.

5 Οδηγίες για την προετοιμασία αναφοράς

Η έκθεση πρέπει να περιέχει:

  1. Σκοπός της εργασίας.
  2. Σχηματικό διάγραμμα σύνδεσης του πληκτρολογίου με τον μικροελεγκτή.
  3. Γραφικό διάγραμμα του αλγόριθμου προγράμματος.
  4. Πηγαίο κείμενο του προγράμματος.
  5. Περιεχόμενα του αρχείου καταχώρισης έργου λογισμικού.
  6. Συμπεράσματα από τις εργαστηριακές εργασίες που πραγματοποιήθηκαν.

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

Οι αντιστάσεις R2 – R4, R8 – R11 έχουν σχεδιαστεί για να περιορίζουν το ρεύμα εισόδου/εξόδου σε περίπτωση λανθασμένων ρυθμίσεων θύρας ή ταυτόχρονου πατήματος πολλών κουμπιών. Οι ακίδες PD0(RXD), PD1(TXD) συνδέονται στον μετατροπέα UART-RS232, ο οποίος δεν φαίνεται στο διάγραμμα. Η ανταλλαγή USART χρησιμοποιείται για τον εντοπισμό σφαλμάτων προγραμμάτων.

Αλγόριθμος ψηφοφορίας πληκτρολογίου Matrix

Οι γραμμές του πληκτρολογίου συνδέονται με τις ακίδες PD4, PD5, PD6, PD7. Έχουν διαμορφωθεί για έξοδο και στην αρχική κατάσταση υπάρχει μια λογική μηδενική τάση σε αυτούς τους ακροδέκτες. Οι στήλες συνδέονται με καρφίτσες PC0, PC1, PC2. Ρυθμίζονται στην είσοδο, οι εσωτερικές αντιστάσεις έλξης είναι απενεργοποιημένες και αυτές οι γραμμές τροφοδοτούνται με "μηδενική τροφοδοσία" χρησιμοποιώντας εξωτερικές αντιστάσεις 10K.

Η διαδικασία για τη σάρωση ενός πληκτρολογίου είναι η εξής. Βάζουμε 1 στον ακροδέκτη PD4 και ελέγχουμε την κατάσταση των ακίδων PC0, PC1, PC2 (δηλαδή διαβάζουμε τα περιεχόμενα του καταχωρητή PINC). Εάν μία από τις ακίδες έχει οριστεί σε 1, σημαίνει ότι το κουμπί που είναι συνδεδεμένο στην πρώτη γραμμή είναι πατημένο αυτήν τη στιγμή στο πληκτρολόγιο. Αποθηκεύουμε τα bit PD4, PD5, PD6, PD7 και PC0, PC1, PC2 σε μία μεταβλητή - χρησιμοποιώντας αυτόν τον κωδικό θα προσδιορίσουμε τον αριθμό του κουμπιού που πατήθηκε. Εάν δεν πατηθεί κανένα από τα κουμπιά, συνεχίστε τη διαδικασία σάρωσης.

Επαναφέρουμε το 1 στο pin PD4 και το 1 στο pin PD5. Ελέγχουμε ξανά την κατάσταση των ακίδων PC0, PC1, PC2 και αν πατηθεί το κουμπί αποθηκεύουμε τα bit PD4, PD5, PD6, PD7 και PC0, PC1, PC2 σε μια μεταβλητή.

Επαναλαμβάνουμε την περιγραφόμενη ακολουθία για τις υπόλοιπες δύο γραμμές.

Η εναλλαγή κουμπιών πληκτρολογίου συνοδεύεται από αναπήδηση επαφής, την οποία ο μικροελεγκτής μπορεί να «αντιληφθεί» ως πολλαπλά πατήματα. Σε εφαρμογές που χρησιμοποιούν πληκτρολόγια, αυτό είναι ένα ανεπιθύμητο φαινόμενο, επομένως το πρόγραμμα ψηφοφορίας πληκτρολογίου πρέπει να έχει κάποιο είδος προστασίας. Συνήθως το κάνουν αυτό - το γεγονός της πίεσης ενός κουμπιού καταγράφεται εάν κρατηθεί πατημένο για αρκετούς κύκλους ψηφοφορίας.

Ο κωδικός που λαμβάνεται κατά τη σάρωση του πληκτρολογίου χρειάζεται συχνά να μετατραπεί στη συμβολική τιμή ενός αριθμού/γράμματος κουμπιού (για παράδειγμα, για μετάδοση μέσω USART). Για να το κάνετε αυτό, μπορείτε να δημιουργήσετε έναν πίνακα μετατροπών - έναν δισδιάστατο πίνακα. Η πρώτη στήλη του πίνακα θα αποθηκεύσει τους κωδικούς των κουμπιών και η δεύτερη στήλη θα περιέχει τις αντίστοιχες συμβολικές τιμές. Χρησιμοποιώντας τη μέθοδο της διαδοχικής αναζήτησης στον πίνακα, μπορείτε να βρείτε την επιθυμητή τιμή.

Ο αλγόριθμος μέτρησης του πληκτρολογίου μήτρας μπορεί να εφαρμοστεί ως μηχανή πεπερασμένης κατάστασης (State Machine) - μια συνάρτηση που, ανάλογα με την κατάστασή της (την τιμή μιας συγκεκριμένης μεταβλητής) και την ενέργεια εισόδου, εκτελεί διαφορετική εργασία. Το παρακάτω σχήμα δείχνει ένα διάγραμμα μιας τέτοιας μηχανής.

Η αρχική κατάσταση του μηχανήματος είναι 0. Το μηχάνημα παραμένει σε αυτήν την κατάσταση μέχρι να πατηθεί οποιοδήποτε κουμπί. Όταν ανιχνευτεί ένα πάτημα κουμπιού, εκκινείται η λειτουργία σάρωσης πληκτρολογίου ScanKey(), απομνημονεύεται ο κωδικός του πατημένου κουμπιού και το μηχάνημα μεταβαίνει στην κατάσταση 1.

Στην κατάσταση 1, το μηχάνημα ελέγχει εάν το ίδιο κουμπί είναι πατημένο αυτήν τη στιγμή όπως στην κατάσταση 0 ή όχι. Εάν οι κωδικοί των κουμπιών δεν ταιριάζουν, το μηχάνημα επιστρέφει στην κατάσταση 0, αν συμβαίνει αυτό, εκκινείται η συνάρτηση FindKey(), η οποία βρίσκει τη συμβολική τιμή του αριθμού του κουμπιού και ορίζει σημαίες που σηματοδοτούν το σύστημα σχετικά με το πατημένο κουμπί. Με την ολοκλήρωση της λειτουργίας, το μηχάνημα μεταβαίνει στην κατάσταση 2.

Όσο κρατάτε πατημένο το ίδιο κουμπί, το μηχάνημα βρίσκεται στην κατάσταση 2. Εάν προκύψουν αλλαγές, μεταβαίνει στην κατάσταση 3.

Εάν η αλλαγή ήταν τυχαία, το μηχάνημα επιστρέφει στην κατάσταση 2 και αν όχι, μεταβαίνει στην αρχική κατάσταση για να ξεκινήσει ξανά η λειτουργία σάρωσης πληκτρολογίου.

Εφαρμογή λογισμικού της μηχανής

Το παρουσιαζόμενο διάγραμμα κατάστασης μηχανής μπορεί εύκολα να μετατραπεί σε κώδικα προγράμματος.

//αποθηκεύει την τρέχουσα κατάσταση του μηχανήματος
ανυπόγραφο χαρ keyState;

//πρωτότυπα λειτουργιών που χρησιμοποιούνται από το μηχάνημα
ανυπόγραφο χαρ AnyKey( κενός );
ανυπόγραφο χαρ SameKey( κενός );
κενός ScanKey( κενός );
ανυπόγραφο χαρ FindKey( κενός );
κενός ClearKey( κενός );

κενός ScanKeyboard( κενός )
{
διακόπτης(keyState)(
περίπτωση 0:
αν(AnyKey()) (
ScanKey();
keyState = 1;
}
διακοπή;

περίπτωση 1:
αν(SameKey()) (
FindKey();
keyState = 2;
}
αλλού keyState = 0;
διακοπή;

περίπτωση 2:
αν(SameKey())()
αλλού keyState = 3;
διακοπή;

περίπτωση 3:
αν(SameKey()) (
keyState = 2;
}
αλλού {
ClearKey();
keyState = 0;
}
διακοπή;

Αθέτηση:
διακοπή;
}

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


ανυπόγραφο χαρ AnyKey( κενός )
{
PORTD |= 0xf0;
απόδοση(PINC&0x07);
}

Ρυθμίζουμε τις ακίδες PD7 – PD4 σε ones και επιστρέφουμε τις καταστάσεις των ακίδων PC2 – PC0. Εάν πατηθεί κάποιο από τα κουμπιά του πληκτρολογίου αυτή τη στιγμή, η συνάρτηση θα επιστρέψει μια τιμή διαφορετική από το μηδέν, δηλαδή την αλήθεια.

//αποθηκεύει τον κωδικό του πατημένου κουμπιού
ανυπόγραφο χαρΚωδικός κλειδιού;

κενός ScanKey( κενός)
{
ανυπόγραφο χαρ activeRow = (1<<4);
ενώ(ενεργή σειρά) (
PORTD = (PORTD & 0x0f)|activeRow;
αν(PINC & 0x07) (
keyCode = (PINC & 0x07);
keyCode |= (PORTD & 0xf0);
}
activeRow<<= 1;
}
}

Ορίστε το τέταρτο bit της μεταβλητής activeRow σε 1 (ενεργοποιήστε την πρώτη σειρά). Έχοντας διαγράψει τα bit PD7 – PD4, γράφουμε τη μεταβλητή σε PORTD. Εάν οποιοδήποτε από τα τρία λιγότερο σημαντικά ψηφία του καταχωρητή PINC έχει οριστεί σε ένα, τότε πατιέται το κουμπί που αντιστοιχεί στην πρώτη γραμμή. Αποθηκεύουμε τα bit PD7 - PD4 και PC2 - PC0 στη μεταβλητή keyCode. Μετατοπίστε την τιμή της μεταβλητής activeRow προς τα αριστερά κατά ένα ψηφίο και επαναλάβετε τον κύκλο άλλες τρεις φορές.


ανυπόγραφο χαρ SameKey( κενός )
{
PORTD = (PORTD & 0x0f) | (keyCode & 0xf0);
απόδοση((PINC & keyCode) & 0x07);
}

Η λειτουργία ελέγχει εάν ο κωδικός του κουμπιού που πατήθηκε τη δεδομένη στιγμή ταιριάζει με τον κωδικό που ελήφθη στον προηγούμενο κύκλο ψηφοφορίας. Για να το κάνετε αυτό, ορίστε το 1 στην επιθυμητή γραμμή - τα πιο σημαντικά 4 bit του keyCode γράφονται στο PORTD. Στη συνέχεια διαβάζεται ο καταχωρητής PINC, εφαρμόζεται μια μάσκα σε αυτόν με τη μορφή της μεταβλητής keyCode και εκχωρούνται τα 3 λιγότερο σημαντικά bit. Η τιμή που προκύπτει επιστρέφεται. Εάν οι κωδικοί των κουμπιών ταιριάζουν, η τιμή θα είναι μη μηδενική, δηλαδή αληθής.


//αποθηκεύει τη συμβολική τιμή του πατημένου κουμπιού
ανυπόγραφο χαρ keyValue;
//μεταβλητή σημαίας - ορίζεται εάν το κουμπί είναι πατημένο
ανυπόγραφο χαρ keyDown;
//μεταβλητή σημαίας - ορίζεται όταν πατιέται ένα νέο κουμπί
ανυπόγραφο χαρκλειδίΝέο;

//πίνακας μετατροπών
__λάμψη ανυπόγραφο cha r κλειδίΠίνακας = (
(0x11, "1"),
(0x12, "2"),
(0x14, "3"),
(0x21, "4"),
(0x22, "5"),
(0x24, "6"),
(0x41, "7"),
(0x42, "8"),
(0x44, "9"),
(0x81, "*"),
(0x82, "0"),
(0x84, "#")
};

ανυπόγραφο χαρ FindKey( κενός )
{
ανυπόγραφο χαρδείκτης;
για(ευρετήριο = 0, ευρετήριο< 12; index++) {
αν(keyTable == keyCode) (
keyValue = keyTable ;
keyDown = 1;
keyNew = 1;
απόδοση 1;
}
}
απόδοση 0;

Σε αυτό το άρθρο θα ήθελα να παρουσιάσω στους αναγνώστες τη σύνδεση πληκτρολογίων με μικροελεγκτές. Το γεγονός είναι ότι συνήθως τα περισσότερα κυκλώματα μικροελεγκτών απαιτούν ένα ή περισσότερα κουμπιά για την εισαγωγή δεδομένων. Αλλά καθώς τα έργα γίνονται πιο περίπλοκα, ίσως χρειαστεί να χρησιμοποιήσετε ένα μικρότερο πληκτρολόγιο. Υπάρχουν παραλλαγές πληκτρολογίων 3x4 ή 4x4 και σχεδόν πάντα τα πλήκτρα σε αυτά συνδέονται σύμφωνα με ένα διάγραμμα μήτρας. Η χρήση μιας μήτρας είναι απαραίτητη γιατί η σύνδεσή της απαιτεί έναν ελάχιστο αριθμό γραμμών εισόδου-εξόδου. Για παράδειγμα, για ένα πληκτρολόγιο 4x4 που αποτελείται από 16 κουμπιά, απαιτούνται 16 γραμμές εισόδου, επομένως είναι πιο λογικό να το οργανώσετε με τη μορφή μήτρας, δηλ. τακτοποιήστε 4 κουμπιά σε 4 γραμμές, χρησιμοποιώντας 8 γραμμές εισόδου-εξόδου (μία θύρα μικροελεγκτή). Η πιο συνηθισμένη λύση για τη σύνδεση μιας μήτρας σε μια θύρα είναι να συνδέσετε τις σειρές με τα ψηφία υψηλής τάξης και τις στήλες με τα ψηφία χαμηλής τάξης. Ωστόσο, υπάρχει ένα πρόβλημα εδώ - η ανάγνωση της κατάστασης του πληκτρολογίου συμβαίνει όταν συμβαίνει μια διακοπή, αλλά στον μικροελεγκτή ATtiny2313 μπορούμε να χρησιμοποιήσουμε δύο εξωτερικές διακοπές (οι υπόλοιποι ακροδέκτες είναι κατειλημμένοι). Αυτό το πρόβλημα επιλύεται συνδέοντας τέσσερις διόδους που σχηματίζουν ένα στοιχείο "OR" με μια αντίσταση έλξης στην είσοδο INT0.

Το διάγραμμα για τη σύνδεση ενός πληκτρολογίου τύπου matrix 4x4 στον μικροελεγκτή φαίνεται στο Σχ. 1. Διαθέτει υποδοχή DB-9F, μετατροπέα στάθμης MAX3232, οι οποίοι είναι απαραίτητοι για την αλληλεπίδραση του UART του μικροελεγκτή με το RS-232 και η λειτουργία του οποίου περιγράφηκε στο προηγούμενο άρθρο. Οι αντιστάσεις R3 - R6 προστατεύουν τον μικροελεγκτή από βραχυκύκλωμα ρεύματος στη γείωση. Υπάρχει μια αντίσταση έλξης R7 στην είσοδο INT0. Τέσσερις δίοδοι VD1 - VD4 συνδέονται στις γραμμές I/O του πληκτρολογίου (κάθοδοι) και στον ακροδέκτη INT0 (άνοδοι). Τώρα, όταν πατάτε οποιοδήποτε κουμπί, εάν εφαρμοστούν μηδενικά στις στήλες, θα εμφανιστεί ένα χαμηλό επίπεδο στην είσοδο INT0.

Όπως φαίνεται στο Σχ. 1, το πληκτρολόγιο είναι συνδεδεμένο στη θύρα Β του μικροελεγκτή. Το διάγραμμα του παρουσιάζεται στο Σχ. 2.

Ας υποθέσουμε ότι όλη η θύρα Β έχει ρυθμιστεί για είσοδο και όλες οι είσοδοι έχουν τραβηχτεί προς τα πάνω:

DDRB = &B00000000

PORTB = &B11111111

Αφήστε τα κουμπιά (Εικ. 2) να συνδεθούν με κάποιο τρόπο στη γείωση (GND), τότε όταν πατήσετε, για παράδειγμα, το κουμπί «1», οι επαφές της θύρας B PB3 και PB4 θα είναι χαμηλές, δηλ. η θύρα θα λάβει την τιμή PORTB = &B11100111, η οποία είναι ο κωδικός για το κουμπί "1". Το ίδιο ισχύει και για τα υπόλοιπα κουμπιά (κωδικός κουμπιού "B" είναι 01111011, "5" είναι 11011011, κ.λπ.). Όμως, δεδομένου ότι τα κουμπιά δεν είναι συνδεδεμένα με το GND, είναι απαραίτητο να εισαχθεί ξεχωριστός ορισμός γραμμών και στηλών, ακολουθούμενος από άθροιση και ταυτοποίηση του αποτελέσματος με το όνομα του κουμπιού.

Ας κάνουμε τις σειρές εισόδους PB0 - PB3 και ενεργοποιούμε το pull-up τους, και τις στήλες PB3 - PB7 - εξόδους:

DDRB = &B11110000

PORTB = &B00001111

Όταν πατηθεί ένα κουμπί, μια συγκεκριμένη γραμμή θα πέσει χαμηλά. Για παράδειγμα, όταν πατήσετε το κουμπί «1», η θύρα Β θα λάβει την τιμή 00000111, που είναι ο κωδικός γραμμής. Ταυτόχρονα, θα ενεργοποιηθεί μια διακοπή, κατά τη διάρκεια της οποίας η επεξεργασία είναι απαραίτητο να διαβάσετε αυτόν τον κώδικα στη μεταβλητή Stro:

Ας αντιστρέψουμε τις ρυθμίσεις της θύρας - κάνουμε τις στήλες εισόδους PB3 - PB7 και ενεργοποιούμε την ανάσυρσή τους και τις εξόδους σειρών PB0 - PB3:

DDRB = &B00001111

PORTB = &B11110000

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