Προγραμματισμός μικροελεγκτών avr σε C. Προγραμματισμός μικροελεγκτών AVR σε C. Τι είναι λοιπόν ένας μικροελεγκτής

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

Περισσότερο λεπτομερείς πληροφορίεςμπορεί να προβληθεί στα αγγλικά στο Εγχειρίδιο χρήστη CodeVision και προτείνω επίσης τον ιστότοπο http://somecode.ru με μαθήματα βίντεο για το C για μικροελεγκτές και το βιβλίο "How to Program in C" από την Deitel, αυτό είναι το μόνο καλό βιβλίο με το οποίο ξεκίνησα ο ίδιος.

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

Το ίδιο το υλικολογισμικό έχει επέκταση .hex και είναι ένα σύνολο οδηγιών, με τη μορφή μονάδων και μηδενικών, το οποίο είναι κατανοητό από τον μικροελεγκτή. Από πού μπορώ να πάρω το υλικολογισμικό; Μπορείτε να το κατεβάσετε από ιστοσελίδες ηλεκτρονικών ειδών ή να το γράψετε μόνοι σας. Μπορείτε να το γράψετε σε ειδικά προγράμματα που ονομάζονται περιβάλλον ανάπτυξης. Τα πιο γνωστά σε μένα είναι τα AVR Studio, IAR, CodeVision, WinAVR... Είναι αδύνατο να πούμε ποιο από αυτά τα περιβάλλοντα είναι καλύτερο ή χειρότερο, για το καθένα το δικό του. Μπορούμε να πούμε ότι αυτά τα προγράμματα διαφέρουν κυρίως ως προς την ευκολία, τη γλώσσα προγραμματισμού και την τιμή. Σε αυτόν τον ιστότοπο, λαμβάνεται υπόψη μόνο το CodeVision.

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

Ένα αρχείο πηγαίου κώδικα είναι ένα σύνολο εντολών σε μια γλώσσα προγραμματισμού, καθήκον του CodeVision είναι να μεταφράσει αυτές τις εντολές σε δυαδικό κώδικα, καθήκον σας είναι να γράψετε αυτόν τον πηγαίο κώδικα. Το CodeVision κατανοεί τη γλώσσα C, τα αρχεία πηγαίου κώδικα έχουν την επέκταση ".c". Αλλά το CodeVision έχει κάποιες κατασκευές που δεν χρησιμοποιούνται στη C, γι' αυτό δεν αρέσει σε πολλούς προγραμματιστές και η γλώσσα που χρησιμοποιείται ονομάζεται C-like. Ωστόσο, αυτό δεν σας εμποδίζει να γράψετε σοβαρά έργα. Πολλά παραδείγματα, μια γεννήτρια κώδικα και ένα μεγάλο σύνολο βιβλιοθηκών δίνουν στο CodeVision ένα μεγάλο πλεονέκτημα. Το μόνο αρνητικό είναι ότι πληρώνεται, αν και υπάρχει δωρεάν εκδόσειςμε περιορισμό κωδικού.

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

#περιλαμβάνω void main(void) ( ) ;

#περιλαμβάνω void main(void) ( );

Πριν από την κύρια λειτουργία, μπορείτε να συνδέσετε τις απαραίτητες βιβλιοθήκες, να δηλώσετε καθολικές μεταβλητές, σταθερές και ρυθμίσεις. Μια βιβλιοθήκη είναι ένα ξεχωριστό αρχείο, συνήθως με επέκταση ".h", η οποία περιέχει ήδη προγραμμένο κώδικα. Σε ορισμένα έργα μπορεί να χρειαζόμαστε αυτόν τον κωδικό, αλλά σε άλλα δεν τον χρειαζόμαστε. Για παράδειγμα, σε ένα έργο χρησιμοποιούμε οθόνες LCD, αλλά σε ένα άλλο όχι. Μπορείτε να συνδέσετε τη βιβλιοθήκη για εργασία με την οθόνη LCD "alcd.h" ως εξής:

#περιλαμβάνω #περιλαμβάνω void main(void) ( ) ;

#περιλαμβάνω #περιλαμβάνω void main(void) ( );

Οι μεταβλητές είναι περιοχές της μνήμης στις οποίες μπορούν να τοποθετηθούν ορισμένες τιμές. Για παράδειγμα, εάν προσθέσετε δύο αριθμούς, πρέπει να αποθηκεύσετε το αποτέλεσμα κάπου για να το χρησιμοποιήσετε στο μέλλον. Πρώτα πρέπει να δηλώσετε τη μεταβλητή, δηλ. εκχωρήστε μνήμη για αυτό, για παράδειγμα:
int i=0;
εκείνοι. Δηλώσαμε τη μεταβλητή i και τοποθετήσαμε την τιμή 0 σε αυτήν, το int είναι ο τύπος της μεταβλητής ή πιο απλά σημαίνει το μέγεθος της εκχωρημένης μνήμης. Κάθε τύπος μεταβλητής μπορεί να αποθηκεύσει μόνο ένα συγκεκριμένο εύρος τιμών. Για παράδειγμα, το int μπορεί να γραφτεί ως αριθμοί από -32768 έως 32767. Εάν πρέπει να χρησιμοποιήσετε αριθμούς με κλασματικό μέρος, τότε η μεταβλητή πρέπει να δηλωθεί ως float· για χαρακτήρες, χρησιμοποιήστε τον τύπο char.

bit, _Bit 0 ή 1 char από -128 έως 127 ανυπόγραφο char από 0 έως 255 int από -32768 έως 32767 unsigned int από 0 έως 65535 long int από -2147483648 έως 21474893647 int από -2147483648 έως 21474893647 int από 2147483647 1,17 5e- 38 έως ±3,402e38

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

void main(void) ( while (1) ( ) ;) ;

void main(void) ( while (1) ( ); );

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

/*Βασικές μαθηματικές πράξεις:*/ int i= 0 ; //δηλώνει τη μεταβλητή i και της εκχωρεί την τιμή 0//Προσθήκη: i = 2 + 2 ; //Αφαίρεση: i = 2 - 2 ; //μετά την εκτέλεση αυτής της έκφρασης, η μεταβλητή i θα είναι ίση με 0//Πολλαπλασιασμός: i = 2 * 2 ; //μετά την εκτέλεση αυτής της έκφρασης, η μεταβλητή i θα είναι ίση με 4//Διαίρεση: i = 2 / 2 ; //μετά την εκτέλεση αυτής της έκφρασης, η μεταβλητή i θα είναι ίση με 1

/*Βασικές μαθηματικές πράξεις:*/ int i=0; //δηλώνει τη μεταβλητή i και της εκχωρεί την τιμή 0 //Προσθήκη: i = 2+2; //μετά την εκτέλεση αυτής της παράστασης, η μεταβλητή i θα είναι ίση με 4 //Αφαίρεση: i = 2-2; //μετά την εκτέλεση αυτής της παράστασης, η μεταβλητή i θα είναι ίση με 0 //Πολλαπλασιασμός: i = 2*2; //μετά την εκτέλεση αυτής της παράστασης, η μεταβλητή i θα είναι ίση με 4 //Διαίρεση: i = 2/2; //μετά την εκτέλεση αυτής της έκφρασης, η μεταβλητή i θα είναι ίση με 1

Συχνά, ένα πρόγραμμα χρειάζεται να μεταβεί από το ένα κομμάτι κώδικα στο άλλο, ανάλογα με τις συνθήκες· για αυτό, υπάρχουν λειτουργίες if() υπό όρους, για παράδειγμα:

if(i>3) //αν το i είναι μεγαλύτερο από 3, τότε αντιστοιχίστε στο i την τιμή 0 ( i=0; ) /*αν το i είναι μικρότερο από 3, τότε μεταβείτε στον κωδικό που ακολουθεί το σώμα της συνθήκης, δηλ. μετά από αγκύλες ()*/

Επίσης εάν μπορεί να χρησιμοποιηθεί σε συνδυασμό με άλλα - διαφορετικά

αν εγώ<3) //если i меньше 3, то присвоить i значение 0 { i=0; } else { i=5; //иначе, т.е. если i больше 3, присвоить значение 5 }

Υπάρχει επίσης ένας τελεστής σύγκρισης "==", ο οποίος δεν πρέπει να συγχέεται με την εκχώρηση "=". Η αντίστροφη πράξη δεν ισούται με "!=", ας πούμε

if(i==3)//εάν i είναι 3, αντιστοιχίστε στο i την τιμή 0 ( i=0; ) εάν(i!=5) //εάν i δεν είναι 5, αντιστοιχίστε στο i την τιμή 0 ( i=0; )

Ας περάσουμε σε πιο σύνθετα πράγματα - λειτουργίες. Ας υποθέσουμε ότι έχετε ένα συγκεκριμένο κομμάτι κώδικα που επαναλαμβάνεται πολλές φορές. Επιπλέον, αυτός ο κωδικός είναι αρκετά μεγάλος σε μέγεθος. Είναι άβολο να το γράφεις κάθε φορά. Για παράδειγμα, σε ένα πρόγραμμα που με κάποιο τρόπο αλλάζει τη μεταβλητή i, όταν πατάτε το κουμπί 0 και 3 της θύρας D, εκτελείται ο ίδιος κώδικας, ο οποίος, ανάλογα με την τιμή της μεταβλητής i, ενεργοποιεί τα σκέλη της θύρας Β.

void main(void) ( if (PIND.0== 0 ) //ελέγξτε εάν είναι πατημένο το κουμπί στο PD0( αν (i== 0 ) //if i==0 ενεργοποιήστε το PB0( PORTB.0= 1 ; ) εάν (i== 5 ) // εάν i==5 ενεργοποιήστε το PB1( PORTB.1= 1 ; ) ) … εάν (PIND.3== 0 ) // κάντε το ίδιο πράγμα όταν ελέγχετε το κουμπί PD3( αν (i== 0 ) ( PORTB.0= 1 ; ) εάν (i== 5 ) ( PORTB.1= 1 ; ) )

void main(void) ( if(PIND.0==0) //ελέγξτε αν έχει πατηθεί το κουμπί στο PD0 ( if(i==0) //if i==0 ενεργοποιήστε το PB0 ( PORTB.0=1; ) if( i==5) // if i==5 ενεργοποιήστε το PB1 ( PORTB.1=1; ) ) ... if(PIND.3==0) // κάντε το ίδιο πράγμα όταν ελέγχετε το κουμπί PD3 ( if(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) )

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

void i_check() ( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) )

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) )

void σημαίνει ότι η συνάρτηση δεν επιστρέφει τίποτα, περισσότερα για αυτό παρακάτω i_check() - αυτό είναι το όνομα της συνάρτησής μας, μπορείτε να την ονομάσετε όπως θέλετε, την ονόμασα ακριβώς έτσι - ελέγξτε το i. Τώρα μπορούμε να ξαναγράψουμε τον κώδικα μας:

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //ελέγξτε εάν το κουμπί στο PD0 είναι πατημένο ( i_check(); ) ... if(PIND.3==0) ( i_check(); ) )

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

Φαίνεται πολύ πιο ενδιαφέρον να χρησιμοποιείτε μια συνάρτηση όταν παίρνει τιμές, για παράδειγμα, υπάρχει μια μεταβλητή c και υπάρχει ένα άθροισμα συνάρτησης που παίρνει δύο τιμές τύπου int. Όταν το κύριο πρόγραμμα εκτελέσει αυτήν τη συνάρτηση, τα ορίσματα θα βρίσκονται ήδη σε παρένθεση, οπότε το "a" θα γίνει ίσο με δύο και το "b" θα γίνει ίσο με 1. Η συνάρτηση θα εκτελεστεί και το "c" θα γίνει ίσο με 3 .

int c= 0 ; void sum(int a, int b) (c= a+ b; ) void main(void) (άθροισμα(2, 1) ;)

int c=0; void sum(int a, int b) (c=a+b; ) void main(void) (sum(2,1); )

Μία από τις πιο κοινές παρόμοιες λειτουργίες είναι η μετακίνηση του δρομέα στην οθόνη LCD lcd_gotoxy(0,0). το οποίο, παρεμπιπτόντως, παίρνει επίσης ορίσματα - συντεταγμένες x και y.

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

int c= 0 ; int sum(int a, int b) ( return a+ b; ) void main(void) (с= sum(2, 1) ; )

int c=0; int sum(int a, int b) ( return a+b; ) void main(void) (с=sum(2,1); )

Το αποτέλεσμα θα είναι ίδιο με την τελευταία φορά c=3, αλλά σημειώστε ότι εκχωρούμε στη μεταβλητή “c” την τιμή μιας συνάρτησης που δεν είναι πλέον άκυρη, αλλά επιστρέφει το άθροισμα δύο αριθμών τύπου int. Με αυτόν τον τρόπο δεν είμαστε συνδεδεμένοι με μια συγκεκριμένη μεταβλητή «c», η οποία προσθέτει ευελιξία στη χρήση συναρτήσεων. Ένα απλό παράδειγμα μιας τέτοιας συνάρτησης είναι η ανάγνωση δεδομένων ADC, η συνάρτηση επιστρέφει τη μετρούμενη τιμή result=read_adc();. Ας τελειώσουμε με τις λειτουργίες.

Τώρα ας προχωρήσουμε στους πίνακες. Ένας πίνακας είναι σχετικές μεταβλητές. Για παράδειγμα, έχετε έναν ημιτονοειδή πίνακα με πολλά σημεία, δεν θα δημιουργήσετε μεταβλητές int sinus1=0; int sinus2=1; και τα λοιπά. Για αυτό χρησιμοποιείται ένας πίνακας. Για παράδειγμα, μπορείτε να δημιουργήσετε έναν πίνακα τριών στοιχείων όπως αυτό:
int sinus=(0,1,5);
Ο συνολικός αριθμός των στοιχείων του πίνακα υποδεικνύεται σε αγκύλες. Μπορείτε να αντιστοιχίσετε την τιμή του τρίτου στοιχείου στη μεταβλητή "c" ως εξής:
σ= κόλπος;
Σημειώστε ότι η αρίθμηση των στοιχείων του πίνακα ξεκινά από το μηδέν, δηλ. Το "c" θα γίνει ίσο με πέντε. Αυτή η συστοιχία δεν έχει στοιχείο κόλπων!!!
Μπορείτε να αντιστοιχίσετε μια τιμή σε ένα μεμονωμένο στοιχείο όπως αυτό:
κόλπος=10;

Ίσως έχετε ήδη παρατηρήσει ότι το CodeVision δεν έχει μεταβλητές συμβολοσειράς. Εκείνοι. δεν μπορείτε να δημιουργήσετε μια μεταβλητή συμβολοσειρά hello=”hello”; Για να γίνει αυτό, θα πρέπει να δημιουργήσετε μια σειρά μεμονωμένων χαρακτήρων.

lcd_putchar(γεια); lcd_putchar(γεια); lcd_putchar(γεια);

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

ενώ (PINB.0!=0) ( )

Μέχρι να πατηθεί το κουμπί, μην κάνετε τίποτα - εκτελέστε έναν κενό βρόχο.

Μια άλλη επιλογή είναι ο βρόχος for

int i? για (i= 0; i< 6 ; i++ ) { lcd_putchar(hello[ i] ) ; }

int i? για(i=0;i<6;i++) { lcd_putchar(hello[i]); }

Το νόημα είναι ακριβώς το ίδιο με αυτό του while, προστίθεται μόνο η αρχική συνθήκη i=0 και η συνθήκη που εκτελείται σε κάθε κύκλο i++. Ο κώδικας μέσα στον βρόχο είναι όσο το δυνατόν πιο απλοποιημένος.

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

Δεν πρέπει να προσπαθήσετε αμέσως να χρησιμοποιήσετε βρόχους, πίνακες και συναρτήσεις στο υλικολογισμικό σας. Το κύριο καθήκον σας είναι να κάνετε το υλικολογισμικό να λειτουργεί, οπότε κάντε το καθώς είναι πιο εύκολο για εσάς και μην δίνετε σημασία στο μέγεθος του κώδικα. Θα έρθει η στιγμή που θα θέλετε όχι μόνο να γράψετε κώδικα εργασίας, αλλά να τον γράψετε όμορφα και συμπαγή. Τότε θα είναι δυνατό να εμβαθύνουμε στην άγρια ​​φύση της γλώσσας C. Για όσους θέλουν να κατακτήσουν τα πάντα, προτείνω για άλλη μια φορά το βιβλίο "How to Program in C", υπάρχουν πολλά παραδείγματα και εργασίες. Εγκαταστήστε το Visual Studio, δημιουργήστε μια εφαρμογή κονσόλας win32 και εξασκηθείτε εκεί όσο ικανοποιεί η καρδιά σας.

Μάθημα 0.

Έτσι, σήμερα ανοίγουμε μια σειρά μαθημάτων προγραμματισμού μικροελεγκτών της οικογένειας AVR.

Σήμερα θα εξεταστούν τα ακόλουθα ερωτήματα:

  1. Τι είναι ένας μικροελεγκτής;
  2. Πού χρησιμοποιούνται οι μικροελεγκτές;

Εισαγωγή.

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

Τι είναι λοιπόν ένας μικροελεγκτής;

Μικροελεγκτής (Μονάδα Micro Controller, MCU) - ένα μικροκύκλωμα σχεδιασμένο για τον έλεγχο ηλεκτρονικών συσκευών. Μπορείτε να το φανταστείτε ως έναν απλό υπολογιστή ικανό να αλληλεπιδρά με εξωτερικές συσκευές. Για παράδειγμα, άνοιγμα και κλείσιμο τρανζίστορ, λήψη δεδομένων από αισθητήρες θερμοκρασίας, εμφάνιση δεδομένων σε οθόνες LCD κ.λπ. Επιπλέον, ο μικροελεγκτής μπορεί να εκτελέσει διάφορες επεξεργασίες δεδομένων εισόδου, όπως ακριβώς ο προσωπικός σας υπολογιστής.

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

Πού χρησιμοποιούνται οι μικροελεγκτές;

  1. Οικιακές συσκευές (πλυντήρια, φούρνοι μικροκυμάτων κ.λπ.).
  2. Κινητή τεχνολογία (Ρομπότ, ρομποτικά συστήματα, εξοπλισμός επικοινωνιών κ.λπ.).
  3. Βιομηχανικός εξοπλισμός (συστήματα ελέγχου μηχανών).
  4. Τεχνολογία Η/Υ (Μητρικές πλακέτες, συστήματα ελέγχου περιφερειακών συσκευών).
  5. Εξοπλισμός ψυχαγωγίας (Παιδικά παιχνίδια, διακοσμητικά).
  6. Μεταφορές (συστήματα ελέγχου κινητήρα αυτοκινήτου, συστήματα ασφαλείας)

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

Ξεκινώντας με το AVR

AVR- μια οικογένεια μικροελεγκτών της Atmel. Έχουν επαρκή απόδοση για τις περισσότερες ερασιτεχνικές συσκευές. Χρησιμοποιούνται επίσης ευρέως στη βιομηχανία.

Το σχηματικό διάγραμμα του προγραμματιστή θύρας LPT φαίνεται στο σχήμα. Ως οδηγός λεωφορείου, χρησιμοποιήστε το μικροκύκλωμα 74AC 244 ή 74HC244 (K1564AP5), 74LS244 (K555AP5) ή 74ALS244 (K1533AP5).

Η λυχνία LED VD1 υποδεικνύει τη λειτουργία εγγραφής του μικροελεγκτή,

LED VD2 - ανάγνωση,

LED VD3 - παρουσία τροφοδοσίας στο κύκλωμα.

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

Ο προγραμματιστής μπορεί να κατασκευαστεί σε μια πλακέτα τυπωμένου κυκλώματος και να τοποθετηθεί στο περίβλημα του βύσματος LPT, όπως φαίνεται στα σχήματα:




Για να εργαστείτε με τον προγραμματιστή, είναι βολικό να χρησιμοποιήσετε μια επέκταση θύρας LPT, η οποία είναι εύκολο να φτιάξετε μόνοι σας (για παράδειγμα, από ένα καλώδιο Centronix για έναν εκτυπωτή), το κύριο πράγμα είναι να μην εξοικονομήσετε τους αγωγούς για το έδαφος (18- 25 πόδια σύνδεσης) ή αγοράστε. Το καλώδιο μεταξύ του προγραμματιστή και του προγραμματιζόμενου τσιπ δεν πρέπει να υπερβαίνει τα 20-30 cm.

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

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

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

Λειτουργίες bitwise

Τις περισσότερες φορές, κατά τον προγραμματισμό μικροελεγκτών AVR, το χρησιμοποιούσαμε, καθώς είναι πιο οπτικό σε σύγκριση με και είναι καλά κατανοητό για αρχάριους προγραμματιστές MK. Για παράδειγμα, πρέπει να ορίσουμε μόνο το 3ο bit της θύρας D. Για να γίνει αυτό, όπως ήδη γνωρίζουμε, μπορούμε να χρησιμοποιήσουμε τον ακόλουθο δυαδικό κώδικα:

PORTD = 0b00001000;

Ωστόσο, με αυτήν την εντολή ορίζουμε το 3ο ψηφίο σε ένα και μηδενίζουμε όλα τα άλλα (0, 1, 2, 4, 5, 6 και 7ο). Τώρα ας φανταστούμε μια κατάσταση όπου το 6ο και το 7ο bit χρησιμοποιούνται ως είσοδοι ADC και αυτή τη στιγμή λαμβάνεται ένα σήμα από κάποια συσκευή στις αντίστοιχες ακίδες MK και χρησιμοποιούμε την παραπάνω εντολή για να επαναφέρουμε αυτά τα σήματα. Ως αποτέλεσμα, ο μικροελεγκτής δεν τα βλέπει και πιστεύει ότι τα σήματα δεν έφτασαν. Επομένως, αντί για μια τέτοια εντολή, θα πρέπει να χρησιμοποιήσουμε μια άλλη που θα ορίζει μόνο το 3ο bit σε ένα, χωρίς να επηρεάζει τα υπόλοιπα bit. Για να γίνει αυτό, συνήθως χρησιμοποιείται η ακόλουθη λειτουργία bitwise:

PORTD |= (1<<3);

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

εάν (PIND == 0b00000000)

(οποιοσδήποτε κωδικός)

Ωστόσο, με τη βοήθειά του ελέγχουμε όχι μόνο το 3ο bit, αλλά όλα τα bit του καταχωρητή PIND ταυτόχρονα. Επομένως, ακόμα κι αν πατηθεί το κουμπί και γίνει επαναφορά του επιθυμητού bit, αλλά αυτή τη στιγμή λαμβάνεται ένα σήμα σε κάποια άλλη ακίδα της θύρας D, η αντίστοιχη τιμή θα οριστεί σε ένα και η συνθήκη στις παρενθέσεις θα είναι ψευδής. Ως αποτέλεσμα, ο κωδικός μέσα στα σγουρά στηρίγματα δεν θα εκτελεστεί ακόμη και όταν πατηθεί το κουμπί. Επομένως, για να ελέγξετε την κατάσταση ενός μεμονωμένου 3ου bit του καταχωρητή PIND, θα πρέπει να χρησιμοποιηθεί μια λειτουργία bitwise:

εάν (~PIND & (1<<3))

(οποιοσδήποτε κωδικός)

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

Ρύθμιση ενός μόνο bit

Για να ορίσετε ένα μεμονωμένο bit, όπως η θύρα D, χρησιμοποιείται μια λειτουργία bitwise OR. Αυτό χρησιμοποιήσαμε στην αρχή του άρθρου.

PORTD = 0b00011100; // αρχική τιμή

PORTD = PORTD | (1<<0); применяем побитовую ИЛИ

PORTD |= (1<<0); // сокращенная форма записи

PORTD == 0b00011101; // αποτέλεσμα

Αυτή η εντολή ορίζει το μηδενικό bit και αφήνει τα υπόλοιπα αμετάβλητα.

Για παράδειγμα, ας εγκαταστήσουμε ένα άλλο 6ο bit της θύρας D.

PORTD = 0b00011100; // αρχική κατάσταση θύρας

PORTD |= (1<<6); //

PORTD == 0b01011100; // αποτέλεσμα

Για να γράψετε ένα έως πολλά ξεχωριστά bit ταυτόχρονα, για παράδειγμα τη μηδέν, την έκτη και την έβδομη θύρα σιΙσχύει ο ακόλουθος συμβολισμός.

PORTB = 0b00011100; // αρχική τιμή

