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

Έτσι, φορτώνετε το STM32duino Bootloader στο "Blue Pill" σας Τι γίνεται τώρα ;: 7 βήματα
Έτσι, φορτώνετε το STM32duino Bootloader στο "Blue Pill" σας Τι γίνεται τώρα ;: 7 βήματα

Βίντεο: Έτσι, φορτώνετε το STM32duino Bootloader στο "Blue Pill" σας Τι γίνεται τώρα ;: 7 βήματα

Βίντεο: Έτσι, φορτώνετε το STM32duino Bootloader στο
Βίντεο: Βασίλης Παπακωνσταντίνου - Χρόνια Φορτώνω - Official Audio Release 2024, Ιούλιος
Anonim
Έτσι, φορτώνετε το πρόγραμμα εκκίνησης STM32duino στο δικό σας
Έτσι, φορτώνετε το πρόγραμμα εκκίνησης STM32duino στο δικό σας
Έτσι, φορτώνετε το πρόγραμμα εκκίνησης STM32duino στο δικό σας
Έτσι, φορτώνετε το πρόγραμμα εκκίνησης STM32duino στο δικό σας

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

Το πρόβλημα είναι ότι πολλά, αν όχι όλα τα παραδείγματα για το "Generic" STM32 δεν θα λειτουργήσουν έξω από το κουτί. Θα χρειαστούν μικρές αλλαγές για να εργαστείτε στη συνέχεια στον πίνακα STM32 "Blue Pill".

Θα επιλέξω 4 παραδείγματα κώδικα για να εξηγήσω τι πρέπει να αλλάξει και γιατί. Οι κωδικοί είναι: "BlinkWithoutDelay", "Fading", "Dimmer" και "AnalogInSerial".

Σημείωση ΔΕΝ κωδικοποίησα τίποτα. Απλώς εκδίδω μικρές αλλαγές στους κωδικούς που δημιουργήθηκαν από:

David A. Mellis και τροποποιήθηκε αργά από τους Tom Igoe, Marti Bolivar και μερικές περιπτώσεις από τον Scott Fitzgerald

Tom Igoe και αργά τροποποιήθηκε από τον Bryan Newbold

Έτσι, προτιμώ να διατηρώ τα ονόματα των συγγραφέων ακόμη και σε κωδικούς που τροποποιώ, διατηρώντας την πίστωση δημιουργίας.

Βήμα 1: Καρφίτσες και καρφίτσες…. Γιατί ο κώδικας δεν λειτουργεί;

Καρφίτσες και καρφίτσες…. Γιατί ο κωδικός δεν λειτουργεί
Καρφίτσες και καρφίτσες…. Γιατί ο κωδικός δεν λειτουργεί

Ας ρίξουμε μια ματιά στην καρφίτσα STM32 "Blue Pill". Σημειώστε ότι οι ακίδες αναγνωρίζονται ως PA1 ή PC2…. Κάτι τέτοιο.

Αν ρίξετε μια ματιά, για παράδειγμα, στο παράδειγμα κώδικα "BlinkWithoutDelay", το pin δηλώνεται ως "33"…. Γιατί;

Υποψιάζομαι ότι αυτό οφείλεται στο γεγονός ότι ο κ. Marti Bolivar μετέφερε αυτόν τον κωδικό για τον πίνακα MAPLE.

Νομίζω ότι δεν ήταν η πρόθεσή του να αφήσει κωδικό συμβατό με τις σανίδες "Blue Pill".

Οι καρφίτσες σφενδάμου Maple και Maple είναι αριθμητικές, όπως το Arduino, αν και χρησιμοποιούν αριθμούς όπως 33, 24 και μερικούς σαν αυτόν.

Είπα ότι ο κωδικός δεν λειτουργεί; Λάθος μου. Ο κώδικας μεταγλωττίζεται χωρίς κανένα σφάλμα και μεταφορτώνεται σωστά στο "Blue Pill", οπότε, κατά τη γνώμη μου, όντως λειτουργεί, αλλά δεν χρησιμοποιούμε έξοδο GPIO. Μπορεί να μην είναι καν διαθέσιμο.

Λίγες αλλαγές είναι απαραίτητες στον κώδικα για να λειτουργήσει όπως αναμενόταν.

Βήμα 2: Ας "ορίσουμε" μερικές καρφίτσες…

