Δυναμική εμφάνιση στο παράδειγμα συναρμολογητή pic. Arduino: δυναμική οθόνη. Άνοδοι, κάθοδοι - τι να επιλέξετε


Διάγραμμα σύνδεσης για μονοψήφιο δείκτη επτά τμημάτων
Διάγραμμα σύνδεσης για πολυψήφιο δείκτη επτά τμημάτων

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

Όπως λέει και το όνομά του, αποτελείται από επτά στοιχεία οθόνης (τμήματα) που ανάβουν και σβήνουν ξεχωριστά. Εντάσσοντάς τα σε διαφορετικούς συνδυασμούς, μπορούν να χρησιμοποιηθούν για τη δημιουργία απλοποιημένων εικόνων αραβικών αριθμών.
Τα τμήματα χαρακτηρίζονται από τα γράμματα A έως G. όγδοο τμήμα - υποδιαστολή (δεκαδικό σημείο, DP), σχεδιασμένο για την εμφάνιση κλασματικών αριθμών.
Περιστασιακά, εμφανίζονται γράμματα στην ένδειξη επτά τμημάτων.

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

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

Εκτός από δέκα ψηφία, οι δείκτες επτά τμημάτων μπορούν να εμφανίζουν γράμματα. Αλλά λίγα γράμματα έχουν μια διαισθητική αναπαράσταση επτά τμημάτων.
Στα λατινικά: κεφαλαία A, B, C, E, F, G, H, I, J, L, N, O, P, S, U, Y, Z, πεζά a, b, c, d, e, g , h, i, n, o, q, r, t, u.
Στα κυριλλικά: A, B, V, G, g, E, i, N, O, o, P, p, R, S, s, U, Ch, Y (δύο ψηφία), b, E/Z.
Επομένως, οι δείκτες επτά τμημάτων χρησιμοποιούνται μόνο για την εμφάνιση απλών μηνυμάτων.

Συνολικά, η ένδειξη LED επτά τμημάτων μπορεί να εμφανίσει 128 χαρακτήρες:

Ένας τυπικός δείκτης LED έχει εννέα απαγωγές: ο ένας πηγαίνει στις κάθοδοι όλων των τμημάτων και οι άλλοι οκτώ πηγαίνουν στην άνοδο κάθε τμήματος. Αυτό το σχήμα ονομάζεται "κοινό κύκλωμα καθόδου", υπάρχουν και σχήματα με κοινή άνοδο(τότε είναι το αντίστροφο). Συχνά, όχι ένας, αλλά δύο κοινοί ακροδέκτες κατασκευάζονται σε διαφορετικά άκρα της βάσης - αυτό απλοποιεί την καλωδίωση χωρίς να αυξάνει τις διαστάσεις. Υπάρχουν και τα λεγόμενα «καθολικά», αλλά εγώ προσωπικά δεν έχω συναντήσει τέτοια. Επιπλέον, υπάρχουν δείκτες με ενσωματωμένο καταχωρητή μετατόπισης, ο οποίος μειώνει σημαντικά τον αριθμό των ακροδεκτών της θύρας μικροελεγκτή, αλλά είναι πολύ πιο ακριβοί και σπάνια χρησιμοποιούνται στην πράξη. Και επειδή η απεραντοσύνη δεν μπορεί να γίνει κατανοητή, δεν θα εξετάσουμε προς το παρόν τέτοιους δείκτες (αλλά υπάρχουν και δείκτες με πολύ μεγαλύτερο αριθμό τμημάτων, μήτρα).

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

Σύνδεση μιας μονοψήφιας ένδειξης επτά τμημάτων σε έναν μικροελεγκτή

Το παρακάτω διάγραμμα δείχνει πώς έχει συνδεθεί μια μονοψήφια ένδειξη επτά τμημάτωνστον μικροελεγκτή.
Θα πρέπει να ληφθεί υπόψη ότι εάν ο δείκτης με ΚΟΙΝΗ ΚΑΘΟΔΟΣ, τότε συνδέεται η κοινή του έξοδος "γη", και τα τμήματα αναφλέγονται με τροφοδοσία λογική μονάδαστην έξοδο της θύρας.
Εάν ο δείκτης είναι ΚΟΙΝΗ ΑΝΩΔΙΑ, τότε τροφοδοτείται στο κοινό σύρμα του "συν"τάση, και τα τμήματα αναφλέγονται μεταβαίνοντας την έξοδο της θύρας στην κατάσταση λογικό μηδέν.

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

Αντιστάσεις περιορισμού ρεύματοςμπορεί να υπάρχει ή να μην υπάρχει στο διάγραμμα. Όλα εξαρτώνται από την τάση τροφοδοσίας που παρέχεται στον δείκτη και τα τεχνικά χαρακτηριστικά των δεικτών. Εάν, για παράδειγμα, η τάση που παρέχεται στα τμήματα είναι 5 βολτ και είναι σχεδιασμένα για τάση λειτουργίας 2 βολτ, τότε πρέπει να εγκατασταθούν αντιστάσεις περιορισμού ρεύματος (για να περιοριστεί το ρεύμα μέσω αυτών για αυξημένη τάση τροφοδοσίας και να μην καούν όχι μόνο η ένδειξη, αλλά και η θύρα του μικροελεγκτή).
Είναι πολύ εύκολο να υπολογίσετε την τιμή των αντιστάσεων περιορισμού ρεύματος, χρησιμοποιώντας τον τύπο του παππού Ωμ.
Για παράδειγμα, τα χαρακτηριστικά του δείκτη είναι τα εξής (λαμβανόμενα από το φύλλο δεδομένων):
— τάση λειτουργίας — 2 βολτ
— ρεύμα λειτουργίας — 10 mA (=0,01 A)
— Τάση τροφοδοσίας 5 βολτ
Τύπος υπολογισμού:
R= U/I (όλες οι τιμές σε αυτόν τον τύπο πρέπει να είναι σε Ohms, Volt και Amps)
R= (τάση τροφοδοσίας - τάση λειτουργίας)/ρεύμα λειτουργίας
R= (5-2)/0,01 = 300 Ohm

Διάγραμμα σύνδεσης για πολυψήφιο δείκτη LED επτά τμημάτωνΒασικά το ίδιο όπως όταν συνδέετε έναν μονοψήφιο δείκτη. Το μόνο πράγμα είναι ότι τα τρανζίστορ ελέγχου προστίθενται στις κάθοδοι (άνοδοι) των δεικτών:

Δεν φαίνεται στο διάγραμμα, αλλά μεταξύ των βάσεων των τρανζίστορ και των ακίδων της θύρας του μικροελεγκτή, είναι απαραίτητο να συμπεριληφθούν αντιστάσεις, η αντίσταση των οποίων εξαρτάται από τον τύπο του τρανζίστορ (υπολογίζονται οι τιμές των αντιστάσεων, αλλά μπορείτε επίσης να δοκιμάσετε να χρησιμοποιήσετε αντιστάσεις με ονομαστική τιμή 5-10 kOhm).

Η ένδειξη με εκκενώσεις πραγματοποιείται δυναμικά:
— ο δυαδικός κωδικός του αντίστοιχου ψηφίου ορίζεται στις εξόδους της θύρας PB για το 1ο ψηφίο και, στη συνέχεια, το λογικό επίπεδο εφαρμόζεται στο τρανζίστορ ελέγχου του πρώτου ψηφίου
— ο δυαδικός κωδικός του αντίστοιχου ψηφίου ορίζεται στις εξόδους της θύρας PB για το 2ο ψηφίο και, στη συνέχεια, το λογικό επίπεδο εφαρμόζεται στο τρανζίστορ ελέγχου του δεύτερου ψηφίου
— ο δυαδικός κωδικός του αντίστοιχου ψηφίου ορίζεται στις εξόδους της θύρας PB για το 3ο ψηφίο και, στη συνέχεια, το λογικό επίπεδο εφαρμόζεται στο τρανζίστορ ελέγχου του τρίτου ψηφίου
- έτσι σε κύκλο
Σε αυτή την περίπτωση, είναι απαραίτητο να ληφθούν υπόψη:
— για δείκτες με Εντάξειχρησιμοποιείται δομή τρανζίστορ ελέγχου NPN(ελέγχεται από λογική μονάδα)
- για ένδειξη με ΟΑ- τρανζίστορ δομής PNP(ελέγχεται από το λογικό μηδέν)

Σε ένα από τα προηγούμενα μαθήματα, μάθαμε πώς να ανάβουμε τμήματα LED. Αν και αυτό μπορεί να γίνει μόνο χρησιμοποιώντας το Arduino, χρησιμοποιήσαμε ένα πρόσθετο στοιχείο στο σεμινάριο μας - . Αυτό το χρήσιμο IC μας έσωσε μερικές πολύτιμες ακίδες μικροελεγκτή. Αλλά ένας δείκτης επτά τμημάτων είναι σχεδόν άχρηστος. Εμφανίζει μόνο έναν αριθμό. Τι γίνεται αν θέλουμε να βγάλουμε έναν μεγάλο αριθμό, ας πούμε από το 0 έως το 500; Θα χρειαστούμε έως και τρεις αριθμούς και επομένως τρεις δείκτες. Πώς θα τα συνδέσουμε με τον ελεγκτή; Μπορούμε απευθείας, αλλά τότε θα πάρουμε 7*3 = 21 εξόδους! Είναι πολύ σπάταλο. Επιπλέον, θα χρειαστείτε άλλη μια πλακέτα, αφού το Arduino Uno απλά δεν έχει αρκετές ψηφιακές ακίδες. Ας δοκιμάσουμε να χρησιμοποιήσουμε έναν καταχωρητή μετατόπισης; Ήδη καλύτερα. Τώρα χρειαζόμαστε τρεις καταχωρητές συνδεδεμένους σε μια αλυσίδα, καθώς και τρεις καρφίτσες Arduino για να τους ελέγξουμε. Σε γενικές γραμμές, θα μπορούσαμε να σταματήσουμε τη βελτιστοποίηση του σχεδίου μας εδώ, αλλά θα προχωρήσουμε παρακάτω. Ας τα βγάλουμε πέρα ​​με ένα μόνο μητρώο βάρδιας!

Δυναμική οθόνη

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

Σύνδεση στο Arduino

Σε αυτό το σεμινάριο χρησιμοποιούμε τρεις δείκτες επτά τμημάτων με κοινή κάθοδο. Θα χρειαστούμε επίσης έναν καταχωρητή μετατόπισης συνδεδεμένο με όλους τους δείκτες ταυτόχρονα. Για να ανάβουμε μόνο έναν δείκτη τη φορά, χρησιμοποιούμε τρία τρανζίστορ πεδίου, τα οποία θα συνδέσουν την κάθοδο με τη γείωση την κατάλληλη στιγμή. Παρεμπιπτόντως, αντί για τρεις ξεχωριστούς δείκτες, είναι καλύτερο να χρησιμοποιήσετε έναν τριψήφιο δείκτη. Αυτό δεν θα αλλάξει την ουσία του κυκλώματος, αλλά θα υπάρχουν λιγότερα καλώδια! Σχηματικό διάγραμμα
Εμφάνιση διάταξης
Συνιστούμε τη χρήση τρανζίστορ σε συσκευασία TO92, για παράδειγμα 2N7000, ως ηλεκτρονικά κλειδιά. Για να συνδέσετε κάθε τρανζίστορ θα χρειαστείτε δύο αντιστάσεις: 100-150 Ohms και 2,2-10 kOhms. Η πρώτη αντίσταση έχει σχεδιαστεί για να προστατεύει την έξοδο του ελεγκτή από υπερτάσεις ρεύματος που συμβαίνουν στην πύλη κατά τη δημιουργία πεδίου. Η δεύτερη αντίσταση θα βοηθήσει στο γρήγορο κλείσιμο του διακόπτη όταν εφαρμόζουμε χαμηλή στάθμη στην αντίστοιχη έξοδο του ελεγκτή (μέσω αυτής το υπολειπόμενο φορτίο της πύλης θα στραγγίσει στο έδαφος). Σε κάθε γραμμή από τον καταχωρητή στον δείκτη, απαιτείται αντίσταση ρύθμισης ρεύματος 200-300 Ohms, έτσι ώστε τα LED στην ένδειξη να μην καούν. Συζητήσαμε αυτήν την απόχρωση της εργασίας με LED. Συναρμολογούμε προσεκτικά το διάγραμμα και προχωράμε στο πρόγραμμα. Το πρόγραμμα για δυναμική απεικόνιση const byte digit_pins = (5,6,7); const byte data_pin = 2; const byte sh_pin = 4; const byte st_pin = 3; ανυπόγραφο long tm, next_flick; const ανυπόγραφο int to_flick = 1; ψηφίο byte = 0; ανυπόγραφος μετρητής int = 125; ψηφία const byte = ( B11101110, B10000010, B11011100, B11010110, B10110010, B01110110, B01111110, B11000010, B1011111); void fill(byte d)( for(char i=0; i<8; i++){ digitalWrite(sh_pin, LOW); digitalWrite(data_pin, digits[d] & (1<next_flick)( next_flick = tm + to_flick; ψηφίο++; if(ψηφίο == 3) ψηφίο = 0; setDigit(ψηφίο, μετρητής); ) ) Μέρος αυτού του προγράμματος, συμπεριλαμβανομένων των μεταβλητών καρφίτσα_δεδομένων, sh_pin, st_pinκαι λειτουργία γέμισμαήδη γνωστό σε μας από. Πίνακας ψηφίααποθηκεύει δέκα συνδυασμούς τμημάτων για τα ψηφία 0 έως 9. Για εξοικονόμηση μνήμης, αποθηκεύουμε κάθε συνδυασμό σε ένα byte και για καλύτερη κατανόηση τους έχουμε γράψει σε δυαδική μορφή. Για εναλλαγή ενδείξεων θα χρησιμοποιήσουμε . Κάθε χιλιοστό του δευτερολέπτου θα γεμίζουμε τον καταχωρητή με τον απαιτούμενο συνδυασμό και θα ενεργοποιούμε την αντίστοιχη ένδειξη. Για αυτό χρησιμοποιούμε τη συνάρτηση setDigit. Διαφωνία ψηφίοείναι το ευρετήριο της ένδειξης που είναι ενεργοποιημένο αυτήν τη στιγμή και μετρητής- έναν τριψήφιο αριθμό που θέλουμε να τονίσουμε. Παράμετρος to_flickείναι υπεύθυνος για την περίοδο εναλλαγής ενδείξεων. Είναι ίσο με 1, που σημαίνει ότι οι αριθμοί για εμφάνιση αλλάζουν κάθε χιλιοστό του δευτερολέπτου. Τι γίνεται αν αυξήσουμε αυτήν την παράμετρο; Ας πούμε μέχρι 100 ms, ή ακόμα και έως 500 ms. Η επίδραση της οπτικής αδράνειας θα εξαφανιστεί και θα αρχίσουμε να παρατηρούμε μια αλλαγή στους αριθμούς. Πρόγραμμα μετρητή με δυναμική οθόνηΣτο προηγούμενο παράδειγμα, η μεταβλητή μετρητήςαποθήκευσε τον αριθμό 125 από προεπιλογή. Ας προσπαθήσουμε τώρα να προσθέσουμε ένα μετρητή δευτερολέπτων στο πρόγραμμα έτσι ώστε μετρητήςαυξάνεται κατά ένα κάθε δευτερόλεπτο, μέχρι τον αριθμό 999. const byte digit_pins = (5,6,7); const byte data_pin = 2; const byte sh_pin = 4; const byte st_pin = 3; ανυπόγραφο long tm, next_sec, next_flick; const unsigned int to_sec = 1000; const ανυπόγραφο int to_flick = 1; ανυπόγραφος μετρητής int = 0; ψηφίο byte = 0; ψηφία const byte = ( B11101110, B10000010, B11011100, B11010110, B10110010, B01110110, B01111110, B11000010, B1011111); void fill(byte d)( for(char i=0; i<8; i++){ digitalWrite(sh_pin, LOW); digitalWrite(data_pin, digits[d] & (1<next_sec)( next_sec = tm + to_sec; counter++; if(counter == 1000) counter = 0; ) tm = millis(); if(tm > next_flick)( next_flick = tm + to_flick; ψηφίο++; if(ψηφίο == 3) ψηφίο = 0; setDigit(ψηφίο, μετρητής); ) ) Φορτώστε το πρόγραμμα στο Arduino και παρακολουθήστε τον μετρητή να λειτουργεί!

Καθήκοντα

  1. Ψηφιακό χρονόμετρο. Συναρμολογήστε ένα κύκλωμα με τριψήφιο δείκτη. Προσθήκη στο διάγραμμα. Όταν πατάτε το κουμπί, το χρονόμετρο θα πρέπει να αρχίσει να μετράει. Όταν το πατήσετε ξανά, σταματήστε. Επιπλέον, μπορείτε να προσθέσετε ένα κλασματικό τμήμα στο χρονόμετρο, που εμφανίζεται στην τρίτη ένδειξη μέσω μιας κουκκίδας.
  2. Ψηφιακό βολτόμετρο για τάσεις από 0 έως 10 Volt. Συναρμολογήστε ένα κύκλωμα με τριψήφιο δείκτη. Προσθέστε ένα διαιρέτη τάσης δύο αντιστάσεων 10 kOhm στο κύκλωμα, συνδεδεμένο στην αναλογική είσοδο του Arduino. Γράψτε ένα πρόγραμμα που θα διαβάζει την τιμή στην αναλογική είσοδο κάθε 100 ms, θα τη μετατρέπει σε Volts και θα την εμφανίζει στην ένδειξη. Για να εμφανίσετε σωστά το κλασματικό τμήμα, πρέπει να συνδέσετε το όγδοο τμήμα - μια κουκκίδα.

συμπέρασμα

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

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

ΕΠΙΛΟΓΗ=0b00000000; // Ρύθμιση του TMR0 INTCON=0b10100000; // Οι διακοπές είναι ενεργοποιημένες και μόνο από το TMR0

Για να εργαστείτε, θα χρειαστείτε τις ακόλουθες καθολικές μεταβλητές:

Ανυπόγραφο char v1,v2,v3, vn;

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

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

Κενή διακοπή isr(void) ( if(T0IF) // όταν το TMR0 υπερχειλίζει ( vn++; // αλλαγή του διακόπτη τμήματος(vn) // επιλογή τμήματος ( case 1:seg7(v1,1);break; case 2:seg7 (v2 ,2);break; case 3:(seg7(v3,3);vn=0;)break; ) TMR0=100; // ρύθμιση του χρονοδιακόπτη στην αρχή T0IF=0; // επαναφορά της σημαίας ) )

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

Void seg7(unsigned char c, unsigned char s) ( unsigned char t=0; // g segment PORTA=0b00000000; // reset port A switch(s) // Select anode ( case 1:(t=1;)break ; περίπτωση 2:(t=2;)διάλειμμα; περίπτωση 3:(t=32;)διάλειμμα; ) διακόπτης(c%10) // επιλογή τμημάτων (κάθοδοι) ( // 00bfaed g περίπτωση 0: (PORTC=0b00000000 ; PORTA=t+4;)διάλειμμα; περίπτωση 1: (PORTC=0b00011110;PORTA=t+4;)διάλειμμα; περίπτωση 2: (PORTC=0b00010001;PORTA=t;)διάλειμμα, περίπτωση 3: (PORTC=0b00010100; PORTA =t;)διάλειμμα; περίπτωση 4: (PORTC=0b00001110;PORTA=t;)διάλειμμα; περίπτωση 5: (PORTC=0b00100100;PORTA=t;)διάλειμμα; περίπτωση 6: (PORTC=0b00100000;PORTA=t;) διάλειμμα ; περίπτωση 7: (PORTC=0b00010110;PORTA=t+4;)διάλειμμα; περίπτωση 8: (PORTC=0b00000000;PORTA=t;)διάλειμμα; περίπτωση 9: (PORTC=0b00000100;PORTA=t;)διάλειμμα; ) )

Το PIC16F676 έχει ημιτελείς θύρες εξόδου, επομένως όλα τα τμήματα δεν χωρούσαν στη θύρα C, το τμήμα g έπρεπε να τοποθετηθεί στη θύρα Α και το σημείο έπρεπε να συνδεθεί σχηματικά σε μία από τις κοινές ανόδους μέσω ενός μετατροπέα. Το διάγραμμα μιας τέτοιας σύνδεσης μοιάζει με αυτό:

Εάν χρησιμοποιείτε άλλο μικροελεγκτή που έχει τουλάχιστον μία πλήρη θύρα, για παράδειγμα PIC16F628A

η συνάρτηση θα έχει την ακόλουθη μορφή:

Κενό seg7(unsigned char c, unsigned char s) ( unsigned char t=0; switch(c%10) // επιλογή τμημάτων (κάθοδοι) ( // gcPdeafb case 0: (t=0b10100000;)break; case 1: ( t=0b10111110;)διάλειμμα; περίπτωση 2: (t=0b01100010;) διάλειμμα; περίπτωση 3: (t=0b00101010;) διάλειμμα; περίπτωση 4: (t=0b00111100;) διάλειμμα; περίπτωση 5: (t=0b0101) διάλειμμα ; περίπτωση 6: (t=0b00100001;) διάλειμμα, περίπτωση 7: (t=0b10111010;) διάλειμμα; περίπτωση 8: (t=0b00100000;) διάλειμμα ; // επαναφορά θύρας Ένας διακόπτης/οι // επιλογή ανόδου ( περίπτωση 1:( PORTA =4;) θραύση; περίπτωση 2: ( PORTA =8;) θραύση, περίπτωση 3: ( PORTA =64;) θραύση; ) PORTB = t; if(c>9) ( PORTB=t ) )

Η κουκκίδα δίπλα στο σύμβολο ανάβει εάν Μεμεγαλύτερη από 9, η τιμή θα εξακολουθεί να εμφανίζεται στην ένδειξη, δηλ. Θα βγει μόνο το λιγότερο σημαντικό ψηφίο, όλα τα άλλα θα απορριφθούν (για παράδειγμα: 1 9 , 39 = 9. ).

Στην κύρια λειτουργία (κύρια) το MK εκτελεί αθόρυβα τη δουλειά του· για να εμφανίσει νέες πληροφορίες στην οθόνη, χρειάζεται μόνο να αλλάξει τις τιμές των μεταβλητών v1,v2,v3, αλλά θα πρέπει να αλλάζονται ταυτόχρονα για να αποφευχθεί η σύγχυση στον δείκτη.

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

Θέμα: Ανάπτυξη κυκλώματος δυναμικής απεικόνισης.

Στόχος: Αποκτήστε πρακτικές δεξιότητες στο σχεδιασμό στοιχείων οθόνης για ψηφιακές συσκευές.

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

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

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

Η ένδειξη LED επτά τμημάτων αποτελείται από οκτώ LED με συνδεδεμένες καθόδους ή ανόδους. Τα τμήματα χαρακτηρίζονται με τα γράμματα A,B,C,D,E,F,G,H, όπως φαίνεται στο Σχήμα 1.

Εικόνα 1

Το τμήμα ανάβει όταν εφαρμόζεται θετική τάση στον κοινό ακροδέκτη και μηδενική τάση εφαρμόζεται στην κάθοδο.

Υπάρχουν δύο τρόποι οργάνωσης μιας διεπαφής με οθόνη: στατική και δυναμική. Το μειονέκτημα του πρώτου είναι η ανάγκη για μεγάλο αριθμό γραμμών ελέγχου (ο αριθμός των ψηφίων των θυρών του μικροελεγκτή) - 8 για κάθε δείκτη.

Η μέθοδος δυναμικής εμφάνισης απαιτεί έναν αριθμό ψηφίων ίσο με το άθροισμα του αριθμού των τμημάτων και του αριθμού των ψηφίων.

Η δυναμική μέθοδος είναι παλμική και βασίζεται στο γεγονός ότι εάν το «τρεμόπαιγμα» παράγεται με συχνότητα 50 Hz ή μεγαλύτερη, τότε η λάμψη εμφανίζεται σταθερή σε ένα άτομο. Αυτή η μέθοδος απαιτεί ελάχιστο κόστος υλικού· η δυναμική επεξεργασία οθόνης, συμπεριλαμβανομένης της μετατροπής κώδικα, γίνεται σε λογισμικό.

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

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

Το διάγραμμα ενός τετραψήφιου δυναμικού δείκτη φαίνεται στο σχήμα 3. Ο δίαυλος τμήματος συνδέεται στη θύρα C του μικροελεγκτή και τα τέσσερα λιγότερο σημαντικά bit της θύρας D είναι τα bit για την επιλογή των bits ένδειξης.

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

Έτσι, το σήμα σε μια γραμμή επιλογής είναι μια ακολουθία παλμών με κύκλο λειτουργίας ίσο με τον αριθμό των ενδείξεων.

Σε συχνότητα τρεμοπαίσματος 50 Hz, η περίοδος παλμού είναι 20 ms.

Σχήμα 2

Εικόνα 3 – Ηλεκτρικό κύκλωμα δυναμικής ένδειξης

Το σχήμα 2 δείχνει τα διαγράμματα χρονισμού των επιλεγμένων σημάτων για μια τετραψήφια οθόνη. Ο χρόνος λάμψης ενός δείκτη είναι 5 ms.

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

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

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

Ο δίαυλος τμήματος SA-SH σχηματίζεται από τους ακροδέκτες της θύρας P2 του μικροελεγκτή και τα τέσσερα λιγότερο σημαντικά ψηφία της θύρας P1 σχηματίζουν τον δίαυλο επιλογής δείκτη (SELI-SEL4). Η επεξεργασία της οθόνης γίνεται από τη μονάδα λογισμικού ως εξής. Ο κωδικός επτά τμημάτων του δεξιού συμβόλου ένδειξης (HG4) φορτώνεται στη θύρα P2. Ενισχύεται από το στοιχείο DD2, αυτό το ρεύμα παρέχεται στον δίαυλο των τμημάτων a, b, c... Στη συνέχεια, ο κωδικός για την επιλογή (ενεργοποίηση) της ένδειξης HG4 φορτώνεται στο τετράδιο χαμηλής τάξης της θύρας P1: SEL1=0, SEL2 -SEL4=1 (δεκαεξαδική τιμή Ε). Το λογικό μηδενικό ρεύμα, που ενισχύεται από το στοιχείο DD2, ρέει μέσω του σύρματος 11 μέσω της αντίστασης R7 και ανοίγει το τρανζίστορ VT4. Τα υπόλοιπα τρανζίστορ είναι απενεργοποιημένα. Η τάση τροφοδοσίας +5V τροφοδοτείται μέσω ενός ανοιχτού τρανζίστορ στην κοινή άνοδο του δείκτη HG4, προκαλώντας την εμφάνιση του συμβόλου. Αυτή η κατάσταση παραμένει για 5 ms. Στο τέλος αυτού του χρονικού διαστήματος, το MK εξάγει ένα υψηλό επίπεδο στην εκφόρτιση της θύρας SEL1, το τρανζίστορ VT4 κλείνει και ο διακόπτης VT3 και το σύμβολο σε αυτήν την εκφόρτιση εμφανίζεται και η εκφόρτιση σταματά να ανάβει. Στη συνέχεια, ένας κωδικός επτά τμημάτων του συμβόλου ένδειξης HG3 εκδίδεται στη θύρα P2 και το bit P1.1 τίθεται σε κατάσταση χαμηλού επιπέδου. Αυτό ενεργοποιεί την οθόνη κ.λπ.

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

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

Πίνακας 2 - Κωδικοί επτά τμημάτων

Byte δεδομένων ΕΝΑ σι ντο ρε μι φά σολ H HEX - κωδικός χαρακτήρα
$9F
$25
$D
$99
$49
$41
$1 F

Ασκηση

1. Αναπτύξτε ένα διάγραμμα ηλεκτρικού κυκλώματος μιας δυναμικής ψηφιακής οθόνης επτά τμημάτων.

2. Κάντε ένα σχέδιο του διαγράμματος ηλεκτρικού κυκλώματος σύμφωνα με το GOST ESKD.

3. Να αιτιολογήσετε την επιλογή των λύσεων κυκλώματος.

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

Πίνακας 2 - Αρχικά δεδομένα

Επιλογή Αρ. Τύπος μικροελεγκτή Τύπος ένδειξης Αριθμός τμημάτων
ATmega8 BL-S56A-11
ATmega16 BC56-11SRWA
ATtiny13 BL-D56A-21
ATtiny2313 BL-S56B-11
ATmega8 BA56-11GWA
ATmega16 BL-D56B-21
ATtiny13 BL-D56A-21
ATtiny2313 BL-D56A-21
ATmega16 BL-S56B-11
ATtiny13 BL-D56B-21

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

1 Βασικά στοιχεία ή εισαγωγή

Πρώτα απ 'όλα, ας ορίσουμε την ορολογία που θα χρησιμοποιήσουμε σε όλο το άρθρο.

Εάν χρειάζεται να ελέγξετε μια οθόνη που αποτελείται από μια ενιαία εξοικείωση επτά τμημάτων, αυτό δεν προκαλεί κανένα πρόβλημα - μπορεί να θεωρηθεί ως 8 ανεξάρτητα LED. Εάν χρειάζεται να εμφανίσετε περισσότερες πληροφορίες από έναν χαρακτήρα, αρχίζουν τα προβλήματα: 2 γνωστά μέρη αποτελούν 16 LED, τρία - 24 κ.λπ., δηλαδή, για μια τριψήφια οθόνη μπορεί απλώς να μην υπάρχουν αρκετές ακίδες μικροελεγκτή, να μην αναφέρετε οθόνες 6 ή περισσότερων ψηφίων και, ειδικά, δείκτες μήτρας.

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

Προκειμένου ολόκληρη η οθόνη να γίνεται αντιληπτή ότι λάμπει συνεχώς, τα ψηφία πρέπει να εναλλάσσονται γρήγορα - περισσότερες από 25 φορές ανά δευτερόλεπτο. Όπως μπορείτε να δείτε, τα επίπεδα όλων των εκροών (τα οποία, παρεμπιπτόντως, έχουν γίνει σημαντικά μικρότερα από ό,τι με τη συνήθη προσέγγιση) αλλάζουν συνεχώς, δηλ. δεν έχουν στατικά επίπεδα, αλλά δυναμικά, εξ ου και η ονομασία της μεθόδου ένδειξης - δυναμική.

Δυναμική απεικόνιση εικόνας

2 Τύποι υλοποίησης υλικού

2.1 Επίπεδοι πίνακες

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

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

  • με γραμμές?
  • με στήλες?
  • τμήμα προς τμήμα (ανά pixel).
  • με μεικτό τρόπο.

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

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

2.2 Πολυδιάστατοι πίνακες

Τα παραδείγματα που εξετάσαμε υποθέτουν την υλοποίηση μιας μονόχρωμης οθόνης, π.χ. που αποτελείται από μονόχρωμα LED. Τι να κάνετε εάν θέλετε να αποκτήσετε μια πολύχρωμη οθόνη, για παράδειγμα, από LED RGB; Υπάρχουν δύο πιθανές λύσεις.

Το πρώτο είναι απλώς να αυξήσουμε τον αριθμό των γραμμών (ή στηλών) του πίνακα μας, αντιμετωπίζοντας κάθε RGB LED ως 3 ανεξάρτητα μεμονωμένα LED. Το μεγάλο μειονέκτημα αυτής της προσέγγισης είναι η τριπλάσια αύξηση του αριθμού των γραμμών (ή στηλών). Ένα απλό παράδειγμα δείχνει εύκολα τι σημαίνει αυτό στην πράξη: χρησιμοποιώντας δύο μικροελεγκτές μικροελεγκτών οκτώ bit, μπορούμε να έχουμε μια μονόχρωμη μήτρα τμήματος 8x8 ή μια έγχρωμη μήτρα 4x4. Συμφωνήστε ότι στη δεύτερη περίπτωση είναι πρακτικά αδύνατο να εμφανιστεί κάτι κατανοητό...

Ο δεύτερος τρόπος είναι η μετάβαση από έναν «επίπεδο» πίνακα τμημάτων σε έναν «πολυδιάστατο». Εάν το σήμα κάθε γραμμής περνά μέσα από έναν πολυπλέκτη 1x3, τότε μπορούμε να φανταστούμε το σύστημα απεικόνισης των LED RGB ως 3 ανεξάρτητες μήτρες της αρχικής διάστασης: κάθε μήτρα αποτελείται από LED του ίδιου χρώματος και επιλέγουμε τον επιθυμητό πίνακα χρησιμοποιώντας πολυπλέκτη σήματα ελέγχου. Η εικόνα εξηγεί τι έχει ειπωθεί.

Προφανώς, στην περίπτωση μιας πολυδιάστατης μήτρας, απαιτείται επίσης ένας επιπλέον αριθμός γραμμών ελέγχου, ωστόσο, ο αριθμός αυτός δεν είναι τόσο μεγάλος: στις ίδιες δύο θύρες ελεγκτή μπορούμε να έχουμε έγχρωμη οθόνη 7x7!!!

2.3 Τρόποι μείωσης της διάστασης των πινάκων

Εάν ο αριθμός των ακροδεκτών μικροελεγκτή είναι πολύ περιορισμένος, θα πρέπει να αναζητήσουμε τρόπους για να μειώσουμε τον αριθμό των γραμμών και στηλών του πίνακα μας. Φυσικά, θαύματα δεν γίνονται και σε αυτή την περίπτωση θα πρέπει να πληρώσουμε χρησιμοποιώντας επιπλέον μικροκυκλώματα εκτός από τον μικροελεγκτή. Όπως ίσως μαντέψατε, εδώ μπορείτε να χρησιμοποιήσετε την προηγουμένως συζητηθείσα μέθοδο των «πολυδιάστατων» πινάκων - τελικά, κανείς δεν θα μας απαγορεύσει να χρησιμοποιούμε απλώς τριπλάσιο αριθμό μονοχρωμάτων LED αντί για RGB LED; Το κυριότερο είναι να τα τακτοποιήσετε κατάλληλα...

Έτσι, μπορούμε να μειώσουμε τη διάσταση του πίνακα χρησιμοποιώντας:

  • αποκωδικοποιητές ή πολυπλέκτης?
  • καταχωρητές βάρδιας.

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

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

Είναι εύκολο να διαπιστωθεί ότι οποιοσδήποτε αριθμός γραμμών και στηλών θα απαιτήσει μόνο αύξηση του αριθμού των καταχωρητών και ο αριθμός των γραμμών ελέγχου μικροελεγκτή που εμπλέκονται θα παραμείνει ο ίδιος! Ένα μικρό μειονέκτημα αυτής της προσέγγισης είναι ότι καθώς αυξάνεται ο αριθμός των καταχωρητών στην αλυσίδα, η ταχύτητα της διαδοχικής εξόδου πληροφοριών σε αυτούς θα πρέπει να αυξηθεί, κάτι που δεν είναι πάντα εύκολο να επιτευχθεί. Για παράδειγμα, οι κοινοί μικροελεγκτές της οικογένειας AVR, πρακτικά δεν σας επιτρέπουν να υπερβείτε τη σειριακή ταχύτητα εξόδου των 10 megabits/sec. Από την άλλη πλευρά, εάν χρησιμοποιείτε άλλους ελεγκτές που μπορούν να εξάγουν σήματα πιο γρήγορα, ενδέχεται να προκύψουν προβλήματα διαφορετικής σειράς: η μετάδοση ενός σήματος ρολογιού υψηλής συχνότητας κατά μήκος μιας μεγάλης γραμμής (και με μεγάλο αριθμό καταχωρητών θα είναι αναπόφευκτα ένα ) εμφανίζεται εντελώς διαφορετικά από ένα χαμηλής συχνότητας, επομένως θα απαιτηθούν ειδικά μέτρα κατά την τοποθέτηση μιας πλακέτας τυπωμένου κυκλώματος και άλλα πράγματα που δεν θα εξετάσουμε σε αυτό το άρθρο.

3 Μέθοδοι υλοποίησης λογισμικού

Δεν θα εξετάσουμε την εφαρμογή λογισμικού όλων των αναφερόμενων επιλογών δυναμικής εμφάνισης - αυτό θα διόγκωνε αδικαιολόγητα το άρθρο. Θα περιοριστούμε μόνο σε τρία από τα πιο δημοφιλή παραδείγματα: μια επίπεδη μήτρα με άμεσο έλεγχο σειρών και στηλών, το ίδιο με τη χρήση αποκωδικοποιητή και, τέλος, μια παραλλαγή που χρησιμοποιεί καταχωρητές μετατόπισης. Σε όλες τις περιπτώσεις, θα δοθεί ιδιαίτερη προσοχή σε όλες τις αποχρώσεις της εφαρμογής λογισμικού, δηλαδή, ο κώδικας C θα συνοδεύεται από επεξηγήσεις μόνο σε περιπτώσεις όπου αυτό συμπίπτει με την πρόθεση του συγγραφέα και καθόλου με το επίπεδο εκπαίδευσής σας . Με αυτό υπαινίσσομαι ότι πρέπει να γνωρίζετε τα βασικά του C χωρίς εμένα.

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

3.1 Ο απλούστερος τρόπος

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

Ας εισαγάγουμε τον ορισμό των παρακάτω σταθερών:

#define SCR_SZ 6 /* αριθμός γνωριμιών εμφάνισης */ #define ROWS PORTB /* εμφάνιση θύρας "γραμμών", π.χ. διαχείριση τμήματος */ #define COLS PORTD /* θύρα διαχείρισης «στήλης», π.χ. κοινές κάθοδοι */

Τώρα ας δηλώσουμε τον πίνακα οθόνης:

Ανυπόγραφο char SCR;

Αρχικά, θα υποθέσουμε ότι κάθε στοιχείο του πίνακα αντιστοιχεί στην εξοικείωση της οθόνης και κάθε bit αυτού του στοιχείου αντιστοιχεί σε ένα συγκεκριμένο τμήμα της ένδειξης. Ποιο bit αντιστοιχεί σε ποιο τμήμα - σε αυτήν την περίπτωση δεν έχει σημασία, όπως δεν έχει σημασία πώς αυτά τα bit ορίζονται στα byte του πίνακα μας, απλώς θα υποθέσουμε προς το παρόν ότι είναι ήδη εκεί. Για απλότητα, θα υποθέσουμε επίσης ότι οι κοινές κάθοδοι συνδέονται με τους ακροδέκτες της θύρας COLSδιαδοχικά: το λιγότερο σημαντικό bit είναι η πιο δεξιά ένδειξη, μετά το δεύτερο, μετά το τρίτο κ.λπ.

Πώς να κάνετε αυτή τη συστοιχία "εμφάνιση" στην οθόνη; Ας γράψουμε τον παρακάτω κώδικα:

< SCR_SZ; pos++){ ROWS = SCR; COLS = ~(1 << pos); }

Θα εκτελέσει την απαιτούμενη λειτουργία; Ναί. Αλλά δεν είναι καλό.

Πρώτα απ 'όλα, σημειώστε ότι δεν έχουμε κανέναν έλεγχο σχετικά με το πόσο γρήγορα ενημερώνονται τα περιεχόμενα των γραμμών και των στηλών. Δεύτερον, σημειώστε ότι μέχρι να εκτυπωθεί το νέο στοιχείο πίνακα ΣΕΙΡΕΣστις γραμμές COLSΤο παλιό νόημα είναι ακόμα εκεί! Πού οδηγεί; Ναι, εξάλλου, για ένα κλάσμα του δευτερολέπτου η περιοχή εξοικείωσης θα εμφανίζει τμήματα της γειτονικής περιοχής εξοικείωσης, δηλ. ορισμένα τμήματα θα φωτίζονται εσφαλμένα.

Μπορείτε να αποφύγετε αυτό το εφέ κάνοντας το εξής: πριν ενημερώσετε το περιεχόμενο ΣΕΙΡΕΣ, σβήνετε πάντα το γνώριμο μέρος που ήταν το προηγούμενο. Για να μην ασχοληθείτε με τον προσδιορισμό της προηγούμενης οικειότητας, μπορείτε να σβήσετε τα πάντα με τη μία. Ο κώδικας μας λοιπόν έχει την εξής μορφή:

Ανυπόγραφο char pos; while(1) for(pos = 0; pos< SCR_SZ; pos++){ COLS = 0xFF; ROWS = SCR; COLS = ~(1 << pos); delay(); }

Προσθέσαμε το κενό ολόκληρης της οθόνης πριν ενημερώσουμε την κατάσταση των γραμμών τμήματος (στέλλοντας τις κοινές καθόδους ψηλά, θα απενεργοποιήσουμε την ένδειξη ανεξάρτητα από το τι υπάρχει στις ανόδους) και εισαγάγαμε μια καθυστέρηση στο τέλος του κύκλου. Τώρα η οθόνη θα λειτουργεί πολύ καλύτερα. Έχουμε όμως γράψει καλό πρόγραμμα; Δυστυχώς όχι.

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

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

Τι πρέπει να κάνεις? Η απάντηση, όπως πάντα, είναι απλή: όλες οι διεργασίες που πρέπει να εκτελούνται απαρατήρητες από την επίλυση της κύριας εργασίας (και η ένδειξη, φυσικά, είναι μια τέτοια διαδικασία) πρέπει να εκτελούνται χρησιμοποιώντας διακοπές με χρονοδιακόπτη.
Οι διακοπές θα φτάνουν σε αυστηρά καθορισμένα χρονικά διαστήματα, που θα διασφαλίζουν ομοιόμορφο φωτισμό των γνωστών πινακίδων. Η ένδειξη φόντου θα μας επιτρέψει απλώς να γράψουμε κάτι στον πίνακα τη σωστή στιγμή στον κύριο βρόχο SCR- και θα εμφανιστεί αμέσως στην οθόνη! Και όλες οι τροποποιήσεις στον κώδικα θα συνοψιστούν στο γεγονός ότι αντί για βρόχους χρησιμοποιούμε μια λειτουργία χειριστή διακοπής:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; COLS = 0xFF; ROWS = SCR; COLS = ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

Μερικά σχόλια.

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

Στο κύριο πρόγραμμα θα χρειαστεί μόνο να αρχικοποιήσουμε τις θύρες και το χρονόμετρο (σε αυτήν την περίπτωση - Χρονοδιακόπτης 0), ώστε να ξεχειλίζει στα διαστήματα που χρειαζόμαστε, και να επιτρέπονται διακοπές. Μετά από αυτό, δεν χρειάζεται να σκεφτείτε την ένδειξη - θα λειτουργήσει αθόρυβα και ειρηνικά από μόνο του. Αλλά πώς να προσδιορίσετε το επιθυμητό διάστημα υπερχείλισης του χρονοδιακόπτη; Πολύ απλό. Το ανθρώπινο μάτι αντιλαμβάνεται το τρεμόπαιγμα με συχνότητα μεγαλύτερη από 25 Hz ως συνεχή λάμψη. Έχουμε 6 δείκτες, καθένας από αυτούς πρέπει να τρεμοπαίζει με αυτή τη συχνότητα, πράγμα που σημαίνει ότι οι πληροφορίες στην οθόνη πρέπει να ενημερώνονται με συχνότητα 25 x 6 = 150 Hz ή περισσότερο. Τώρα ας υπολογίσουμε την τιμή του χρονοδιακόπτη prescaler: διαιρέστε τη συχνότητα ρολογιού του MK με το 256 ( Χρονοδιακόπτης 0όλοι έχουν AVRοκτώ bit, που σημαίνει ότι ξεχειλίζει μετά την καταμέτρηση έως το 256) - αυτή θα είναι η επιθυμητή τιμή του προκαταρκτικού χρονοδιακόπτη. Φυσικά, είναι απίθανο το αποτέλεσμα να συμπίπτει με μία από τις τυπικές τιμές προκλιμάκωσης - αυτό δεν είναι πρόβλημα, μπορείτε να πάρετε την πλησιέστερη μικρότερη κατάλληλη τιμή. Η οθόνη θα λειτουργεί σε υψηλότερη συχνότητα, αλλά αυτό δεν θα υποβαθμίσει την ποιότητά της! Μια παρενέργεια θα είναι ένα μεγάλο φορτίο στον πυρήνα MK για την οθόνη. Εάν αυτό παρεμβαίνει πολύ στο κύριο πρόγραμμα, θα πρέπει να αλλάξετε την οθόνη σε άλλο χρονόμετρο, για παράδειγμα, ένα 16-bit Χρονοδιακόπτης 1, ή εισαγάγετε έναν μετρητή για υπερχειλίσεις χρονοδιακόπτη που παραλείφθηκαν:

#define SKIP 15 /* αριθμός διακοπών του χρονοδιακόπτη για παράβλεψη */ ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0, στατικό ανυπόγραφο char skip = SKIP, εάν (--skip) επιστρέψει, skip = SKIP; COLS = 0xFF; = SCR ; COLS = ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

Σε αυτά τα απλουστευμένα παραδείγματα υποθέτουμε ότι στο λιμάνι COLS, εκτός από τις κοινές καθόδους των δεικτών, τίποτα άλλο δεν συνδέεται. Ωστόσο, στην πραγματική ζωή τέτοια τύχη δεν συμβαίνει συχνά, και κάτι άλλο πιθανότατα συνδέεται με τις υπόλοιπες γραμμές αυτού του λιμανιού. Επομένως, όταν οργανώνετε δυναμική οθόνη, θα πρέπει πάντα να διασφαλίζετε ότι η κατάσταση όλων των γραμμών θυρών που δεν εμπλέκονται άμεσα στην οθόνη παραμένει αμετάβλητη. Αυτό γίνεται απλά: αντί να γράψετε απλώς μια νέα τιμή στη θύρα, θα πρέπει να χρησιμοποιήσετε κάλυψη περιττών bits:

COLS |= 0x3F; // έτσι σβήνουμε όλα τα γνωστά μέρη COLS &= ~(1<

Και οι δύο χειριστές δεν αλλάζουν την τιμή των πιο σημαντικών bits της θύρας COLS.

3.2 Μέθοδος με αποκωδικοποιητή

Ο αποκωδικοποιητής μπορεί να χρησιμοποιηθεί είτε για μετατροπή ΓΟΗΤΕΥΩή BCDκωδικοποιήστε σε σύμβολα επτά τμημάτων ή για να επιλέξετε μία από τις στήλες του πίνακα. Και οι δύο επιλογές θα διαφέρουν από την απλούστερη μέθοδο που συζητήθηκε προηγουμένως μόνο ως προς τον τρόπο οργάνωσης της εξόδου στις θύρες ΣΕΙΡΕΣκαι/ή COLS, στο οποίο θα συνδεθούν οι είσοδοι του αποκωδικοποιητή.
Μια επιλογή για τη χρήση αποκωδικοποιητή για τη λήψη συμβόλου επτά τμημάτων:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; COLS |= 0x3F; ROWS = (ROWS & 0xF0) | (SCR & 0x0F); COLS &= ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

Όπως μπορείτε να δείτε, οι αλλαγές είναι ελάχιστες - πριν από την εμφάνιση ΣΕΙΡΕΣκωδικός χαρακτήρων από τον πίνακα SCR, τα πιο σημαντικά bit καλύπτονται, μετά τα οποία ορίζονται τα λιγότερο σημαντικά bit σύμφωνα με τον κωδικό χαρακτήρων. Δηλαδή, πιστεύουμε ότι ο αποκωδικοποιητής είναι συνδεδεμένος με τα 4 λιγότερο σημαντικά bit της θύρας ΣΕΙΡΕΣ.

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

3.3 Μέθοδος εγγραφής

Αν και η δυναμική ένδειξη με χρήση καταχωρητών μετατόπισης δεν διαφέρει θεμελιωδώς από τις μεθόδους που συζητήθηκαν προηγουμένως, υπάρχουν αρκετές επιλογές για την υλοποίησή της. Θα εξετάσουμε το απλούστερο - την έξοδο bits αποκλειστικά μέσω λογισμικού. Και στην εφαρμογή άλλων (χρησιμοποιώντας USI/USART/SPI/TWI) μπορείτε να δοκιμάσετε τις δυνάμεις σας σε αυτό μόνοι σας.

Για την παραλλαγή της προηγουμένως επιλεγμένης εμφάνισης γνωστών τοποθεσιών 6 και επτά τμημάτων, χρησιμοποιούμε 2 καταχωρητές μετατόπισης του τύπου 74HC595. Αυτός ο καταχωρητής ελέγχεται από τρία σήματα: παλμούς ρολογιού εισαγωγής σειριακών δεδομένων CLK, τα πραγματικά δεδομένα ΔΕΔΟΜΕΝΑκαι έναν παλμό ταυτόχρονης παράλληλης εξόδου πληροφοριών γραμμένων στον καταχωρητή ΣΕΙΡΑ. Ας δηλώσουμε τις αντίστοιχες μακροεντολές (για απλότητα, θα στείλουμε όλα τα σήματα σε μία θύρα):

#define CLK _BV(PB0) #define DATA _BV(PB1) #define SET _BV(PB2) #define REG_PORT PORTB

Για να γράψετε στο μητρώο, είναι βολικό να γράψετε μια ξεχωριστή συνάρτηση:

Static void shift(unsigned char d)( unsigned char i; for (i=0; i< 8; i++){ // устанавливаем нужный уровень DATA if(d & 1) REG_PORT |= DATA; else REG_PORT &= ~DATA; REG_PORT |= CLK; // даем импульс CLK REG_PORT &= ~CLK; d >>= 1; } }

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

Τώρα ο χειριστής διακοπών μας θα μοιάζει με αυτό:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; shift(SCR); shift(~(1<< pos)); REG_PORT |= SET; // выдаем импульс SET REG_PORT &= ~SET; if(++pos == SCR_SZ) pos = 0; }

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

4 Για όσους δεν έχουν ποτέ αρκετό

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

4.1 Άνοδοι, κάθοδοι - τι να επιλέξετε;

Όλα όσα εξετάσαμε νωρίτερα σχετίζονται με δείκτες με κοινές καθόδους. Τι γίνεται αν θέλετε να το χρησιμοποιήσετε με κοινές ανόδους; Γενικά, όλα παραμένουν ίδια, εκτός από το ότι πριν από την έξοδο θα χρειαστεί να αντιστραφούν τα δεδομένα - η εκκαθάριση της εξοικείωσης πραγματοποιείται με την έξοδο μηδενικών στο COLS, ανάφλεξη - αντίστοιχα, μονάδες και τμήματα μέσα ΣΕΙΡΕΣθα συμπεριληφθούν με μηδενικά αντί για μονάδες. Έτσι, ο χειριστής διακοπής θα μοιάζει κάπως έτσι:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; COLS &= 0xC0; ROWS = ~SCR; COLS |= (1<< pos); if(++pos == SCR_SZ) pos = 0; }

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

#define COMMON_ANODE 1 ISR(TIMER0_OVF_vect)( static unsigned char pos = 0; #if COMMON_ANODE != 1 COLS &= 0xC0; ROWS = ~SCR; COLS |= (1<< pos); #else COLS |= 0x3F; ROWS = SCR; COLS &= ~(1 << pos); #endif if(++pos == SCR_SZ) pos = 0; }

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

4.2 Τρεμοπαίξιμο

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

Είναι πολύ εύκολο να γίνει. Ας εισαγάγουμε μια καθολική μεταβλητή, κάθε bit μονάδας της οποίας θα υποδηλώνει ένα σύμβολο που αναβοσβήνει:

ανυπόγραφο αναβοσβήνει = 0;

Τώρα ας τροποποιήσουμε ελαφρώς τον χειριστή διακοπής:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; στατική ανυπόγραφη καταχώρηση χαρακτήρων = 0; COLS |= 0x3F; if(!(αναβοσβήνει & (1<

Όπως μπορείτε να δείτε, έχει προστεθεί μόνο μία στατική μεταβλητή - ο μετρητής των εισόδων στον χειριστή διακοπών είσοδος, και έναν χειριστή δοκιμής κατάστασης. Η λογική είναι απλή: η έξοδος της επόμενης εξοικείωσης πραγματοποιείται μόνο εάν υπάρχει στο αντίστοιχο bit αναβοσβήνωμηδέν ή το πιο σημαντικό κομμάτι του μετρητή είσοδοςισούται με 1. Αν, ας υποθέσουμε, αναβοσβήνωπεριέχει όλα τα μηδενικά, τότε αυτή η συνθήκη πληρούται πάντα - εμφανίζονται όλα τα γνωστά μέρη. Αν αναβοσβήνωπεριέχει ένα 1 σε ένα από τα bit του, τότε το αντίστοιχο πρόσημο θα φωτίζεται μόνο τη στιγμή που το πιο σημαντικό bit του μετρητή είναι ίσο με 1. Εφόσον ο μετρητής αυξάνεται κάθε φορά που εισάγεται ο χειριστής διακοπής, το αντίστοιχο πρόσημο θα τρεμοπαίζει με συχνότητα 128 φορές μικρότερη από τη συχνότητα διακοπής.

4.3 Ρύθμιση της φωτεινότητας των τμημάτων

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

4.4 Αυθαίρετη διανομή καρφιτσών

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

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

Τμήμα Α

Τμήμα Β

Τμήμα Η

Τμήμα Γ

Τμήμα Δ

Το τμήμα G

Τμήμα Ε

Τμήμα ΣΤ

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

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

Είναι βολικό να ζωγραφίσετε το σκοπό των γραμμών λιμένων με τη μορφή τριών πλακών:

1

ΕΝΑ

0

4

H

3

2

σι

φά

μι

5

σολ

ρε

ντο

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

Αν το τμήμα μπιτ FEGDCαφήστε στο σύμβολο ώστε να πέσουν μέσα PORTDχωρίς μετατοπίσεις, μετά το τμήμα Hμπορεί επίσης να παραμείνει στο 6ο bit του συμβόλου και επίσης δεν χρειάζεται να μετατοπιστεί πριν την έξοδο PORTC, αλλά για τμήματα ΕΝΑΚαι ΣΕΤα bit 7 και 3 θα παραμείνουν, δηλαδή, πιθανότατα το τμήμα ΣΕθα πρέπει να μετατοπιστεί κατά 3 θέσεις πριν από την έξοδο, και το τμήμα ΕΝΑ- κατά 6. Θα εστιάσω σε αυτήν την επιλογή και μπορείτε να συνεχίσετε την αναζήτηση για τις ελάχιστες βάρδιες (οι μετατοπίσεις σε πολλές θέσεις δεν είναι τόσο γρήγορη λειτουργία, επομένως συνιστάται να μειώσετε τον αριθμό τους στο ελάχιστο).

Έτσι, στην περίπτωσή μας, η κατανομή των bit στο byte χαρακτήρων ήταν ως εξής:

ΕΝΑ

H

φά

μι

σι

σολ

ρε

ντο

Ας επισημάνουμε τις μάσκες bit για έξοδο στις αντίστοιχες θύρες:

ρε

0

0

1

1

0

1

1

1

0x37

σι

1

0

0

0

0

0

0

0

0x80

ντο

0

1

0

0

1

0

0

0

0x48

Χρησιμοποιώντας αυτές τις μάσκες, χρησιμοποιούμε τη λειτουργία «bitwise AND» για να επιλέξουμε τα απαραίτητα bit για έξοδο στη θύρα.

Ας δηλώσουμε σταθερές μάσκας:

#define MASKD 0x37 #define MASKB 0x80 #define MASKC 0x48

Προηγουμένως, εξάγαμε το σύμβολο σε μία μόνο θύρα ΣΕΙΡΕΣ, τώρα αυτή η διαδικασία θα χωριστεί σε τρία μέρη:

PORTD = (PORTD & ~MASKD) | (SCR & MASKD); PORTB = (PORTB & ~MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~MASKC) | ((SCR & _BV(6)) | (((SCR & _BV(3)) >> 3);

Σημειώστε ότι για ανάληψη σε PORTCένα bit πρέπει να βγαίνει χωρίς μετατόπιση και το δεύτερο - με μετατόπιση, έτσι αντί για ΜΑΣΚΑΈπρεπε να χρησιμοποιήσω ξεχωριστές μακροεντολές _BV().

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

#define COM0 _BV(0) #define COM1 _BV(3) #define COM2 _BV(4) #define COM3 _BV(5) #define COM4 _BV(7) #define COM5 _BV(3) #define COM_D (COM5) #define COM_C (COM2 | COM3 | COM4) #define COM_B (COM0 | COM1)

Για να σβήσετε όλες τις γνωριμίες, πρέπει να εξάγετε τις αντίστοιχες σταθερές στις θύρες COM_x:

PORTD |= COM_D; PORTC |= COM_C; PORTB |= COM_B;

Αλλά για να ενεργοποιήσετε την εξοικείωση, θα πρέπει να είστε δύσκολοι (δεν έχει νόημα η έξοδος και στις τρεις θύρες, επειδή μόνο ένα μεμονωμένο bit θα είναι ενεργό σε μια συγκεκριμένη θύρα, ανάλογα με την τιμή pos), για παράδειγμα, χρησιμοποιώντας τον τελεστή διακόπτης:

Switch(pos)( case 0: PORTB &= ~COM0; break; case 1: PORTB &= ~COM1; break; case 2: PORTC &= ~COM2; break; case 3: PORTC &= ~COM3; break; case 4: PORTC &= ~COM4; διάλειμμα; περίπτωση 5: PORTD &= ~COM5; διάλειμμα; )

Δεν είναι ο πιο όμορφος τρόπος, αλλά λειτουργεί.

Έτσι, ο χειριστής διακοπών μας έχει την ακόλουθη μορφή:

ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; στατική ανυπόγραφη καταχώρηση χαρακτήρων = 0; // καταστολή PORTD |= COM_D; PORTC |= COM_C; PORTB |= COM_B; // εμφάνιση PORTD = (PORTD & (~MASKD) | SCR & MASKD); PORTB = (PORTB & ~MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~MASKC) | ((SCR & _BV(6)) | ((SCR & _BV (3)) >> 3); // αναβοσβήνει αν(!(αναβοσβήνει & (1<< pos)) || (++entry & 0x80)) { switch(pos){ case 0: PORTB &= ~COM0; break; case 1: PORTB &= ~COM1; break; case 2: PORTC &= ~COM2; break; case 3: PORTC &= ~COM3; break; case 4: PORTC &= ~COM4; break; case 5: PORTD &= ~COM5; break; } } if(++pos == SCR_SZ) pos = 0; }

Τώρα μένει να καταλάβουμε πώς να περιγράψουμε πιο εύκολα τα σύμβολα για έξοδο... Προτείνω να κάνουμε τα εξής: ορίστε σταθερές που αντιστοιχούν στα bit των τμημάτων και στη συνέχεια «κατασκευάστε» τα απαραίτητα σύμβολα από αυτές τις σταθερές:

// στοιχειώδη τμήματα #define _A _BV(7) #define _B _BV(3) #define _C _BV(0) #define _D _BV(1) #define _E _BV(4) #define _F _BV(5) #define _G _BV (2) #define _H _BV(6) // ψηφιακά σύμβολα #define d_0 (_A | _B | _C | _D | _E | _F) #define d_1 (_B | _C) #define d_2 (_A | _B | _G | _D | _Ε) // και ούτω καθεξής

Επομένως, εάν πρέπει να εμφανίσετε ένα μηδέν στη δεξιά άκρα της οθόνης, πρέπει απλώς να γράψετε στη σωστή θέση:

SCR = d_0;

Εάν σε άλλο έργο πρέπει να κατανείμετε τα bit διαφορετικά, θα αλλάξετε μόνο τους αριθμούς στις μακροεντολές _BV()για στοιχειώδη τμήματα, και όλα τα σύμβολα θα "επαναδημιουργηθούν" αυτόματα. Για τις απλούστερες περιπτώσεις που περιγράφηκαν στην αρχή, δεν θα χρειαστεί να κάνετε τίποτα άλλο, αλλά για την επιλογή "αναδιάταξης bit", θα πρέπει, φυσικά, να το τσιμπήσετε.

4.5 Υποστήριξη κουμπιών

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

Αυτό φαίνεται σχηματικά στο σχήμα.

Και το πρόγραμμα μοιάζει με αυτό:

#define keypin() (!(PIND & _BV(KEY))) ISR(TIMER0_OVF_vect)( στατικό ανυπόγραφο char pos = 0; στατική ανυπόγραφη καταχώρηση χαρακτήρων = 0; στατικό ανυπόγραφο char tmp_key = 0; ROWS = 0; if(keypin( )) tmp_key |= 1<< pos; COLS |= 0x3F; if(!(blink & (1<< pos)) || (++entry &0x80)){ ROWS = (ROWS & 0xF0) | (SCR & 0x0F); COLS &= ~(1 << pos); } if(++pos == SCR_SZ){ pos = 0; key = tmp_key; tmp_key = 0; } }

Εδώ ΚΛΕΙΔΙ- αυτή είναι μια μακροεντολή που ορίζει το bit της επιλεγμένης θύρας στην οποία όλα τα κουμπιά είναι "συνδεδεμένα", μακροεντολή keypin()επιστρέφει τη λογική τιμή TRUE εάν η επιλεγμένη καρφίτσα είναι λογικά χαμηλή. Στο παράδειγμα, τα κουμπιά συνδέονται με PORTD.

Κάθε φορά που εμφανίζεται μια διακοπή του χρονοδιακόπτη, πρώτα σβήνουν όλα τα τμήματα - αυτό είναι απαραίτητο ώστε το ρεύμα που περνά από τις λυχνίες LED να μην έχει ως αποτέλεσμα την εσφαλμένη ανίχνευση του πατημένου κουμπιού. Μετά από αυτό, η είσοδος του κουμπιού μετράται - εάν η στάθμη είναι χαμηλή, σημαίνει ότι πατιέται το κουμπί που είναι συνδεδεμένο στην αντίστοιχη κάθοδο pos. Σε μεταβλητή tmp_keyΟι καταστάσεις κουμπιών συγκεντρώνονται και ξαναγράφονται σε μια καθολική μεταβλητή κλειδίμετά την ολοκλήρωση του κύκλου εμφάνισης. Το μόνο που έχετε να κάνετε είναι να αναλύετε το νόημα από καιρό σε καιρό κλειδίκαι να επεξεργαστείτε τα κλικ που εντοπίστηκαν:

Στατικός ανυπόγραφος χαρακτήρας get_key())( ανυπόγραφος χαρακτήρας tmp = 0; tmp = κλειδί; _delay_ms(10); if(key == tmp) επιστροφή tmp; αλλιώς επιστροφή 0; )

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

5 Τι άλλο;

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

Όπως είπα νωρίτερα, μπορείτε να προσθέσετε, ακόμη και ανεξάρτητη ρύθμιση για κάθε τμήμα.

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

Μπορείτε να σκεφτείτε την ενδιαφέρουσα ιδέα της αυτόματης προσαρμογής της φωτεινότητας της οθόνης ανάλογα με το επίπεδο φωτισμού του περιβάλλοντος. Όπως γνωρίζετε, οι ενδείξεις LED είναι λιγότερο ορατές όσο πιο σκούρο είναι - απλώς θολώνουν. Επομένως, στο σκοτάδι, είναι λογικό να μειωθεί η φωτεινότητα των ενδείξεων, αυξάνοντάς την κατά τη διάρκεια της ημέρας. Το πιο απλό πράγμα είναι να χρησιμοποιήσετε μια ξεχωριστή φωτοαντίσταση ή LED ως αισθητήρα φωτός, αλλά μπορείτε να το κάνετε διαφορετικά: είναι γνωστό ότι ένα LED μπορεί επίσης να λειτουργήσει ως φωτοδίοδος, επομένως, εάν χρησιμοποιήσετε τη θύρα που είναι συνδεδεμένη στην είσοδο για ένδειξη ADC, στη συνέχεια, αν θέλετε, μπορείτε να μετρήσετε το photo-emf του μη φωτεινού τμήματος της ένδειξης και να χρησιμοποιήσετε αυτήν την τιμή για να ρυθμίσετε τη φωτεινότητα...

Μπορείτε να σκεφτείτε τη χρήση του υλικού σειριακής εξόδου, το οποίο υπαινίχθηκα ήδη.

Μια ενδιαφέρουσα έκδοση μιας εντελώς καθολικής προσέγγισης στη δυναμική οθόνη, την οποία προτείνω επίσης να εξοικειωθείτε, προτάθηκε από MOLCHEC. Εν συντομία, η ουσία: η κατανομή των τμημάτων ανά bit συμβόλων, η αντιστοίχιση θυρών για τον έλεγχο του δείκτη, ακόμη και ο τύπος του δείκτη - εν συντομία, όλες, όλες, όλες οι παράμετροι - καθορίζονται με τη μορφή πίνακα διαμόρφωσης στο EEPROM. Με βάση αυτόν τον πίνακα, τα πάντα οργανώνονται μέσω προγραμματισμού: από την αντιστροφή ανάλογα με τον τύπο του δείκτη, έως την αναδιάταξη των bit σε διαφορετικές θύρες. Σε αυτήν την περίπτωση, ο πηγαίος κώδικας του προγράμματος δυναμικής εμφάνισης παραμένει πάντα αμετάβλητος και ο πίνακας ρυθμίσεων καταρτίζεται από τον τελικό χρήστη ανάλογα με τις προτιμήσεις του. Η μέθοδος είναι πραγματικά καθολική και ευέλικτη, αλλά σχετίζεται με αυξημένη κατανάλωση μνήμης προγράμματος.


3 αναρτήθηκε από ARV, στις 06:48 25/08/2010
Μίσα, αν ήμουν στη θέση σου, δεν θα έδινα τόσο κατηγορηματικές δηλώσεις «δεν μπορείς να το κάνεις», «κανείς δεν το έγραψε» ή «πνευματικά δικαιώματα», γιατί πρώτον, δεν είναι ευγενικό και δεύτερον:
1. Έκανα μια έρπουσα γραμμή σε μια μήτρα 10x16 πριν από πολύ καιρό (αυτό ήταν) - μπορείτε να βρείτε ένα βίντεο της λειτουργίας της σε αυτή τη σημείωση http://site/content/view/160/38/
2. Έγραψα ένα άρθρο (θα το βρείτε στις ειδήσεις - το τελευταίο για σήμερα) για το πώς να φτιάξετε ένα ticker σε LCD. Εάν καταπονήσετε λίγο τον εγκέφαλό σας, τότε το να επαναλάβετε τον αλγόριθμο για έξοδο σε μια μήτρα είναι ασήμαντο.
3. στον ιστότοπό μου δεν υπάρχει ούτε ένα άρθρο αντιγραμμένο από κάπου (το copy-paste δεν είναι πνευματική ιδιοκτησία, έκανες τυπογραφικό λάθος), όλα τα υλικά είναι εντελώς πρωτότυπα. Πολλοί ιστότοποι έχουν αντίγραφα αυτού του υλικού με την άδειά μου (ή την άδεια των δημιουργών του υλικού, οι οποίοι έχουν κάθε δικαίωμα να δημοσιεύουν το υλικό τους σε πολλά μέρη ταυτόχρονα).

Μόνο οι εγγεγραμμένοι χρήστες μπορούν να αφήσουν σχόλια.
Εγγραφείτε ή συνδεθείτε στον λογαριασμό σας.

Συνεχίζοντας το θέμα:
Υπολογιστή

Σήμερα, το Διαδίκτυο έχει γίνει αναπόσπαστο μέρος της καθημερινότητάς μας. Η συνεχής πρόσβαση στο παγκόσμιο δίκτυο είναι απαραίτητη προϋπόθεση για άνετη...

Νέα άρθρα
/
Δημοφιλής