- Pregătirea hardware-ului
- Înțelegerea Pinouts GPIO pe STM8S103F
- Descriere Pinout și sfaturi pentru selecția STM8S103F GPIO
- Programarea STM8S pentru intrare și ieșire GPIO utilizând SPL
- Încărcarea și testarea programului
Pentru microcontrolere, un program LED intermitent este echivalent cu programul „hello world”. În tutorialul nostru anterior, am învățat cum să începem cu placa de dezvoltare STM8S103F3 și cum să configurăm IDE și compilatorul pentru a programa controlerele noastre STM8S. De asemenea, am învățat cum să folosim bibliotecile periferice standard și cum să compilăm și să încărcăm codul în microcontrolerul nostru. Cu toate elementele de bază acoperite, să începem de fapt să scriem cod. În acest tutorial, vom învăța cum să efectuăm funcții generale GPIO pe controlerele STM8S. Placa are deja un LED integrat conectat la pinul 5 al portului B, vom învăța cum să clipim acest LED și, de asemenea, să adăugăm un LED extern și să-l controlăm cu un buton. Dacă sunteți complet nou, este foarte recomandat să citiți tutorialul anterior înainte de a continua mai departe.
Pregătirea hardware-ului
Înainte de a ne arunca cu capul în program, permiteți pregătirea conexiunilor hardware. După cum sa menționat mai devreme, vom folosi două LED-uri aici, unul este un LED de la bord care va clipi continuu, iar celălalt este un LED extern care va fi comutat cu un buton. Ideea este să învățați toate funcționalitățile GPIO într-un set simplu. Ledul de la bord este deja conectat la PB5 (pinul 5 al PORTB), așa că tocmai am conectat un LED la PA3 și un buton la PA2, așa cum puteți vedea în diagrama de mai jos.
Dar, dintre toți pinii de ieșire disponibili pe controlul nostru, de ce am selectat PA3 pentru ieșire și PA2 pentru intrare? Întrebările sunt valabile și voi explica asta mai târziu în acest articol. Configurarea mea hardware pentru acest tutorial este prezentată mai jos. După cum puteți vedea, am conectat și programatorul meu ST-link la pinii de programare care nu numai că vor programa placa noastră, ci vor acționa și ca sursă de alimentare.
Înțelegerea Pinouts GPIO pe STM8S103F
Revenind acum la întrebarea, de ce PA2 pentru intrare și de ce PA3 pentru ieșire? Pentru a înțelege acest lucru, să aruncăm o privire mai atentă asupra pinout-ului microcontrolerului care este prezentat mai jos.
Conform diagramei pinout, avem patru porturi pe microcontrolerul nostru, și anume, PORT A, B, C și D notate cu PA, PB, PC și respectiv PD. Fiecare pin GPIO este de asemenea dotat cu alte funcționalități speciale. De exemplu, PB5 (pinul 5 din PORT B) nu poate funcționa doar ca pin GPIO, ci și ca pin SDA pentru comunicații I2C și ca pin de ieșire Timer 1. Deci, dacă folosim acest pin în scopuri GPIO simple, cum ar fi conectarea unui LED, atunci nu vom putea folosi I2C și LED-ul în același timp. Din păcate, LED-ul integrat este conectat la acest pin, deci nu avem prea multe de ales aici, iar în acest program, nu vom folosi I2C, deci nu este o problemă.
Descriere Pinout și sfaturi pentru selecția STM8S103F GPIO
Adevărat vorbind, nu ar strica să folosiți PA1 un pin de intrare și ar funcționa pur și simplu pin. Dar am adus acest lucru în mod deliberat pentru a-mi oferi ocazia să vă arăt câteva capcane comune în care ați putea cădea atunci când selectați pinii GPIO pe un nou microcontroler. Cel mai bun pentru a evita capcanele este să citiți detaliile pinului și descrierea pinului furnizate în foaia tehnică STM8S103F3P6. Pentru detaliile descrierii pinului microcontrolerului STM8S103F3P6 care sunt menționate în foaia tehnică sunt prezentate mai jos imagini.
Pinii de intrare de pe microcontrolerul nostru pot fi flotanți sau slabi, iar pinii de ieșire pot fi Open Drain sau Push-pull. Diferența dintre pinii de ieșire Open Drain și Push-Pull Output este deja discutată, prin urmare nu vom intra în detalii despre asta. Pentru a simplifica, un pin de ieșire Open Drain poate face ca ieșirea să fie la fel de mică, nu la fel de mare, în timp ce un pin de ieșire push-pull poate face ieșirea atât la fel de mare, cât și de mare.
În afară de aceasta din tabelul de mai sus, puteți observa, de asemenea, că un pin de ieșire poate fi fie ieșire rapidă (10 Mhz), fie ieșire lentă (2 MHz). Aceasta determină viteza GPIO, dacă doriți să comutați pinii GPIO între mare și mic foarte rapid, atunci putem alege Ieșire rapidă.
Unele pini GPIO de pe controlerul nostru acceptă True Open Drain (T) și High Sink Current (HS), așa cum se menționează în imaginea de mai sus. O diferență considerabilă între Open Drain și True Open Drain este că ieșirea conectată la drenajul deschis nu poate fi trasă mai mare decât tensiunea de funcționare a microcontrolerului (Vdd), în timp ce un pin de ieșire cu drenaj deschis adevărat poate fi tras mai sus decât Vdd. Pinii cu capacitate mare de scufundare înseamnă că poate scădea mai mult curent. Sursa și curentul de scufundare al oricărui pin GPIO HS este de 20mA, în timp ce linia de alimentare poate consuma până la 100 mA.
Aruncând o privire mai atentă asupra imaginii de mai sus, veți observa că aproape toți pinii GPIO sunt de tip High Sink Current (HS), cu excepția PB4 și PB5 care sunt True Open Drain Type (T). Aceasta înseamnă că acești știfturi nu pot fi ridicați, nu vor putea furniza 3,3V chiar și atunci când știftul este ridicat. Acesta este motivul pentru care ledul de la bord este conectat la un 3.3V și împământat prin PB5 în loc să-l alimenteze direct de la pinul GPIO.
Consultați pagina 28 din foaia tehnică pentru descrierea detaliată a pinului. După cum sa menționat în imaginea de mai sus, PA1 este configurat automat ca un pull-up slab și nu este recomandat să fie utilizat ca pin de ieșire. Oricum poate fi folosit ca un pin de intrare împreună cu un buton, dar am decis să folosesc PA2 doar pentru a încerca să activați extragerea din program. Acestea sunt doar câteva lucruri de bază care vor fi utile atunci când scriem programe mult mai complicate. Deocamdată, este în regulă dacă multe lucruri ți-au sărit din cap, vom intra în stratul său în alte tutoriale.
Programarea STM8S pentru intrare și ieșire GPIO utilizând SPL
Creați un spațiu de lucru și un proiect nou așa cum am discutat în primul nostru tutorial. Puteți adăuga fie toate fișierele antet și sursă, fie adăugați doar fișierele gpio, config și stm8s. Deschideți fișierul main.c și începeți să scrieți programul.
Asigurați-vă că ați inclus fișierele antet așa cum se arată în imaginea de mai sus. Deschideți fișierul main.c și porniți codul. Codul main.c complet poate fi găsit în partea de jos a acestei pagini și veți putea descărca fișierul de proiect de acolo. Explicația codului este următoarea, puteți consulta, de asemenea, manualul de utilizare SPL sau videoclipul legat în partea de jos a acestei pagini, dacă sunteți confuz cu privire la partea de codare.
Dezinicializarea portului necesar
Începem programul nostru prin dezinicializarea porturilor necesare. După cum am discutat mai devreme, fiecare pin GPIO va avea multe alte funcții asociate cu acesta, altele decât să funcționeze ca o intrare și o ieșire normale. Dacă acești pini au fost utilizați anterior pentru alte aplicații, atunci ar trebui dezinicializat înainte de a-i folosi. Nu este obligatoriu, însă este o bună practică. Următoarele două linii de cod sunt utilizate pentru a dezinicializa portul A și portul B. Folosiți doar sintaxa GPIO_DeInit (GPIOx); și menționați numele portului în locul lui x.
GPIO_DeInit (GPIOA); // pregătiți portul A pentru funcționarea GPIO_DeInit (GPIOB); // pregătiți portul B pentru lucru
Declarație GPIO de intrare și ieșire
Apoi, trebuie să declarăm ce pini vor fi folosiți ca intrare și care ca ieșire. În cazul nostru, pinul PA2 va fi folosit ca intrare, vom declara și acest pin cu Pull-up intern, astfel încât să nu trebuiască să-l folosim extern. Sintaxa este GPIO_Init (GPIOx, GPIO_PIN_y, GPIO_PIN_MODE_z); . Unde x este numele portului, y este numărul pinului, iar z este modul PIN GPIO.
// Declarați PA2 ca pin de intrare GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
Apoi, trebuie să declarăm pinii PA3 și PB5 ca ieșire. Din nou sunt posibile multe tipuri de declarații de ieșire, dar vom folosi „GPIO_MODE_OUT_PP_LOW_SLOW” ceea ce înseamnă că o vom declara ca un pin de ieșire de tip push-pull cu viteză mică. Și în mod implicit, valoarea va fi scăzută. Sintaxa va fi aceeași.
GPIO_Init (GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW); // Declarați PB5 ca pin de ieșire push pull GPIO_Init (GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
Instantaneul de mai jos din manualul de utilizare SPL menționează toate modurile posibile GPIO (z).
Buclă infinită în timp ce
După declarația pinului, trebuie să creăm o buclă infinită în interiorul căreia vom continua să clipim LED-ul pentru totdeauna și să monitorizăm starea butonului pentru a comuta LED-ul. Bucla infinită se poate crea fie cu un timp (1), fie cu un pentru (;;) . Aici am folosit while (1).
while (1) {}
Verificarea stării pinului de intrare
Trebuie să verificăm starea pinului de intrare, sintaxa pentru a face acest lucru este GPIO_ReadInputPin (GPIOx, GPIO_PIN_y); unde x este numele portului și y este numărul pinului. Dacă știftul este ridicat, vom obține „1” și dacă știftul este scăzut, vom obține un „0”. Am obișnuit să intrăm într-o buclă if pentru a verifica dacă pinul este ridicat sau scăzut.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // dacă butonul este apăsat
Realizarea unui pin GPIO mare sau scăzut
Pentru a crea un pin GPIO High sau Low, putem folosi GPIO_WriteHigh (GPIOx, GPIO_PIN_y); și GPIO_WriteLow (GPIOx, GPIO_PIN_y); respectiv. Aici am făcut LED-ul să se aprindă dacă butonul este apăsat și să se stingă dacă butonul nu este apăsat.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // dacă butonul a fost apăsat GPIO_WriteLow (GPIOA, GPIO_PIN_3); // LED ON else GPIO_WriteHigh (GPIOA, GPIO_PIN_3); // LED OFF
Comutarea unui PIN GPIO
Pentru a comuta un pin GPIO, avem GPIO_WriteReverse (GPIOx, GPIO_PIN_y); apelarea acestei funcții va schimba starea pinului de ieșire. Dacă știftul este ridicat, acesta va fi schimbat la scăzut, iar dacă este scăzut, acesta va fi schimbat la înalt. Folosim această funcție pentru a clipi LED-ul de pe PB5.
GPIO_WriteReverse (GPIOB, GPIO_PIN_5);
Funcția de întârziere
Spre deosebire de Arduino, compilatorul cosmic nu are o funcție de întârziere predefinită. Deci, trebuie să creăm unul singur. Funcția mea de întârziere este dată mai jos. Valoarea doe întârzierea va fi primită în variabila ms și vom folosi două pentru buclă pentru a ține sau pentru a executa programul. Ca și _asm („nop”) este o instrucțiune de asamblare care nu înseamnă nicio operațiune. Aceasta înseamnă că controlerul va intra în buclă în bucla for fără a efectua nicio operațiune, creând astfel o întârziere.
void delay (int ms) // Definiție funcție {int i = 0; int j = 0; for (i = 0; i <= ms; i ++) {for (j = 0; j <120; j ++) // Nop = Fosc / 4 _asm ("nop"); // Nu efectuați nicio operațiune // cod asamblare}}
Încărcarea și testarea programului
Acum că programul nostru este gata, îl putem încărca și testa. Odată încărcat, hardware-ul meu funcționa așa cum era de așteptat. LED-ul roșu de la bord clipea la fiecare 500 de milisecunde și LED-ul verde extern se aprindea de fiecare dată când apăsam comutatorul.
Lucrarea completă poate fi găsită în videoclipul legat mai jos. Odată ce ați ajuns la acest punct, puteți încerca să conectați comutatorul și LED-ul la diferiți pini și să scrieți din nou codul pentru a înțelege conceptul. De asemenea, puteți juca cu temporizarea întârzierii pentru a verifica dacă ați înțeles clar conceptele.
Dacă aveți întrebări, vă rugăm să le lăsați în secțiunea de comentarii de mai jos și pentru alte întrebări tehnice, puteți folosi forumurile noastre. Vă mulțumim că ați urmat, ne vedem în următorul tutorial.