PORTB |= (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101; // αποτέλεσμα

Επαναφορά (μηδενισμός) μεμονωμένων bit

Για να επαναφέρετε ένα μεμονωμένο bit, χρησιμοποιούνται ταυτόχρονα τρεις εντολές που συζητήθηκαν προηγουμένως: .

Ας επαναφέρουμε το 3ο bit του καταχωρητή PORTC και ας αφήσουμε τα υπόλοιπα αμετάβλητα.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Ας εκτελέσουμε παρόμοιες ενέργειες για το 2ο και το 4ο ψηφίο:

PORTC = 0b00111110;

PORTC &= ~((1<<2) | (1<<4));

PORTC == 0b00101010;

Εναλλαγή bit

Εκτός από τη ρύθμιση και την επαναφορά, χρησιμοποιείται επίσης μια χρήσιμη εντολή που αλλάζει ένα bit στην αντίθετη κατάσταση: ένα στο μηδέν και αντίστροφα. Αυτή η λογική λειτουργία χρησιμοποιείται ευρέως για τη δημιουργία διαφόρων εφέ φωτισμού, για παράδειγμα, μια γιρλάντα Πρωτοχρονιάς. Ας δούμε το παράδειγμα της ΠΟΡΤΑ

ΠΟΡΤΑ = 0b00011111;

ΠΟΡΤΑ ^= (1<<2);

ΠΟΡΤΑ == 0b00011011;

Ας αλλάξουμε την κατάσταση του μηδενικού, του δεύτερου και του έκτου bit:

ΠΟΡΤΑ = 0b00011111;

ΠΟΡΤΑ ^= (1<<0) | (1<<2) | (1<<6);

ΠΟΡΤΑ == 0b01011010;

Έλεγχος της κατάστασης ενός μεμονωμένου bit. Να σας υπενθυμίσω ότι ο έλεγχος (σε αντίθεση με την εγγραφή) μιας θύρας I/O πραγματοποιείται με την ανάγνωση δεδομένων από τον καταχωρητή PIN.

Τις περισσότερες φορές, η δοκιμή εκτελείται με μία από τις δύο εντολές βρόχου: if και while. Γνωρίζουμε ήδη νωρίτερα αυτούς τους τελεστές.

Έλεγχος του bit για την παρουσία ενός λογικού μηδενός (επαναφορά) με αν

εάν (0==(PIND & (1<<3)))

Εάν το τρίτο bit της θύρας D διαγραφεί, τότε εκτελείται ο Code1. Διαφορετικά, εκτελείται ο Code2.

Παρόμοιες ενέργειες εκτελούνται με αυτήν τη μορφή εγγραφής:

εάν (~PIND & (1<<3))

Έλεγχος του bit για παρουσία λογικής μονάδας (ρύθμισης) με αν

αν (0 != (PIND & (1<<3)))

εάν (PIND & (1<<3))

Οι δύο παραπάνω βρόχοι λειτουργούν παρόμοια, αλλά μπορούν, λόγω της ευελιξίας της γλώσσας προγραμματισμού C, να έχουν διαφορετική μορφή σημειογραφίας. Ο τελεστής != σημαίνει όχι ίσος. Εάν το τρίτο bit της θύρας εισόδου/εξόδου PD έχει οριστεί (ένα), τότε εκτελείται ο Κώδικας1, εάν όχι, ο Κώδικας2.

Αναμονή για επαναφορά του bit ενώ

ενώ (PIND & (1<<5))

Ο Κώδικας1 θα εκτελεστεί όσο έχει οριστεί το 5ο bit του καταχωρητή PIND. Όταν το επαναφέρετε, ο Code2 θα ξεκινήσει να εκτελείται.

Αναμονή για τη ρύθμιση του bit ενώ

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

Οι μικροελεγκτές (εφεξής MK) έχουν μπει σταθερά στη ζωή μας· στο Διαδίκτυο μπορείτε να βρείτε πολλά ενδιαφέροντα κυκλώματα που εκτελούνται στο MK. Τι δεν μπορείτε να συναρμολογήσετε σε ένα MK: διάφορες ενδείξεις, βολτόμετρα, οικιακές συσκευές (συσκευές προστασίας, συσκευές μεταγωγής, θερμόμετρα...), ανιχνευτές μετάλλων, διάφορα παιχνίδια, ρομπότ κ.λπ. Η λίστα μπορεί να διαρκέσει πολύ. Είδα το πρώτο κύκλωμα σε έναν μικροελεγκτή πριν από 5-6 χρόνια σε ένα ραδιοφωνικό περιοδικό και σχεδόν αμέσως γύρισα σελίδα, σκεπτόμενος «Ακόμα δεν θα μπορώ να το συναρμολογήσω». Πράγματι, εκείνη την εποχή τα MK ήταν μια πολύ περίπλοκη και παρεξηγημένη συσκευή για μένα· δεν είχα ιδέα πώς λειτουργούσαν, πώς να τα flash και τι να τα κάνω σε περίπτωση λανθασμένου υλικολογισμικού. Αλλά πριν από περίπου ένα χρόνο, συναρμολόγησα για πρώτη φορά το πρώτο μου κύκλωμα σε ένα MK· ήταν ένα ψηφιακό κύκλωμα βολτόμετρου βασισμένο σε 7 δείκτες τμημάτων και έναν μικροελεγκτή ATmega8. Έτυχε να αγόρασα έναν μικροελεγκτή τυχαία, όταν στεκόμουν στο τμήμα εξαρτημάτων του ραδιοφώνου, ο τύπος μπροστά μου αγόραζε ένα MK και αποφάσισα επίσης να το αγοράσω και να προσπαθήσω να συναρμολογήσω κάτι. Στα άρθρα μου θα σας μιλήσω για Μικροελεγκτές AVR, θα σας μάθω πώς να δουλέψετε μαζί τους, θα δούμε προγράμματα για υλικολογισμικό, θα φτιάξουμε έναν απλό και αξιόπιστο προγραμματιστή, θα εξετάσουμε τη διαδικασία του υλικολογισμικού και, το πιο σημαντικό, τα προβλήματα που μπορεί να προκύψουν δεν μόνο για αρχάριους.

Βασικές παράμετροι ορισμένων μικροελεγκτών της οικογένειας AVR:

Μικροελεγκτής

Μνήμη flash

Μνήμη RAM

Μνήμη EEPROM

Θύρες I/O

U δύναμη

Πρόσθετες παράμετροι του mega μικροελεγκτή AVR:

Θερμοκρασία λειτουργίας: -55…+125*С
Θερμοκρασία αποθήκευσης: -65…+150*С
Τάση στον ακροδέκτη RESET σε σχέση με το GND: max 13V
Μέγιστη τάση τροφοδοσίας: 6,0V
Μέγιστο ρεύμα γραμμής I/O: 40mA
Μέγιστο ρεύμα τροφοδοσίας VCC και GND: 200mA

Pinouts μοντέλου ATmega 8X

Pinouts για μοντέλα ATmega48x, 88x, 168x

Διάταξη καρφίτσας για μοντέλα ATmega8515x

Διάταξη καρφίτσας για μοντέλα ATmega8535x

Διάταξη καρφίτσας για μοντέλα ATmega16, 32x

Διάταξη καρφίτσας για μοντέλα ATtiny2313

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

MK AVR εγκατάσταση FUSE bits

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

Οι πιο δημοφιλείς μικροελεγκτές μεταξύ των ραδιοερασιτέχνων είναι ο ATmega8 και ακολουθούν οι ATmega48, 16, 32, ATtiny2313 και άλλοι. Οι μικροελεγκτές πωλούνται σε πακέτα TQFP και DIP· για αρχάριους, προτείνω την αγορά σε DIP. Εάν αγοράσετε TQFP, θα είναι πιο προβληματικό να τα αναβοσβήσετε· θα πρέπει να αγοράσετε ή να κολλήσετε την πλακέτα επειδή τα πόδια τους βρίσκονται πολύ κοντά το ένα στο άλλο. Σας συμβουλεύω να εγκαταστήσετε μικροελεγκτές σε πακέτα DIP σε ειδικές υποδοχές, είναι βολικό και πρακτικό, δεν χρειάζεται να ξεκολλήσετε το MK εάν θέλετε να το επαναφέρετε ή να το χρησιμοποιήσετε για άλλο σχέδιο.

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

Για τον προγραμματισμό χρησιμοποιούνται 6 ακίδες:
ΕΠΑΝΑΦΟΡΑ- Είσοδος MK
VCC- Συν τροφοδοσία, 3-5V, εξαρτάται από το MK
GND- Κοινό καλώδιο, μείον την ισχύ.
MOSI- Είσοδος MK (σήμα πληροφοριών σε MK)
MISO- Έξοδος MK (σήμα πληροφοριών από MK)
SCK- Είσοδος MK (σήμα ρολογιού σε MK)

Μερικές φορές χρησιμοποιούν επίσης τις ακίδες XTAL 1 και XTAL2· ο χαλαζίας συνδέεται σε αυτές τις ακίδες εάν ο MK τροφοδοτείται από έναν εξωτερικό ταλαντωτή· στα ATmega 64 και 128, οι ακίδες MOSI και MISO δεν χρησιμοποιούνται για προγραμματισμό ISP· αντίθετα, οι ακίδες MOSI είναι συνδέεται με τον ακροδέκτη PE0 και το MISO με τον ακροδέκτη PE1. Κατά τη σύνδεση του μικροελεγκτή στον προγραμματιστή, τα καλώδια σύνδεσης πρέπει να είναι όσο το δυνατόν πιο κοντά και το καλώδιο που εκτείνεται από τον προγραμματιστή στη θύρα LPT δεν πρέπει επίσης να είναι πολύ μακρύ.

Η σήμανση του μικροελεγκτή μπορεί να περιέχει περίεργα γράμματα με αριθμούς, για παράδειγμα Atmega 8L 16PU, 8 16AU, 8A PU, κλπ. Το γράμμα L σημαίνει ότι το MK λειτουργεί σε χαμηλότερη τάση από το MK χωρίς το γράμμα L, συνήθως 2,7V. Οι αριθμοί μετά την παύλα ή το διάστημα 16PU ή 8AU υποδεικνύουν την εσωτερική συχνότητα της γεννήτριας που βρίσκεται στο MK. Εάν οι ασφάλειες έχουν ρυθμιστεί να λειτουργούν από εξωτερικό χαλαζία, ο χαλαζίας πρέπει να ρυθμιστεί σε συχνότητα που δεν υπερβαίνει τη μέγιστη σύμφωνα με το φύλλο δεδομένων, αυτή είναι 20 MHz για το ATmega48/88/168 και 16 MHz για άλλα atmega.


Μπλουζα