Ας
Ας

Είναι μια καλή πρακτική κώδικα που δηλώνει τους πόρους ως εύκολο προσδιορισμό ή έννοια μεταβλητών ή σταθερών. Θα σας επιτρέψει να κωδικοποιήσετε ευκολότερα και να αντιμετωπίσετε προβλήματα.

Χρησιμοποίησα τις καρφίτσες δήλωσης Arduino ως εξής:

const int ledPin = 13;

…"

Αν μου αρέσει, ίσως ρωτάτε τον εαυτό σας: "Πώς μπορώ να δηλώσω καρφίτσες με ονόματα όπως το PC13;;;"

Η απάντηση είναι: Χρησιμοποιήστε την εντολή "#define" C.

Έτσι, σύμφωνα με το pinout draw, το PC13 είναι το pin που έχουμε στο LED στο "BluePill". Για να το χρησιμοποιήσω, θα δηλώσω έτσι, αμέσως μετά τον ορισμό των βιβλιοθηκών (#περιλαμβάνει…) και πριν από οτιδήποτε άλλο:

#define LedPin PC13

…"

Σημειώστε ότι ΔΕΝ υπάρχει ";" τερματισμός γραμμής, NOR "=" εκχώρηση.

Συγκρίνετε και τους δύο κωδικούς. Το ένα είναι το αρχικό παράδειγμα που φορτώθηκε από το IDE. Δεύτερο είναι αυτό που έκανα για να δουλέψω με το "BluePill".

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

Αυτό θα κάνει τη ζωή σας εύκολη.

Βήμα 3: PinMode ()… Πώς θα χρησιμοποιήσετε τις καρφίτσες σας…

Πριν συνεχίσετε, ας κατανοήσουμε τη λειτουργία του PinMode ().

Όπως και το Arduino, οι καρφίτσες STM32 έχουν πολλαπλές λειτουργίες. Ο πιο απλός τρόπος για να επιλέξετε το ένα ή το άλλο είναι να χρησιμοποιήσετε τη δήλωση pinMode ().

Το Arduino διαθέτει μόνο 3 λειτουργίες, INPUT, OUTPUT ή INPUT_PULLUP.

Το STM32, από την άλλη πλευρά, έχει πολλές γεύσεις pinMode (). Αυτοί είναι:

ΕΞΟΔΟΣ -Βασική ψηφιακή έξοδος: όταν ο πείρος είναι Υ HIGHΟΣ, η τάση διατηρείται στα +3,3v (Vcc) και όταν είναι ΧΑΜΗΛΗ, τραβιέται προς τα κάτω στη γείωση

OUTPUT_OPEN_Drain

INPUT_ANALOG -Αυτή είναι μια ειδική λειτουργία για το πότε θα χρησιμοποιηθεί η καρφίτσα για αναλογικές (όχι ψηφιακές) αναγνώσεις. Επιτρέπει την εκτέλεση της μετατροπής ADC στην τάση στον πείρο

INPUT_PULLUP -Η κατάσταση του πείρου σε αυτήν τη λειτουργία αναφέρεται με τον ίδιο τρόπο όπως με το INPUT, αλλά η τάση του πείρου "τραβιέται" απαλά προς τα +3,3v

INPUT_PULLDOWN -Η κατάσταση του πείρου σε αυτήν τη λειτουργία αναφέρεται με τον ίδιο τρόπο όπως με το INPUT, αλλά η τάση του πείρου "κατεβαίνει" απαλά προς τα 0v

INPUT_FLOATING -Συνώνυμο για INPUT

PWM -Αυτή είναι μια ειδική λειτουργία για το πότε θα χρησιμοποιηθεί ο πείρος για έξοδο PWM (ειδική περίπτωση ψηφιακής εξόδου)

PWM_OPEN_DRAIN -Όπως το PWM, εκτός από το ότι αντί για εναλλασσόμενους κύκλους LOW και HIGH, η τάση στον πείρο αποτελείται από εναλλασσόμενους κύκλους LOW και floating (αποσυνδεδεμένος)

(σημείωση: εξήχθη από

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

Βήμα 4: AnalogWrite () έναντι PwmWrite ()… Αναλογική έξοδος σε 2 γεύσεις

AnalogWrite () έναντι PwmWrite ()… Αναλογική έξοδος σε 2 γεύσεις
AnalogWrite () έναντι PwmWrite ()… Αναλογική έξοδος σε 2 γεύσεις
AnalogWrite () έναντι PwmWrite ()… Αναλογική έξοδος σε 2 γεύσεις
AnalogWrite () έναντι PwmWrite ()… Αναλογική έξοδος σε 2 γεύσεις

Πριν από τη χρήση των καρφιτσών GPIO "Blue Pill" είναι απαραίτητο να δηλώσετε τη συμπεριφορά του, δηλαδή πώς θα λειτουργήσει. Αυτό ακριβώς κάνει η συνάρτηση pinMode ().

Λοιπόν, ας εστιάσουμε τώρα στο πόσο σωστό ορίσουμε μια αναλογική έξοδο. Μπορεί να δηλωθεί είτε ως λειτουργία OUTPUT είτε ως λειτουργία PWM.

Με τον ίδιο τρόπο, οι αναλογικές τιμές μπορούν να αποδοθούν στο GPIO με 2 τρόπους: analogWrite () ή pwmWrite (), ΑΛΛΑ, analogWrite () θα λειτουργήσει μόνο εάν pinMode () = OUTPUT. Από την άλλη πλευρά, το pwmWrite () θα λειτουργήσει μόνο εάν pinMode () = PWM.

Ας πάρουμε το PA0, για παράδειγμα: είναι μια αναλογική έξοδος/pwm.

analogWrite (): αυτό δηλώνει με αυτόν τον τρόπο:

….

#define ledPin PA0

pinMode (ledPin, OUTPUT);

analogWrite (ledPin, <αριθμός>);

……"

όπου ο αριθμός πρέπει να είναι μεταξύ 0 και 255, όπως το Arduino. Στην πραγματικότητα, είναι συμβατό με το Arduino.

pwmWrite (): δηλώστε με αυτόν τον τρόπο:

#define ledPin PA0

pinMode (ledPin, PWM);

pwmWrite (ledPin, <αριθμός.>);

…."

Όπου ο αριθμός πρέπει να είναι μεταξύ 0 ~ 65535, μια ανάλυση πολύ υψηλότερη από το Arduino.

Στις εικόνες είναι δυνατή η σύγκριση μεταξύ 2 κωδικών. Μπορείτε επίσης να δείτε τον αρχικό κώδικα.

Βήμα 5: Σειριακή επικοινωνία STM32

Σειριακή επικοινωνία STM32
Σειριακή επικοινωνία STM32

Ας δούμε πώς είναι διατεταγμένες οι διεπαφές USART στο STM32. Ναι, διεπαφές στον πληθυντικό…..

Το "Blue Pill" διαθέτει 3 USART (RX/ TX 1 ~ 3) και, εάν χρησιμοποιείτε ένα bootloader σας επιτρέπει να χρησιμοποιείτε USB, δεν είναι συνδεδεμένο με κανένα από τα τότε.

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

Περίπτωση 1: Χρήση USB:

Με αυτόν τον τρόπο, τα σκίτσα μεταφορτώνονται απευθείας μέσω USB. Δεν χρειάζεται να μετακινήσετε το άλτη BOOT0 σε 1 θέση και πίσω στο 0.

Σε αυτήν την περίπτωση, κάθε φορά που δηλώνετε "Serial" χωρίς ευρετήριο, σημαίνει επικοινωνία μέσω USB.

Έτσι, Serial1, σημαίνει TX/ RX 1 (Pins PA9 και PA10). Serial2, σημαίνει TX/ RX 2 (καρφίτσες PA2 και PA3) και Serial 3 σημαίνει TX/ RX 3 (καρφίτσες PA10 και PA11).

Αυτός είναι ο τρόπος με τον οποίο συνεργαζόμαστε. Θα παρουσιάσω αλλαγές σε παραδείγματα για αυτόν τον τρόπο κωδικοποίησης.

Ένα άλλο πράγμα: "Serial USB" δεν χρειάζεται να προετοιμαστεί. Με άλλα λόγια, "… Serial.begin (15200);" δεν είναι αναγκαίο.

Είναι δυνατή η κλήση οποιασδήποτε σειριακής λειτουργίας (Serial.read (), Serial.write (), κλπ) χωρίς καμία αρχικοποίηση.

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

Περίπτωση 2: Χρήση προσαρμογέα σειρών TTL σε USB:

Με αυτόν τον τρόπο, ο φορτωτής εκκίνησης δεν υποστηρίζει την εγγενή επικοινωνία USB STM32, επομένως χρειάζεστε έναν σειριακό προσαρμογέα USB σε TX/ RX 1 (pin PA9 και PA10) για να ανεβάσετε σκίτσα.

Σε αυτήν την περίπτωση, κάθε φορά "Serial" χωρίς ευρετήριο είναι κωδικός, σημαίνει TX/ RX1 (θύρα που χρησιμοποιείται για τη μεταφόρτωση του κώδικα). Ούτω καθεξής, το Serial1 αναφέρεται στα TX/ RX 2 (καρφίτσες PA2 και PA3) και το Serial2 αναφέρεται σε TX/ RX 3 (Pins PA10 και PA11). Δεν υπάρχει διαθέσιμο Serial3.

Βήμα 6: Μεταβίβαση μιας τιμής στον μικροελεγκτή

Μεταφορά αξίας στον μικροελεγκτή
Μεταφορά αξίας στον μικροελεγκτή

Το παράδειγμα Dimmer είναι ένας απλός τρόπος για να δείξετε πώς περνάτε μια τιμή στον μικροελεγκτή.

Υποτίθεται ότι περνάει μια τιμή από 0 έως 255 για τον έλεγχο της φωτεινότητας των LED.

ΔΕΝ θα λειτουργήσει όπως αναμένεται στο Blue Pill λόγω:

  1. Για να χρησιμοποιήσετε τη λειτουργία pwmWrite (), το pinMode () ΠΡΕΠΕΙ να δηλωθεί ως λειτουργία PWM.
  2. Ποτέ δεν θα λάβετε ολόκληρο τριψήφιο αριθμό. Η συνάρτηση Serial.read () καταγράφει μόνο περιεχόμενο buffer, το οποίο είναι "BYTE". εάν πληκτρολογήσετε "100" και πατήσετε "enter", μόνο το τελευταίο "0" θα καταγραφεί από το buffer. Και η τιμή του θα είναι "48" (δεκαδική τιμή ASCII για "0"). Εάν σκοπεύετε να εκδώσετε την τιμή "100", είναι απαραίτητο να πληκτρολογήσετε "d". Επομένως, είναι σωστό να πούμε ότι θα μετατρέψει μια δεκαδική τιμή συμβόλου ASCII σε φωτεινότητα LED, σωστά;……. Λοιπόν, ένα είδος…
  3. Πρόβλημα, οι τιμές χάρτη απευθείας από τη λειτουργία Serial.read () είναι μια ενέργεια τέχνασμα. Είναι σχεδόν βέβαιο ότι θα λάβετε απροσδόκητες τιμές. Καλύτερη προσέγγιση είναι το περιεχόμενο buffer αποθήκευσης σε μια προσωρινή μεταβλητή και THAN να το χαρτογραφήσετε.

Όπως εξηγώ προηγουμένως στο σημείο 2, ο κωδικός που εισάγω αλλαγές θα επιτρέψουν την εισαγωγή ενός συμβόλου ASCII και αυτό θα ελέγξει τη φωτεινότητα των LED με βάση την δεκαδική τιμή ASCII … για παράδειγμα, το "space" είναι η τιμή 32 (στην πραγματικότητα είναι ο χαμηλότερος εκτυπώσιμος χαρακτήρας που μπορείτε να εισαγάγετε) και το "}" είναι πιθανό το υψηλότερο (τιμή 126). Οι άλλοι χαρακτήρες είναι μη εκτυπώσιμοι, οπότε το τερματικό δεν θα καταλάβει ή είναι πιθανό μια σύνθεση χαρακτήρων (όπως το "~" είναι ένα νεκρό πλήκτρο στο πληκτρολόγιό μου και δεν θα λειτουργήσει σωστά). Αυτό σημαίνει ότι αυτός ο σύνθετος χαρακτήρας, όταν εισαχθεί στο τερματικό, θα στείλει τον ίδιο τον χαρακτήρα και κάτι άλλο. Συνήθως ένα μη εκτυπώσιμο. Και είναι αυτός ο τελευταίος κωδικός που θα συλλάβει. Επίσης, λάβετε υπόψη το τερματικό σας, σε αυτή την περίπτωση, ΔΕΝ πρέπει να στέλνει ούτε "Επιστροφή μεταφοράς" ούτε "Τροφοδοσία γραμμής". Πρέπει να δώσετε προσοχή σε αυτό για να λειτουργήσει σωστά ο κώδικας.

Αν έπεσες είναι λίγο μπερδεμένο, γίνεται χειρότερο…..

Βήμα 7: Και αν θα ήθελα να πληκτρολογήσω τρία ψηφία…. ή ακόμα περισσότερα ??

Και αν θα ήθελα να πληκτρολογήσω τρία ψηφία…. ή ακόμα περισσότερα ??
Και αν θα ήθελα να πληκτρολογήσω τρία ψηφία…. ή ακόμα περισσότερα ??

Η λήψη πολλαπλών χαρακτήρων από μια σειριακή επικοινωνία δεν είναι μια απλή εργασία.

Το σειριακό buffer είναι σωρός χαρακτήρων byte FIFO. Κάθε φορά που καλείται η λειτουργία Serial.read (), ο πρώτος χαρακτήρας που αποστέλλεται αφαιρείται από το σωρό και αποθηκεύεται σε κάποιο άλλο μέρος. Συνήθως μια μεταβλητή char στον κώδικα. Σημείωση, εξαρτάται από το υλικό, συνήθως υπάρχει ένα χρονικό όριο για το πώς το buffer καταγραφής μπορεί να κρατήσει πληροφορίες.

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

Αυτό σημαίνει ότι η ποδηλασία διαβάζει κάθε buff buff, αποθηκεύει σε μια μεταβλητή temp, τη φορτώνει στην πρώτη θέση ενός πίνακα συμβολοσειρών, μεταβαίνει στην επόμενη θέση και ξεκινά από την αρχή, μέχρι… καλά, εξαρτάται από την εφαρμογή. Υπάρχουν 2 τρόποι για να τερματίσετε τον κύκλο:

  1. Χρήση κάποιου χαρακτήρα "σημείου λήξης", όπως "επιστροφή μεταφοράς" ή "Ροή γραμμής". Μόλις βρεθεί ο χαρακτήρας "end Mark", ο βρόχος καταλήγει.
  2. Εναλλακτικά, ο αριθμός των χαρακτήρων στην αλυσίδα συμβολοσειρών μπορεί να είναι περιορισμένος, το ίδιο και ο αριθμός των διαδραστικών κύκλων. Όταν φτάσει στο όριο, ας πούμε, 4, αποκτήστε τελειώματα ρουτίνας μόνος του.

Ας ρίξουμε μια ματιά σε ένα απλό παράδειγμα πώς γίνεται αυτό:

  • Ορίστε έναν χαρακτήρα "τέλους", όπως "\ n" (αυτό σημαίνει τροφοδοσία γραμμής ASCII char).
  • looping εν τω μεταξύ Serial.available () είναι αληθές
  • η αποθήκευση του Serial.read () έχει ως αποτέλεσμα μια προσωρινή μεταβλητή char. Θυμηθείτε: μόλις το Serial.read () πραγματικά "διαβάσει" το buffer, είναι καθαρό και ο επόμενος χαρακτήρας φορτώνεται σε αυτό.
  • αυξήστε μια μεταβλητή συμβολοσειράς με αυτόν τον χαρακτήρα
  • Εάν ο τελευταίος χαρακτήρας είναι "τέλος", βγείτε από τον βρόχο.

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

Βασίστηκε σε μια εκτενή προσαρμογή του αρχικού κώδικα του κ. David A. Mellis.

Έπεσε ελεύθερος να το χρησιμοποιήσει και να το δοκιμάσει. Θυμηθείτε: οι τιμές ΠΡΕΠΕΙ να εισαχθούν σε μορφή 3 ψηφίων.

Αυτό είναι προς το παρόν. Δεν θα επεκταθώ σε επιπλέον σειριακές λεπτομέρειες επικοινωνίας. Είναι πολύ περίπλοκο για να το καλύψεις εδώ και του αξίζει το δικό του Intructables.

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

Ραντεβού σε άλλα διδακτικά.

Συνιστάται: