Πίνακας περιεχομένων:

Μικροελεγκτής AVR. Εναλλαγή LED με χρήση διακόπτη με κουμπί. Κουμπί απωθήσεων: 4 βήματα
Μικροελεγκτής AVR. Εναλλαγή LED με χρήση διακόπτη με κουμπί. Κουμπί απωθήσεων: 4 βήματα

Βίντεο: Μικροελεγκτής AVR. Εναλλαγή LED με χρήση διακόπτη με κουμπί. Κουμπί απωθήσεων: 4 βήματα

Βίντεο: Μικροελεγκτής AVR. Εναλλαγή LED με χρήση διακόπτη με κουμπί. Κουμπί απωθήσεων: 4 βήματα
Βίντεο: Apa Itu Arduino Micro Controller (Subtittle) 2024, Νοέμβριος
Anonim
Image
Image

Σε αυτήν την ενότητα, θα μάθουμε πώς να δημιουργήσετε τον κωδικό προγράμματος C για το ATMega328PU για να αλλάξετε την κατάσταση των τριών LED σύμφωνα με την είσοδο από έναν διακόπτη κουμπιού. Επίσης, έχουμε διερευνήσει λύσεις στο πρόβλημα του "Switch Bounce". Ως συνήθως, θα συναρμολογήσουμε το ηλεκτρικό κύκλωμα στη βάση του AVR ATmega328 για να ελέγξουμε την εργασία του κώδικα προγράμματος.

Βήμα 1: Γράψιμο και δημιουργία εφαρμογών μικροελεγκτών AVR σε κώδικα C χρησιμοποιώντας την ενσωματωμένη πλατφόρμα ανάπτυξης Atmel Studio 7

Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κωδικό C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7
Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κωδικό C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7
Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κώδικα C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7
Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κώδικα C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7
Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κωδικό C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7
Γραφή και δημιουργία εφαρμογών μικροελεγκτών AVR σε κωδικό C χρησιμοποιώντας την πλατφόρμα ενσωματωμένης ανάπτυξης Atmel Studio 7

Εάν δεν έχετε Atmel Studio, θα πρέπει να το κατεβάσετε και να το εγκαταστήσετε.

www.microchip.com/mplab/avr-support/atmel-studio-7

Οι πρώτες λίγες γραμμές που έχουμε ορισμένους μεταγλωττιστές ορίζει.

Το F_CPU καθορίζει τη συχνότητα ρολογιού σε Hertz και είναι συνηθισμένο σε προγράμματα που χρησιμοποιούν τη βιβλιοθήκη avr-libc. Σε αυτήν την περίπτωση, χρησιμοποιείται από τις ρουτίνες καθυστέρησης για τον προσδιορισμό του τρόπου υπολογισμού των χρονικών καθυστερήσεων.

#ifndef F_CPU

#define F_CPU 16000000UL // ειδοποίηση κρυστάλλινης συχνότητας ελεγκτή (16 MHz AVR ATMega328P) #endif

#include // header για να ενεργοποιήσετε τον έλεγχο ροής δεδομένων στις ακίδες. Ορίζει ακίδες, θύρες κ.λπ.

Το πρώτο αρχείο περιλαμβάνει μέρος του avr-libc και θα χρησιμοποιηθεί σε σχεδόν οποιοδήποτε έργο AVR στο οποίο εργάζεστε. Το io.h θα καθορίσει τη CPU που χρησιμοποιείτε (γι 'αυτό καθορίζετε το μέρος κατά τη μεταγλώττιση) και με τη σειρά της θα περιλαμβάνει την κατάλληλη κεφαλίδα ορισμού IO για το τσιπ που χρησιμοποιούμε. Ορίζει απλώς τις σταθερές για όλες τις καρφίτσες, τις θύρες, τους ειδικούς καταχωρητές κ.λπ.

#include // header για να ενεργοποιήσετε τη λειτουργία καθυστέρησης στο πρόγραμμα

Η χρήση/καθυστέρηση της βιβλιοθήκης περιέχει μερικές ρουτίνες για μικρές καθυστερήσεις. Η συνάρτηση που θα χρησιμοποιήσουμε είναι _delay_ms ().

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

#define BUTTON1 1 // διακόπτης κουμπιού συνδεδεμένος στη θύρα Β pin 1

#define LED1 0 // Led1 συνδεδεμένο στη θύρα B pin 0 #define LED2 1 // Led2 συνδεδεμένο στη θύρα C pin 1 #define LED3 2 // Led3 συνδεδεμένο στη θύρα D pin 2

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

#define DEBOUNCE_TIME 25 // χρόνος αναμονής κατά το κουμπί "de-bouncing"

#define LOCK_INPUT_TIME 300 // χρόνος αναμονής μετά το πάτημα ενός κουμπιού

void init_ports_mcu ()

{

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

Για το κουμπί, θα χρησιμοποιούμε τους καταχωρητές PORT και PIN για εγγραφή και ανάγνωση. Με τα AVR, διαβάζουμε μια καρφίτσα χρησιμοποιώντας τον καταχωρητή PINx και γράφουμε σε μια καρφίτσα χρησιμοποιώντας τον καταχωρητή PORTx. Πρέπει να γράψουμε στον καταχωρητή κουμπιών για να ενεργοποιήσουμε τα pull-ups.

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

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

DDRB = 0xFFu; // Ορίστε όλες τις ακίδες του PORTB ως έξοδο.

Στη συνέχεια, ορίστε ρητά το pin του κουμπιού ως είσοδο.

DDRB & = ~ (1 <

Στη συνέχεια, οι ακίδες PORTB έχουν ρυθμιστεί σε υψηλό επίπεδο (+5 volt) για να τις ενεργοποιήσετε. Οι ακίδες εξόδου είναι αρχικά υψηλές και δεδομένου ότι η λυχνία LED είναι ενσύρματη-υψηλή, θα ενεργοποιηθεί αν δεν την απενεργοποιήσουμε ρητά.

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

PORTB = 0xFF; // Ορίστε όλες τις ακίδες του PORTB ως Υ HIGHΗΛΕΣ. Το Led είναι ενεργοποιημένο, // είναι επίσης ενεργοποιημένη η εσωτερική αντίσταση Pull Up της πρώτης ακίδας PORTB. DDRC = 0xFFu; // Ορίστε όλες τις ακίδες του PORTC ως έξοδο. PORTC = 0x00u; // Ρυθμίστε όλες τις ακίδες του PORTC χαμηλά, ώστε να απενεργοποιηθεί. DDRD = 0xFFu; // Ορίστε όλες τις ακίδες του PORTD ως έξοδο. PORTD = 0x00u; // Ρυθμίστε όλες τις καρφίτσες του PORTD χαμηλά και απενεργοποιείται. }

χωρίς υπογραφή char button_state ()

{

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

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

/ * το κουμπί πιέζεται όταν το κουμπί 1 bit είναι καθαρό */

εάν (! (PINB & (1 <

Το κάνουμε αυτό ελέγχοντας αν το bit είναι καθαρό. Εάν το bit είναι καθαρό, υποδεικνύοντας ότι το κουμπί είναι πατημένο, καθυστερούμε πρώτα για το χρονικό διάστημα που ορίζεται από το DEBOUNCE_TIME που είναι 25ms και στη συνέχεια ελέγχουμε ξανά την κατάσταση του κουμπιού. Εάν το κουμπί πατηθεί μετά τα 25ms τότε ο διακόπτης θεωρείται ότι έχει καταργηθεί και είναι έτοιμος να ενεργοποιήσει ένα συμβάν και έτσι επιστρέφουμε το 1 στη ρουτίνα κλήσεων. Εάν το κουμπί δεν είναι πατημένο, επιστρέφουμε το 0 στη ρουτίνα κλήσεων.

_delay_ms (DEBOUNCE_TIME);

εάν (! (PINB & (1 <

int main (άκυρο)

{

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

ανυπόγραφο char n_led = 1; // αρχικά ο αριθμός LED είναι αναμμένος τώρα

Κλήση της συνάρτησης για την προετοιμασία των ακίδων εισόδου/εξόδου που χρησιμοποιούνται:

init_ports_mcu ();

άπειρο βρόχο όπου τρέχει το πρόγραμμά μας:

ενώ (1)

{

Όταν το button_state επιστρέφει ένα που υποδεικνύει ότι το κουμπί έχει πατηθεί και αποσυρθεί, μετά εναλλάσσει την τρέχουσα κατάσταση των LED με τη σειρά, σύμφωνα με την παράμετρο n_led.

if (button_state ()) // Εάν πατηθεί το κουμπί, αλλάξτε την κατάσταση του LED και καθυστερήστε για 300ms (#define LOCK_INPUT_TIME)

{switch (n_led) {case 1: PORTB ^= (1 << LED1]; PORTC ^= (1 << LED2]; Διακοπή;

Αυτές οι δηλώσεις χρησιμοποιούν τελεστές C bitwise. Αυτή τη φορά χρησιμοποιεί τον αποκλειστικό χειριστή OR. Όταν XOR το PORT με την τιμή bit του bit που θέλετε να αλλάξετε, αυτό το ένα bit αλλάζει χωρίς να επηρεάσει τα άλλα bits.

περίπτωση 2:

PORTC ^= (1 << LED2]; PORTD ^= (1 << LED3]; Διακοπή; περίπτωση 3: PORTD ^= (1 << LED3); PORTB ^= (1 << LED1]; n_led = 0; // Επαναφορά διακοπής αριθμού LED. } n_led ++; // το επόμενο LED είναι ενεργοποιημένο _delay_ms (LOCK_INPUT_TIME). }} επιστροφή (0); }

Έτσι, τώρα, όταν εκτελείτε αυτό το πρόγραμμα, θα πρέπει να μπορείτε να πατήσετε το κουμπί στα LED που αλλάζουν. Λόγω της καθυστέρησής μας που ορίζεται από LOCK_INPUT_TIME, μπορείτε να πατήσετε και να κρατήσετε πατημένο το κουμπί που θα προκαλέσει την απενεργοποίηση και την ενεργοποίηση των LED με σταθερό ρυθμό (λίγο περισσότερο από κάθε 275ms).

Ο προγραμματισμός ολοκληρώθηκε.

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

Μπορείτε να κατεβάσετε το αρχείο main.c με το πρόγραμμα σε κώδικα c:

Βήμα 2: Μεταφορά του αρχείου HEX του προγράμματος στη μνήμη flash του τσιπ

Μεταφορά του αρχείου HEX του προγράμματος στη μνήμη flash του τσιπ
Μεταφορά του αρχείου HEX του προγράμματος στη μνήμη flash του τσιπ
Μεταφορά του αρχείου HEX του προγράμματος στη μνήμη flash του τσιπ
Μεταφορά του αρχείου HEX του προγράμματος στη μνήμη flash του τσιπ

Κατεβάστε και εγκαταστήστε το AVRDUDE. Η τελευταία διαθέσιμη έκδοση είναι 6.3: Λήψη του αρχείου zip

Αρχικά, αντιγράψτε το εξάγωνο αρχείο του προγράμματος στον κατάλογο AVRDUDE. Στην περίπτωσή μου είναι το ButtonAVR.hex

Στη συνέχεια, πληκτρολογήστε στο παράθυρο προτροπής DOS την εντολή: avrdude –c [όνομα προγραμματιστή] –p m328p –u –U flash: w: [όνομα του δεκαεξαδικού αρχείου σας].

Στην περίπτωσή μου είναι: avrdude –c ISPProgv1 –p m328p –u –U flash: w: ButtonAVR.hex

Αυτή η εντολή γράφει ένα δεκαεξαδικό αρχείο στη μνήμη του μικροελεγκτή.

Δείτε το βίντεο με μια λεπτομερή περιγραφή της καύσης μνήμης flash του μικροελεγκτή:

Μνήμη flash μικροελεγκτή που καίγεται…

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

Βήμα 3: Αποσύνδεση διακόπτη υλικού

Διακοπή υλικού Debouncing
Διακοπή υλικού Debouncing

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

Τι τιμή πυκνωτή πρέπει να επιλέξετε; Αυτό τελικά θα εξαρτηθεί από το πόσο κακή απόδοση έχει το κουμπί σχετικά με αυτό το συγκεκριμένο πρόβλημα. Ορισμένα κουμπιά μπορούν να εμφανίσουν μια τρομερή συμπεριφορά αναπήδησης, ενώ άλλα θα έχουν πολύ λίγα. Μια χαμηλή τιμή πυκνωτή όπως 1,0 nanofarads θα αντιδράσει πολύ γρήγορα, με μικρή ή καθόλου επίδραση στην αναπήδηση. Αντίστροφα, μια υψηλότερη τιμή πυκνωτή όπως τα 220 nanofarads (η οποία είναι ακόμα αρκετά μικρή όσον αφορά τους πυκνωτές) θα παρέχει μια αργή μετάβαση από την τάση έναρξης στην τελική τάση (5 volt έως 0 volt). Η μετάβαση που παρατηρείται με χωρητικότητα 220 nanofarads είναι ακόμα αρκετά γρήγορη με την πραγματική έννοια, ωστόσο, και έτσι μπορεί να χρησιμοποιηθεί σε κουμπιά κακής απόδοσης.

Βήμα 4: Ηλεκτρικό κύκλωμα

Ηλεκτρικό κύκλωμα
Ηλεκτρικό κύκλωμα
Ηλεκτρικό κύκλωμα
Ηλεκτρικό κύκλωμα
Ηλεκτρικό κύκλωμα
Ηλεκτρικό κύκλωμα

Συνδέστε εξαρτήματα σύμφωνα με το σχηματικό διάγραμμα.

Συνιστάται: