Firmware Stm32 prin swd. Stăpânirea rapidă a microcontrolerelor STM32

Acest articol este primul dintr-o serie planificată de articole despre studierea programării microcontrolerelor. În timp ce studiam diverse materiale, am observat că aproape toate încep cu faptul că unui începător i se cere să descarce (sau să folosească biblioteca care vine cu mediul de dezvoltare) pentru a lucra cu dispozitive periferice și să o folosească pentru a scrie primul său program (de obicei clipind un LED).

Acest lucru m-a surprins foarte mult. Dacă credeți aceste articole, nici măcar nu trebuie să citiți documentația pentru programarea controlerului programabil. Am fost învățat înțelepciunea "programare hardware" complet diferit.

În acest articol, calea de la expresia „Da, vreau să încerc!” până când clipitul vesel al LED-ului va fi mult mai lung decât cel al altor autori. Voi încerca să dezvălui aspecte ale programării microcontrolerelor care sunt ascunse în spatele utilizării funcțiilor de bibliotecă și a exemplelor gata făcute.
Dacă intenționați să studiați serios programarea microcontrolerelor, acest articol este pentru dvs. Poate că ar putea fi de interes și pentru cei care s-au jucat suficient cu Arduino și doresc să pună mâna pe toate capacitățile hardware ale hardware-ului.

Alegerea unui microcontroler

Mulți ar putea spune că este mai bine să începeți să învățați microcontrolere cu AVR, PIC, 8051 sau altceva. Problema este multifațetă și controversată. Cunosc destule exemple în care oamenii, după ce au studiat Cortex-M, au programat AVR, ARM7 etc. Eu însumi am început cu Cortex-M3. Dacă vă confruntați cu o anumită sarcină, există o mulțime de informații pe Internet care compară diferite tipuri de microcontrolere și sarcinile pe care le pot rezolva. Această întrebare a fost pusă și la Habré, de exemplu.

Vom presupune că ne-am dat seama de tipul de microcontroler. Dar piața oferă o gamă largă de modificări diferite de la diferiți producători. Ele diferă în mulți parametri - de la dimensiunea memoriei flash la numărul de intrări analogice. Pentru fiecare sarcină, alegerea trebuie făcută individual. Nu există și nu pot exista recomandări generale aici. Voi observa doar că merită să vă începeți studiul cu producătorii MK care au cea mai mare gamă posibilă. Apoi, atunci când alegeți un MK pentru o anumită sarcină, există șanse destul de mari ca ceva din gama prezentată să vi se potrivească.

Am ales STM32(deși cred că este mai bine să începi să studiezi cu MK de la TexasInstruments - documentația este foarte bine compilată), deoarece sunt larg răspândite în rândul dezvoltatorilor de electronice ruși. Dacă aveți probleme sau întrebări, puteți găsi cu ușurință soluții pe forumuri. Un alt plus este selecția largă de plăci demo, atât de la producător, cât și de la organizații terțe.

Ce ai nevoie pentru a studia?

Din păcate, pentru a începe programarea unui MK, doar un PC nu este suficient. Va trebui să obțineți o placă demo și un programator de undeva. Deși acest lucru reduce concurența pe piața muncii.

Eu însumi folosesc o placă demonstrativă. STM3220G-EVAL si programator J-Link PRO. Dar pentru început, va fi destul STM32F4DESCOPERIRE, care poate fi cumpărat fără probleme pentru o sumă mică.

Toate exemplele vor fi specifice pentru placa de depanare STM32F4DESCOPERIRE. În această etapă, nu va fi deloc important pentru noi ca această placă să aibă un MCU bazat pe nucleul Cortex-M4. Nu vom folosi caracteristicile și avantajele sale față de Cortex-M3 în viitorul apropiat. Vom vedea ce se întâmplă mai departe.

Dacă aveți orice altă placă bazată pe STM32F2xx/STM32F4xx, puteți lucra cu ea. În prezentarea materialului, voi încerca să descriu cât mai detaliat posibil. De ce o facem așa și nu altfel. Sper că nimeni nu va avea probleme la transferul de exemple pe alt hardware.

Mediu de dezvoltare

După cum sa menționat deja de mai multe ori, există un număr suficient de medii de dezvoltare pentru microcontrolere ARM, atât plătite, cât și nu atât. Și din nou aș dori să omit controversa pe această chestiune. Folosesc IAR Embedded Workbench pentru ARM 6.60. Toate exemplele vor fi în acest mediu. Dacă îți place (sau organizația ta folosește) altceva (Keil, Eclipse, CCS, CooCoc etc.), atunci nici asta nu te va răni. Voi acorda o atenție deosebită caracteristicilor legate în mod special de mediul de dezvoltare.

De ce un mediu de dezvoltare plătit?

Poate că cineva nu va fi pe deplin mulțumit de faptul că sugerez să utilizați un mediu de dezvoltare plătit, dar în IAR este posibil să obțineți o licență temporară fără restricții de funcționalitate sau o licență nelimitată cu o limită de dimensiune a codului (32KB pentru MK este mult ).
În plus, voi observa imediat că pentru unele MK-uri nu există medii de dezvoltare libere. Și, din păcate, acești deputați sunt de neînlocuit în unele zone.


Nu voi descrie procesul de instalare.

Unde sa încep?

Crearea unui proiect
Mai întâi, să creăm un proiect gol. IAR vă permite să creați proiecte în ASM, C și C++. Vom folosi C.

Un proiect gol cu ​​un fișier principal va apărea în fața noastră.

Acum trebuie să configurați proiectul pentru a începe să lucreze cu „nostru” MK și depanator. MK instalat pe placa STM32F4DISCOVERY STM32F407VG. Trebuie selectat în proprietățile proiectului (Opțiuni generale->Target->Dispozitiv):

Când selectați un procesor programabil țintă, se încarcă descrierea acestuia, ceea ce oferă oportunități ample de depanare (acesta va fi discutat mai jos). În plus, este atașat automat un fișier de configurare care descrie spațiul de adrese disponibil pentru linker. Dacă este necesar, vom atinge subiectul fișierului de configurare a linkerului în articolele viitoare.

După aceasta, trebuie să configurați depanatorul. Depanarea programului are loc direct „în hardware”. Acest lucru se face folosind un depanator JTAG. Puteți afla mai multe despre cum se întâmplă acest lucru pe Wikipedia. Depanatorul ST-LINK/V2 este integrat pe placa STM32F4DISCOVERY. Pentru a lucra cu depanatorul, trebuie să selectați driverul acestuia din meniu Depanator->Configurare->Driver. De asemenea, este necesar să se indică faptul că depanarea trebuie efectuată direct în hardware. Pentru a face acest lucru, trebuie să setați steagul Depanator->Descărcare->Utilizați încărcător(e) flash


Pentru cei care au văzut cuvântul Simulator

În teorie, IAR vă permite să depanați programe folosind un simulator. Dar nu l-am văzut niciodată folosit în practică.

Acum proiectul este gata de lucru (programare, completare și depanare).

„TZ” pentru primul proiect
Să rezumam: S-au selectat MK și placa de depanare, proiectul a fost pregătit. Este timpul să decideți asupra sarcinii.

Să nu ne abatem de la clasici. Primul proiect va fi un LED intermitent. Din fericire, sunt destule pe placă Ce înseamnă asta din punct de vedere al programării? Primul lucru pe care trebuie să-l faceți este să studiați schema de circuit a plăcii demo și să înțelegeți cum „pornește” LED-ul.
disponibil pe site-ul producătorului. Această descriere are chiar și o secțiune separată despre LED-urile de pe placă - 4.4 LED-uri. De exemplu, vom folosi Utilizator LD3. Să-l găsim în diagramă:

Cea mai simplă analiză a circuitului sugerează că, pentru a „aprinde” LED-ul, trebuie să aplicați „1” pinului MK (care pentru acest MK corespunde cu 3,3 V). Oprirea se face prin aplicarea „0” acestui pin. În diagramă este desemnat acest pin PD13(aceasta este probabil cea mai importantă informație din acest document).

Ca rezultat, putem scrie „TK” pentru primul nostru program:
Programul pentru MK trebuie să transfere starea pinului MK PD13 de la starea „0” la starea „1” și înapoi cu o anumită periodicitate care este vizibilă pentru ochiul uman (o notă importantă, dacă LED-ul clipește prea des în ochi. este posibil să nu poată distinge acest lucru).

Înainte de a începe programarea, sau puțină teorie
Înainte de a începe să implementăm specificațiile noastre tehnice, este necesar să înțelegem cum este gestionat MK.

Să începem cu faptul că orice MK include un nucleu, memorie și unități periferice. Cred că cu memoria totul este clar deocamdată. Permiteți-mi să menționez doar că STM32 are memorie flash în care este stocat programul MK (în general, aceasta nu este o afirmație adevărată, programul poate fi stocat în memorie externă nevolatilă, dar vom ignora asta pentru moment) și alte date, inclusiv datele utilizatorului. Există și SRAM - memorie cu acces aleatoriu.

Nucleul este partea din microcontroler care execută un flux de comenzi. În MK-ul nostru tipul de bază este Cortex-M4. Nucleul MK poate fi comparat cu procesorul dintr-un PC. Poate executa doar comenzi și transfera date către alte unități (procesoarele cu acceleratoare grafice integrate nu sunt luate în considerare în această comparație).
În același timp, producătorul MK nu dezvoltă nucleul. Nucleul este achiziționat de la ARM Limited. Principala diferență între diferitele MK este la periferie.

Blocurile periferice sunt blocuri care interacționează cu „lumea exterioară” sau îndeplinesc funcții specifice care sunt inaccesibile pentru nucleul MK. MCU-urile moderne (inclusiv STM32) conțin o gamă largă de unități periferice. Blocurile periferice sunt concepute pentru a rezolva diverse probleme, de la citirea valorii tensiunii de la intrarea analogică a MK până la transmiterea datelor către dispozitive externe prin magistrala SPI.
Spre deosebire de nucleul MK, unitățile periferice nu execută instrucțiuni. Ei execută doar comenzile nucleului. În acest caz, nu este necesară participarea nucleului la executarea comenzii.

Exemplu

Un exemplu este blocul UART, care este conceput pentru a primi și transmite date de la MK către dispozitive externe. Nucleul trebuie doar să configureze blocul și să-i dea date pentru transmisie. După aceasta, nucleul poate continua să execute instrucțiuni. Unitatea periferică este responsabilă pentru controlul ieșirii MK corespunzătoare pentru transmiterea datelor în conformitate cu protocolul. Unitatea periferică însăși transferă ieșirea MK în starea necesară „0” sau „1” la momentul potrivit, efectuând transmisia.

Interacțiunea miezului cu unitatea periferică
Interacțiunea nucleului MK cu unitatea periferică se realizează folosind registre speciale (există și interacțiune prin mecanismul de întrerupere și DMA, dar mai multe despre asta în postările următoare). Din punctul de vedere al nucleului, aceasta este pur și simplu o bucată de memorie cu o anumită adresă, doar că nu este adevărat. Scrierea datelor într-un registru special echivalează cu transmiterea unei comenzi sau a datelor către o unitate periferică. Citire - primirea datelor dintr-un bloc sau citirea stării acestuia. Descrierea blocurilor periferice și a registrelor lor speciale ocupă partea leului din descrierea MK.

IMPORTANT: După ce scrieți date într-un registru special și apoi le citiți, puteți obține date complet diferite. De exemplu, trimiterea datelor către un bloc UART pentru a le trimite și citirea datelor primite de bloc de la un dispozitiv extern sunt efectuate folosind același registru.

Registrele speciale sunt de obicei împărțite în câmpuri de biți. Unul (sau mai mulți) biți controlează un anumit parametru de bloc periferic, de obicei independent. De exemplu, diferiți biți ai unui registru controlează starea diferitelor ieșiri MK.

Ține minte C
Dacă sunteți un guru al limbajului C, puteți sări peste această secțiune în siguranță. Este destinat în primul rând celor care au fost învățați (sau care au învățat ei înșiși) să programeze pentru un PC. Experiența arată că oamenii de multe ori nu își amintesc comenzile importante. Aici vă voi aminti pe scurt despre operațiunile pe biți și despre lucrul direct cu memoria la adresa acesteia.

Scrierea datelor la o adresă de memorie

Să presupunem că în timp ce citim descrierea blocului periferic, ne-am dat seama că pentru ca acesta să funcționeze corect, este necesar să scriem în el numărul 0x3B. Adresa de registru specială este 0x60004012. Registrul este pe 32 de biți.
Dacă nu știți imediat cum să faceți acest lucru, voi încerca să descriu lanțul de raționament pentru a obține comanda corectă.

Valoarea 0x60004012 nu este altceva decât valoarea unui pointer către o locație de memorie. Este exact ceea ce trebuie să indicăm în programul nostru, adică să facem o conversie de tip în funcție de sintaxa limbajului C:

(nesemnat lung*)(0x60004012)

Deci avem un pointer către un element. Acum trebuie să scrieți valoarea necesară în acest element. Acest lucru se face prin dereferențierea indicatorului. Astfel, obținem comanda corectă:

*(nesemnat lung*)(0x60004012) = 0x3B;

Setarea biților arbitrari la 1

Să presupunem că doriți să setați biții 7 și 1 la adresa 0x60004012 la „1” fără a modifica valoarea tuturor celorlalți biți din registru. Pentru a face acest lucru, trebuie să utilizați operația binară |. Iti dau imediat raspunsul corect:

*(nesemnat lung*)(0x60004012) |= 0x82;

Fiți atenți la 2 fapte. Biții sunt numărați de la zero, nu de la primul. Această operație durează de fapt cel puțin 3 cicluri de ceas - citirea valorii, modificarea acesteia, scrierea acesteia. Uneori, acest lucru nu este acceptabil deoarece între citire și scriere, valoarea unuia dintre biții pe care nu avem voie să-i modificăm poate fi schimbată de unitatea periferică. Nu uitați de această funcție, altfel pot apărea erori extrem de greu de prins.

Setarea biților arbitrari la 0

Să presupunem că vrem să setăm biții 7 și 1 la adresa 0x60004012 la „0” fără a modifica valoarea tuturor celorlalți biți din registru. Pentru a face acest lucru, trebuie să utilizați operatorul binar &. Iti dau imediat raspunsul corect:

*(nesemnat lung*)(0x60004012) &= 0xFFFFFF7D;

Sau notația sa mai simplă (nu vă faceți griji pentru operația suplimentară, compilatorul va calcula totul în avans chiar și cu o optimizare minimă):

*(nesemnat lung*)(0x60004012) &= (~0x82);

Unele caracteristici ale programelor pentru MK
Aici voi încerca să descriu câteva caracteristici ale programelor pentru MK care sunt importante de reținut. Lucrurile sunt destul de evidente, dar totuși.
Programul nu are sfârșit
Spre deosebire de majoritatea programelor pentru PC, programul MK nu ar trebui să se termine niciodată, NICIODATĂ! Ce va trebui să facă exact MK după finalizarea programului? Întrebarea este practic retorică. Prin urmare, nu uitați să vă asigurați că nu ați uitat ciclul etern. Dacă doriți, puteți pune MK în modul de repaus.
Utilizați variabile întregi
În ciuda faptului că folosim un microcontroler cu nucleu Cortex-M4, care efectuează operații pe numere în virgulă mobilă din hardware, vă sfătuiesc să nu le folosiți. Într-un microcontroler fără suport pentru astfel de operațiuni, timpul de calcul va fi pur și simplu enorm.
Evitați alocarea dinamică a memoriei
Acesta este doar un sfat. Motivul este simplu - nu există suficientă memorie. Am întâlnit adesea biblioteci care aveau scurgeri de memorie „lente”. A fost foarte neplăcut când, după câteva săptămâni de funcționare stabilă, MK s-a prăbușit cu o eroare. Este mai bine să vă gândiți în avans la arhitectura programului, astfel încât să nu fie nevoie să utilizați alocarea dinamică a memoriei.
Dacă tot doriți să-l utilizați, studiați cu atenție munca managerului de memorie sau scrieți-l pe propria dvs.

Sa trecem la treaba!

Lucrul la un program pentru MK începe întotdeauna cu citirea documentației. Pentru MK-ul nostru este disponibil pe site-ul producătorului. Sunt multe pagini, dar citește-le pe toate Pa nu este nevoie. După cum sa menționat deja, cea mai mare parte a documentației constă într-o descriere a unităților periferice și a registrelor acestora. De asemenea, vreau să vă atrag atenția asupra faptului că acest Manual de referință a fost scris nu pentru un MK, ci pentru mai multe rânduri. Acest lucru sugerează că codul va fi portabil atunci când vă mutați la alte MK-uri din aceste linii (cu excepția cazului în care, desigur, încercați să utilizați unități periferice care nu sunt în MK-ul pe care îl utilizați).

În primul rând, trebuie să decideți cu ce blocuri să lucrați. Pentru a face acest lucru, trebuie doar să studiați secțiunile IntroducereȘi Caracteristici principale.

Controlul direct al stării pinii MK se realizează folosind blocul GPIO. După cum se indică în documentație, MCU STM32 poate avea până la 11 blocuri GPIO independente. Diverse blocuri GPIO periferice sunt denumite în mod obișnuit porturi. Porturile sunt desemnate prin literele de la A la K. Fiecare port poate conține până la 16 pini. După cum am observat mai devreme, LED-ul este conectat la pinul PD13. Aceasta înseamnă că acest pin este controlat de portul D GPIO al unității periferice. Pinul numărul 13.

De data aceasta nu vom avea nevoie de alte unități periferice.

Controlul ceasului periferic
Pentru a reduce consumul de energie al MK, aproape toate unitățile periferice sunt oprite după pornirea MK. Blocul este pornit/oprit prin aplicarea/oprirea furnizării unui semnal de ceas la intrarea sa. Pentru o funcționare corectă, este necesar să configurați controlerul de semnal de ceas MK, astfel încât unitatea periferică necesară să primească un semnal de ceas.
Important: Unitatea periferică nu poate începe să funcționeze pe loc după ce semnalul ceasului este pornit. Trebuie să așteptați câteva bifături până când „începe”. Persoanele care folosesc biblioteci periferice de multe ori nici măcar nu știu despre această caracteristică.

Registrele sunt responsabile pentru activarea tacării unităților periferice Registrul de activare a ceasului periferic RCC XXX.În locul lui XXX pot fi anvelope AHB1, AHB2, AHB3, APB1 și APB2. După ce am studiat cu atenție descrierea registrelor corespunzătoare, putem concluziona că tactarea blocului periferic GPIOD este activată prin setarea „1” în al treilea bit al registrului. Registrul de activare a ceasului periferic RCC AHB1 (RCC_AHB1ENR):

Acum trebuie să vă dați seama cum să aflați adresa registrului în sine RCC_AHB1ENR.

Cometariu: Descrierea sistemului de ceas STM32 MK merită un articol separat. Dacă cititorii ar dori, voi acoperi această secțiune mai detaliat într-unul dintre articolele următoare.

Determinarea adreselor de registru speciale
Determinarea adreselor registrelor speciale trebuie să înceapă prin citirea secțiunii Harta memorieiîn manualul de referință. Puteți vedea că fiecărui bloc îi este alocată propria secțiune a spațiului de adrese. De exemplu, pentru blocul RCC aceasta este secțiunea 0x4002 3800 - 0x4002 3BFF:

Pentru a obține adresa de registru, este necesar să adăugați la valoarea inițială a spațiului de adrese al blocului RCC Adr. decalaj registrul necesar. Adrese compensate este indicat și în descrierea registrului (vezi captura de ecran de mai sus).

Prin urmare, am stabilit adresa de înregistrare RCC_AHB1ENR- 0x4002 3830.

bloc GPIO
Pentru o înțelegere generală a blocului GPIO, vă recomand să citiți întreaga secțiune a Manualului de referință. Deocamdată nu poți acorda prea multă atenție Mod alternativ. Vom lăsa asta pentru mai târziu.

Acum sarcina noastră este să învățăm cum să gestionăm starea pinurilor MK. Să trecem direct la descrierea registrelor GPIO.

Mod de operare
În primul rând, trebuie să setați modul de funcționare al pinului 13 al portului D ca Mod de ieșire de uz general, ceea ce înseamnă că blocul GPIO va controla starea pinului MK. Modul de operare al pinii MK este controlat folosind un registru Registrul modului port GPIO (GPIOx_MODER) (x = A..I/J/K):

După cum se poate vedea din descriere, pentru a face ajustarea necesară, trebuie să scriem valoarea 01b în 26-27 de biți ai registrului GPIOx_MODER. Adresa de registru poate fi determinată folosind aceeași metodă descrisă mai sus.

Configurarea parametrilor de funcționare ai pinilor de ieșire ai portului GPIO
Blocul GPIO vă permite să aplicați setări suplimentare pentru pinii de ieșire ai portului. Aceste setări se fac în registre:
  • Registrul tipului de ieșire a portului GPIO (GPIOx_OTYPER)- setați tipul de ieșire push-pull sau open-drain
  • Registrul vitezei de ieșire a portului GPIO (GPIOx_OSPEEDR)- setați viteza de ieșire
Nu vom modifica acești parametri, deoarece suntem destul de mulțumiți de valorile implicite.
Setarea valorii pe pinul MK
În cele din urmă, am ajuns la momentul controlării stării de ieșire a MK. Există două metode de setare a valorii de ieșire pe un anumit pin MK.

Folosim registrul de setare/resetare a biților portului GPIO (GPIOx_BSRR)

Scrierea unui „0” sau „1” la biții 0-16 determină o modificare corespunzătoare a stării pinii portului. Pentru a seta o anumită valoare la ieșirea unuia sau mai multor pini MK și pentru a nu schimba starea celorlalți, va fi necesar să folosiți operația de modificare a biților individuali. Această operație se realizează în cel puțin 3 cicluri. Dacă este necesar să scrieți 1s la unii biți și 0s la alții, atunci vor fi necesare cel puțin 4 cicluri de ceas. Această metodă este cel mai bine utilizată pentru a schimba starea unei ieșiri în starea sa opusă dacă starea inițială este necunoscută.

Setarea/resetarea registrului de biți portului GPIO (GPIOx_BSRR)

Spre deosebire de metoda anterioară, scrierea lui 0 la oricare dintre biții acestui registru nu va duce la nimic (și, în general, toți biții sunt doar pentru scriere!). Scrierea 1 la biții 0-15 va avea ca rezultat setarea unui „1” la ieșirea corespunzătoare a MK. Scrierea 1 la biții 16-31 va seta „0” la ieșirea corespunzătoare a MK. Această metodă este de preferat celei anterioare dacă trebuie să setați o anumită valoare pe pinul „MK”, în loc să o schimbați.

Să aprindem LED-ul!
După ce ați găsit adresele tuturor registrelor necesare, puteți scrie un program care aprinde LED-ul:
void main() ( //Activează tactarea portului D *(nesemnat lung*)(0x40023830) |= 0x8; //întârziere mică pentru GPIOD pregătiți-vă volatil nesemnat lung i=0; i++; i++; i++; i=0; / /Setați PD13 ca ieșire de uz general *(nesemnat lung*)(0x40020C00) = (*(nesemnat lung*)(0x40020C00)& (~0x0C000000)) | (0x04000000); //Porniți LED-ul! *(nesemnat lung*) (0x40020C14) |= 0x2000; în timp ce(1); )
Poate fi compilat ( Proiect->Compilare) și umpleți ( Proiect->Descărcare->Descărcare aplicație activă). Sau rulați depanarea ( Proiect->Dpwnload și Debug) și începeți execuția (F5).
LED-ul s-a aprins!
LED intermitent
Aprinderea intermitentă a LED-ului nu este altceva decât pornirea și oprirea alternativă cu o întârziere între aceste acțiuni. Cel mai simplu mod este să porniți și să opriți într-o buclă veșnică și să introduceți o întârziere între ele.
void main() ( //Activează tactarea portului D *(nesemnat lung*)(0x40023830) |= 0x8; //întârziere mică pentru GPIOD pregătiți-vă volatil nesemnat lung i=0; i++; i++; i++; i=0; / /Setați PD13 ca ieșire de uz general *(unsigned long*)(0x40020C00) = (*(unsigned long*)(0x40020C00)& (~0x0C000000)) | (0x04000000); while(1) ( //Aprindeți LED-ul *( nesemnat lung*)(0x40020C14) |= 0x2000; //Întârziere pentru (i=0; i<1000000 ;++i); //Turn LED OFF *(unsigned long*)(0x40020C14) &= ~0x2000; //Delay for(i=0; i<1000000 ;++i); } }
Valoarea de întârziere de 1.000.000 a fost selectată experimental, astfel încât perioada de clipire a LED-ului să fie vizibilă pentru ochi, dar să nu fie prea lungă.
Optimizarea algoritmului
Dezavantajul abordării alese cu LED-uri intermitente este că nucleul MK își petrece cea mai mare parte a timpului în bucle goale, deși ar putea face ceva util (în exemplul nostru nu există alte sarcini, dar acestea vor apărea în viitor).

Pentru a evita acest lucru, se folosește de obicei un numărător de cicluri, iar starea pinului MK se schimbă atunci când programul trece printr-un anumit număr de cicluri.
void main() ( //Activează tactarea portului D *(nesemnat lung*)(0x40023830) |= 0x8; //întârziere mică pentru GPIOD pregătiți-vă volatil nesemnat lung i=0; i++; i++; i++; i=0; / /Setați PD13 ca ieșire de uz general *(unsigned long*)(0x40020C00) = (*(unsigned long*)(0x40020C00)& (~0x0C000000)) | (0x04000000); while(1) (i++; if(!(i) %2000000)) ( //Porniți LED-ul *(nesemnat lung*)(0x40020С14) |= 0x2020; ) altfel dacă(!(i%1000000)) ( //Opriți LED-ul *(nesemnat lung*)(0x40020С14) = ~0x2000; ) ) )
Dar nici aici nu va fi fără probleme; odată cu modificarea numărului de comenzi executate în cadrul ciclului, perioada de clipire a LED-ului (sau perioada de execuție a altor comenzi din ciclu) se va schimba. Dar în acest stadiu nu putem lupta cu asta.

Un pic despre depanare
IAR vă permite să depanați o aplicație direct pe hardware. Totul arată aproape la fel ca depanarea unei aplicații pentru PC. Există un mod de execuție pas cu pas, introducerea unei funcții, vizualizarea valorilor variabilelor (În modul de depanare Vizualizare->Vizionare->Vizionare1/4).

Dar, în plus, este posibil să vizualizați valorile registrelor kernelului, registrelor speciale ale unităților periferice (View->Register), etc.
Vă recomand cu tărie să vă familiarizați cu capacitățile depanatorului în timp ce învățați programarea MK.

Câteva cuvinte în concluzie

Poate că mulți vor spune că scrierea manuală a adreselor într-un program nu este corectă, deoarece producătorul oferă fișiere cu definiții ale registrelor și câmpurilor de biți, biblioteci pentru lucrul cu periferice și alte instrumente care ușurează viața dezvoltatorului. Sunt complet de acord cu acest lucru, dar cred în continuare că primii pași în programarea unui MK trebuie făcuți prin săpătura manuală a documentației, determinând independent registrele și câmpurile de biți necesare. Nu trebuie să utilizați acest lucru în viitor, dar cu siguranță trebuie să știți cum să o faceți.
Iată doar câteva motive pentru această afirmație:
  • Uneori bibliotecile de la producător conțin erori! Odată aproape că am ratat un termen limită pentru proiect din cauza asta. Am re-lipit cipul de mai multe ori, crezând că cristalul a fost deteriorat în timpul lipirii (asta se întâmplase înainte). Problema a fost că adresa registrului special a fost introdusă greșit în bibliotecă. Acest lucru se întâmplă de obicei cu liniile MK sau MK care tocmai au intrat pe piață.
  • Bibliotecile pentru lucrul cu periferice de la unii producători nu implementează toate capacitățile unităților periferice. Am păcătuit mai ales cu asta Luminar Micro, care ulterior au fost cumpărate de TI. A trebuit să scriu manual inițializarea perifericelor.
  • Mulți oameni se obișnuiesc să înceapă programarea MK studiind exemple. Cred că mai întâi trebuie să decideți ce vă permite să implementați MK. Acest lucru poate fi înțeles doar citind documentația. Dacă ceva nu este în exemple, asta nu înseamnă că hardware-ul nu îl acceptă. Ultimul exemplu este suportul hardware PTP STM32. Desigur, puteți găsi ceva online, dar nu este inclus în setul standard de la producător.
  • Driverele unităților periferice de la unii producători sunt atât de neoptimizate încât comutarea stării unui pin folosind biblioteca durează până la 20 de cicluri de ceas. Acesta este un lux inaccesibil pentru unele sarcini.

Mulțumesc tuturor celor care mi-au citit postarea, a ieșit mult mai mult decât mă așteptam la început.
Aștept cu nerăbdare comentariile dumneavoastră și criticile motivate. Dacă cei care îl citesc au o dorință, voi încerca să continui seria articolelor. Poate că cineva are idei despre subiecte care ar merita abordate - m-aș bucura să le aud.

Publicat 08.09.2016

Microcontrolere STM32 devin din ce în ce mai populare datorită puterii lor, perifericelor destul de diverse și flexibilității. Vom începe să studiem folosind o placă de testare bugetară, al cărei cost nu depășește 2 USD (de la chinezi). Vom avea nevoie și noi ST-Link programator, al cărui cost este de aproximativ 2,5 USD (de la chinezi). Astfel de sume de cheltuieli sunt accesibile atât pentru elevi, cât și pentru școlari, așa că îmi propun să începem cu această variantă bugetară.


Acest microcontroler nu este cel mai puternic dintre STM32, dar nici cel mai slab. Există diverse plăci cu STM32, inclusiv Descoperire care a costat aproximativ 20 de dolari. Pe astfel de plăci, aproape totul este la fel ca pe placa noastră, plus un programator. În cazul nostru, vom folosi programatorul separat.

Microcontroler STM32F103C8. Caracteristici

  • Miez ARM Cortex-M3 pe 32 de biți
  • Frecventa maxima 72MHz
  • Memorie flash de 64 Kb pentru programe
  • memorie SRAM de 20 Kb
  • Alimentare 2,0 … 3,3 V
  • 2 x ADC pe 12 biți (0 ... 3,6 V)
  • Controler DMA
  • 37 intrări/ieșiri tolerante 5V
  • 4 temporizatoare pe 16 biți
  • 2 cronometre watchdog
  • I2C – 2 autobuze
  • USART – 3 autobuze
  • SPI – 2 autobuze
  • Interfață USB 2.0 de viteză maximă
  • RTC – ceas încorporat

Disponibil pe placa STM32F103C8

  • Porturi de ieșire A0-A12, B0-B1, B3-B15, C13-C15
  • Micro USB prin care poți alimenta placa. Placa are un stabilizator de tensiune de 3,3 V. Alimentarea de 3,3 V sau 5 V poate fi furnizată la pinii corespunzători de pe placă.
  • Buton Resetați
  • Doi săritori BOOT0Și BOOT1. Îl vom folosi în timpul flashing via UART.
  • Două cuarț 8 MHz și 32768 Hz. Microcontrolerul are un multiplicator de frecventa, asa ca cu un quartz de 8 MHz putem ajunge la frecventa maxima a controlerului de 72 MHz.
  • Două LED-uri. PWR– semnalează că este furnizată energie. PC13– conectat la ieșire C13.
  • Conector pentru programator ST-Link.

Deci, să începem prin a încerca să flashăm microcontrolerul. Acest lucru se poate face prin USART sau folosind un programator ST-Link.

Puteți descărca fișierul de testare pentru firmware. Programul clipește LED-ul de pe placă.

Firmware-ul STM32 folosind adaptorul USB-Uart pentru Windows

În memoria sistemului STM32 Există Bootloader. Bootloader-ul este înregistrat în etapa de producție și orice microcontroler STM32 poate fi programat prin interfață USART folosind un adaptor USART-USB. Astfel de adaptoare sunt cel mai adesea realizate pe baza microcircuitelor populare FT232RL. Mai întâi de toate, conectați adaptorul la computer și instalați driverele (dacă este necesar). Puteți descărca drivere de pe site-ul producătorului FT232RL– ftdichip.com. Trebuie să descărcați drivere VCP(port com virtual). După instalarea driverelor, pe computer ar trebui să apară un port serial virtual.


Conectare RXȘi TX ieșiri către pinii corespunzători USART1 microcontroler. RX conectați adaptorul la TX microcontroler (A9). TX conectați adaptorul la RX microcontroler (A10). Deoarece USART-USB are ieșiri de putere de 3,3 V, vom furniza energie plăcii de la acesta.

Pentru a pune microcontrolerul în modul de programare, trebuie să setați pinii BOOT0Și BOOT1 la starea dorită și reporniți-l cu butonul Resetați sau opriți și porniți alimentarea microcontrolerului. Pentru asta avem săritori. Combinații diferite forțează microcontrolerul în moduri diferite. Suntem interesați doar de un singur mod. Pentru a face acest lucru, microcontrolerul are BOOT0 ar trebui să existe unul logic și rezultatul BOOT1– zero logic. Pe placă, aceasta este următoarea poziție a jumperului:

După apăsarea butonului Resetați sau deconectarea și conectarea alimentării, microcontrolerul trebuie să intre în modul de programare.

Software-ul firmware

Dacă folosim un adaptor USB-UART, numele portului va fi cam așa /dev/ttyUSB0

Obțineți informații despre cip

Rezultat:

Citim de pe cip în fișierul dump.bin

sudo stm32flash -r dump.bin /dev/ttyUSB0

Scrieți pe cip

sudo stm32flash -w dump.bin -v -g 0x0 /dev/ttyUSB0

Rezultat:

Stm32flash 0.4 http://stm32flash.googlecode.com/ Folosind parser: Raw BINARY Interfață serial_posix: 57600 8E1 Versiunea: 0x22 Opțiunea 1: 0x00 Opțiunea 2: 0x00 ID dispozitiv: 0x0410 (Medium-dens: 120Kid) bootloader) - Flash: 128KiB (dimensiunea sectorului: 4x1024) - Opțiune RAM: 16b - System RAM: 2KiB Scriere în memorie Stergerea memoriei Adresă scrisă și verificată 0x08012900 (100,00%) Gata. Începe execuția la adresa 0x08000000... gata.

Firmware-ul STM32 utilizând programatorul ST-Link pentru Windows

Când utilizați un programator ST-Link concluzii BOOT0Și BOOT1 nu sunt utilizate și trebuie să fie în poziția standard pentru funcționarea normală a controlerului.

(Carte în rusă)

marcaj STM32

Familia de dispozitiveTip produsSubfamilie de dispozitiveNumăr de pinDimensiunea memoriei flashPachetInterval de temperatură
STM32 =
Microcontroler pe 32 de biți bazat pe ARM
F = de uz general
L = Putere ultra-scăzută
TS = Ecran tactil
W = sistem wireless pe cip
60 = rezistiv multitouch
103 = linia de performanță
F = 20 pini
G = 28 de pini
K = 32 pini
T = 36 pini
H = 40 pini
C = 48/49 pini
R = 64 pini
O=90 pini
V = 100 pini
Z = 144 pini
I = 176 pini
B = 208 pini
N = 216 pini
4 = 16 Kbytes de memorie Flash
6 = 32 Kbytes de memorie Flash
8 = 64 Kbytes de memorie Flash
B = 128 Kbytes de memorie Flash
Z = 192 Kbytes de memorie Flash
C = 256 Kbytes de memorie Flash
D = 384 Kbytes de memorie Flash
E = 512 Kbytes de memorie Flash
F = 768 Kbytes de memorie Flash
G = 1024 Kbytes de memorie Flash
I = 2048 Kbytes de memorie Flash
H = UFBGA
N=TFBGA
P = TSSOP
T = LQFP
U = V/UFQFPN
Y = WLCSP
6 = Interval de temperatură industrial, –40…+85 °C.
7 = Interval de temperatură industrial, -40…+ 105 °C.
STM32F103 C8 T6

Cum se elimină protecția la scriere/citire?

Dacă ați primit o placă cu STM32F103, dar programatorul nu o vede, asta înseamnă că chinezii au protejat memoria Flash a microcontrolerului. Întrebarea „de ce?” hai sa il ignoram. Pentru a elimina blocarea, vom conecta un adaptor UART și vom programa prin el. Setăm jumperii pentru programare și pornim:

Voi face acest lucru de pe Ubuntu folosind utilitarul stm32flash.

1. Verificați dacă microcontrolerul este vizibil:

Sudo stm32flash /dev/ttyUSB0

Ar trebui să obțineți ceva de genul acesta:

Stm32flash 0.4 http://stm32flash.googlecode.com/ Interfață serial_posix: 57600 8E1 Versiune: 0x22 Opțiunea 1: 0x00 Opțiunea 2: 0x00 ID dispozitiv: 0x0410 (densitate medie) - Rezervat de către booter 20KiB: (RAM: 20KiB) 128 KiB (dimensiunea sectorului: 4x1024) - RAM opțiune: 16b - RAM de sistem: 2 KiB

2. Eliminați protecția la citire și apoi protecția la scriere:

Sudo stm32flash -k /dev/ttyUSB0 stm32flash 0.4 http://stm32flash.googlecode.com/ Interfață serial_posix: 57600 8E1 Versiune: 0x22 Opțiunea 1: 0x00 Opțiunea 2: 0x00 ID dispozitiv: 0x0x00000000000 512b rezervat de bootloader) - Flash: 128KiB (dimensiunea sectorului: 4x1024) - Opțiune RAM: 16b - RAM de sistem: 2KiB Flash de dezactivare a citirii Terminat. sudo stm32flash -u /dev/ttyUSB0 stm32flash 0.4 http://stm32flash.googlecode.com/ Interfață serial_posix: 57600 8E1 Versiune: 0x22 Opțiunea 1: 0x00 Opțiunea 2: 0x00 ID dispozitiv: 0x000000000000 512b rezervat de bootloader) - Flash: 128KiB (dimensiunea sectorului: 4x1024) - Opțiune RAM: 16b - RAM de sistem: 2KiB Flash de deprotecție la scriere Terminat.

Acum puteți lucra normal cu microcontrolerul.

Unele dintre microcontrolerele stm32 acceptă protocolul USB DFU (o listă a acestora poate fi găsită în nota de aplicație AN3156); firmware-ul poate fi încărcat pe astfel de MCU-uri prin USB obișnuit, folosind, de exemplu, DFuSe demo de la ST sau open source dfu -util. Totul este clar cu această opțiune și nu o voi descrie.

Pentru aceleași MK-uri (în special, cel folosit în placa BluePill - STM32F103C8T6), cărora le lipsește suportul DFU, într-un fel sau altul aveți nevoie de un programator, de exemplu ST-Link V2 Mini

Fixarea dispozitivului:

Conectarea la placă este simplă:

ST-Link STM32F103C8T6 3,3 V --- 3,3 V GND --- GND SWDIO --- DIO SWCLK --- DCLK

De asemenea, aveți nevoie de utilitarul ST-Link, îl puteți descărca de pe site-ul oficial st.com - link. Când vă conectați pentru prima dată, ar fi o idee bună să actualizați firmware-ul programatorului însuși. Selectați ST-LINK -> actualizare firmware, dacă este disponibil un firmware mai recent, atunci va fi ceva de genul acesta:

Selectați Da >>>>, firmware-ul este actualizat.

Apoi, deschideți fișierul firmware actual și selectați Target -> Connect. Informațiile despre MK-ul dvs. vor apărea și în fereastra de stare a utilitarului - aceasta înseamnă că programatorul este conectat corect și utilitarul poate contacta MK. Exemplu:

Apoi trebuie să faceți o curățare completă a cipului, selectați Țintă -> Ștergeți cip

Dacă, de exemplu, firmware-ul meu de la postarea controlerului pedalei și butoanelor a fost deja încărcat și trebuie să fie actualizat sau reîncărcat, atunci programatorul nu se va putea conecta la placă atât de ușor (pentru că folosesc pinii SWD în mod obișnuit GPIO-uri). În acest caz, există două opțiuni:

  1. rearanjați ambii săritori galbeni. În acest caz, placa va fi încărcată direct în bootloader-ul intern
  2. puteți face așa-numita Conectare sub Resetare. Pentru el secvența va fi așa:
  • în utilitarul ST-Link, selectați Țintă -> Setări
  • în Modul Resetare, selectați Resetare hardware
  • apăsați și mențineți apăsat butonul Reset de pe placă
  • Faceți clic pe OK în utilitarul ST-Link
  • eliberați butonul Reset de pe placă

PS. Dacă aveți o placă de dezvoltare SMT32F4Discovery, atunci aceasta are deja un programator în ea și poate fi folosită și pentru a flash-o altă placă. În acest caz, trebuie să utilizați conectorul SWD al STM32F4Discovery și să îndepărtați ambii jumperi CN3. Conectorul SWD are următorul pinout:

În ultimii ani, microcontrolerele pe 32 de biți (MCU) bazate pe procesoare ARM au cucerit rapid lumea electronicii. Această descoperire se datorează performanței ridicate, arhitecturii avansate, consumului redus de energie, costurilor reduse și instrumentelor avansate de programare.

POVESTE SCURTA
Numele ARM este un acronim pentru Advanced RISC Machines, unde RISC (Reduced Instruction Set Computer) reprezintă arhitectura redusă a procesorului setului de instrucțiuni. Numărul copleșitor de microcontrolere populare, precum familiile PIC și AVR, au și o arhitectură RISC, care a crescut performanța prin simplificarea decodării instrucțiunilor și accelerarea execuției acestora. Apariția microcontrolerelor ARM de 32 de biți avansate și productive ne permite să trecem la rezolvarea unor probleme mai complexe cărora MCU-urile pe 8 și 16 biți nu le mai pot face față. Arhitectura microprocesorului ARM cu un nucleu de 32 de biți și un set de instrucțiuni RISC a fost dezvoltată de compania britanică ARM Ltd, care dezvoltă exclusiv nuclee, compilatoare și instrumente de depanare. Compania nu produce MK-uri, ci vinde licențe pentru producția acestora. MK ARM este unul dintre segmentele cu cea mai rapidă creștere de pe piața MK. Aceste dispozitive folosesc tehnologii de economisire a energiei, astfel încât sunt utilizate pe scară largă în sistemele încorporate și domină piața dispozitivelor mobile pentru care este important un consum redus de energie. În plus, microcontrolerele ARM sunt utilizate în mod activ în comunicații, dispozitive portabile și încorporate unde este necesară o performanță ridicată. O caracteristică a arhitecturii ARM este nucleul de calcul al procesorului, care nu este echipat cu niciun element suplimentar. Fiecare dezvoltator de procesor trebuie să echipeze în mod independent acest nucleu cu blocurile necesare pentru sarcinile sale specifice. Această abordare a funcționat bine pentru marii producători de cipuri, deși inițial s-a concentrat pe soluții clasice de procesoare. Procesoarele ARM au trecut deja prin mai multe etape de dezvoltare și sunt bine cunoscute pentru familiile ARM7, ARM9, ARM11 și Cortex. Acesta din urmă este împărțit în subfamilii de procesoare clasice CortexA, procesoare în timp real CortexR și nuclee de microprocesoare CortexM. Miezurile CortexM au devenit baza pentru dezvoltarea unei clase mari de MCU-uri pe 32 de biți. Ele diferă de alte variante ale arhitecturii Cortex în primul rând prin utilizarea setului de instrucțiuni Thumb2 pe 16 biți. Acest set a combinat performanța și compactitatea instrucțiunilor „clasice” ARM și Thumb și a fost dezvoltat special pentru lucrul cu limbajele C și C++, ceea ce îmbunătățește semnificativ calitatea codului. Marele avantaj al microcontrolerelor construite pe nucleul CortexM este compatibilitatea lor cu software-ul, care teoretic permite utilizarea unui cod de program de limbaj de nivel înalt în modele de la diferiți producători. Pe lângă indicarea zonei de aplicare a nucleului, dezvoltatorii MK indică performanța nucleului CortexM pe o scară de zece puncte. Astăzi, cele mai populare opțiuni sunt CortexM3 și CortexM4. MCU-urile cu arhitectură ARM sunt produse de companii precum Analog Devices, Atmel, Xilinx, Altera, Cirrus Logic, Intel, Marvell, NXP, STMicroelectronics, Samsung, LG, MediaTek, MStar, Qualcomm, SonyEricsson, Texas Instruments, nVidia, Freescale, Milander , HiSilicon și altele.
Datorită arhitecturii optimizate, costul MCU-urilor bazate pe nucleul CortexM este în unele cazuri chiar mai mic decât cel al multor dispozitive pe 8 biți. Modelele „mai tinere” pot fi achiziționate în prezent pentru 30 de ruble. pentru corp, care creează concurență pentru generațiile anterioare de MK. MICROCONTROLLER STM32 Să luăm în considerare cel mai accesibil și mai răspândit MCU din familia STM32F100 de la STMicroelectronics, care este unul dintre cei mai importanți producători de MCU din lume. Compania a anunțat recent începerea producției unui MK pe 32 de biți care profită de industria industrială
Miezuri STM32 în aplicații cu costuri reduse. MCU-urile din familia STM32F100 Value Line sunt proiectate pentru dispozitive în care performanța MCU-urilor pe 16 biți nu este suficientă, iar funcționalitatea bogată a dispozitivelor „obișnuite” pe 32 de biți este redundantă. Linia de MCU STM32F100 se bazează pe un nucleu modern ARM CortexM3 cu periferice optimizate pentru utilizare în aplicații tipice în care au fost utilizate MCU-uri pe 16 biți. Performanța MCU STM32F100 la 24 MHz este superioară majorității MCU-urilor pe 16 biți. Această linie include dispozitive cu diferiți parametri:
● de la 16 la 128 kbytes de memorie flash de program;
● de la 4 la 8 kbytes de RAM;
● până la 80 de porturi de intrare/ieșire GPIO;
● până la nouă temporizatoare pe 16 biți cu funcții avansate;
● două cronometre watchdog;
● ADC de mare viteză pe 12 biți cu 16 canale;
● două DAC-uri pe 12 biți cu generatoare de semnal încorporate;
● până la trei interfețe UART care acceptă modurile IrDA, LIN și ISO7816;
● până la două interfețe SPI;
● până la două interfețe I2C care acceptă modurile SMBus și PMBus;
● Acces direct la memorie pe 7 canale (DMA);
● Interfata CEC (Consumer Electronics Control) inclusa in standardul HDMI;
● ceas în timp real (RTC);
● Controler de întrerupere imbricat NVIC.

Diagrama funcțională a STM32F100 este prezentată în Figura 1.

Orez. 1. Arhitectura liniei MK STM32F100

O comoditate suplimentară este compatibilitatea cu pini a dispozitivelor, care permite, dacă este necesar, utilizarea oricărui MK al familiei cu funcționalitate și memorie mai mari fără a relua placa de circuit imprimat. Linia de controlere STM32F100 este produsă în trei tipuri de pachete LQFP48, LQFP64 și LQFP100, având 48, 64 și, respectiv, 100 de pini. Atribuirea pinilor este prezentată în figurile 2, 3 și 4. Astfel de cazuri pot fi instalate pe plăci de circuite imprimate fără utilizarea de echipamente speciale, care este un factor semnificativ în producția la scară mică.


Orez. 2. MCU STM32 în pachet LQFP48 Fig. 3. MCU STM32 în pachet LQFP64


Orez. 4. MCU STM32 în pachet LQFP100

STM32F100 este un dispozitiv accesibil și optimizat bazat pe nucleul CortexM3, susținut de un mediu de dezvoltare avansat pentru familia de microcontrolere STM32, care conține
Biblioteci gratuite pentru toate perifericele, inclusiv controlul motorului și tastaturile tactile.

SCHEMA DE CONEXIUNE STM32F100C4
Să luăm în considerare utilizarea practică a MK folosind exemplul celui mai simplu dispozitiv STM32F100C4, care, totuși, conține toate blocurile principale ale liniei STM32F100. Schema circuitului electric a STM32F100C4 este prezentată în Figura 5.


Orez. 5. Schema de conectare pentru MK STM32F100C4

Condensatorul C1 asigură că MK este resetat la pornirea alimentării, iar condensatoarele C2-C6 filtrează tensiunea de alimentare. Rezistoarele R1 și R2 limitează curentul de semnal al pinii MK. Oscilatorul intern este folosit ca sursă de ceas, deci nu este nevoie să folosiți un cristal extern.


Intrările BOOT0 și BOOT1 vă permit să selectați metoda de încărcare a MK la pornirea alimentării în conformitate cu tabelul. Intrarea BOOT0 este conectată la magistrala potențial zero prin rezistența R2, care protejează pinul BOOT0 de un scurtcircuit atunci când este utilizat ca port de ieșire al PB2. Folosind conectorul J1 și un jumper, puteți modifica potențialul la intrarea BOOT0, determinând astfel modul în care este încărcat MK - din memoria flash sau din bootloader-ul încorporat. Dacă trebuie să încărcați MK din RAM, un conector similar cu un jumper poate fi conectat la intrarea BOOT1.
Programarea MK se realizează prin portul serial UART1 sau prin programatori speciali - depanatoarele JTAG sau STLink. Acesta din urmă face parte din popularul dispozitiv de depanare STM32VLDISCOVERY, prezentat în Figura 6. Pe placa STM32VLDIS COVERY, conectorul cu 4 pini al programatorului - STLink debugger - este desemnat SWD. Autorul articolului sugerează programarea MK prin portul serial UART1, deoarece este mult mai simplu, nu necesită echipamente speciale și nu este inferioară ca viteză față de JTAG sau ST Link. Orice computer personal (PC) care are un port serial COM sau un port USB cu un convertor USBRS232 poate fi folosit ca dispozitiv de control capabil să genereze comenzi și să afișeze rezultatele programului MK, precum și ca programator.

Pentru a interfața portul COM al unui PC cu un MK, este potrivit orice convertor de semnale RS232 în niveluri de semnal logic de la 0 la 3,3 V, de exemplu, microcircuitul ADM3232. Linia de transmisie TXD a portului serial al computerului, după convertorul de nivel, trebuie conectată la intrarea PA10 a microcontrolerului, iar linia receptorului RXD, printr-un convertor similar, la ieșirea PA9.

Dacă trebuie să utilizați un ceas MK nevolatil, ar trebui să conectați o baterie CR2032 cu o tensiune de 3 V și un rezonator cu quartz cu o frecvență de 32768 Hz. În acest scop, MK este echipat cu pini Vbat/GND și OSC32_IN/OSC32_OUT. Pinul Vbat trebuie mai întâi deconectat de la magistrala de alimentare de 3,3 V.

Terminalele libere rămase ale MK pot fi folosite după cum este necesar. Pentru a face acest lucru, ar trebui să fie conectați la conectorii care se află în jurul perimetrului plăcii de circuit imprimat pentru MK, prin analogie cu dispozitivele populare Arduino și placa de depanare STM32VLDISCOVERY.


Orez. 6. Depanați dispozitivul STM32VLDISCOVERY


Schema circuitului electric STM32VLDISCOVERY.

Astfel, în funcție de scopul și metoda de utilizare a MK, puteți conecta elementele necesare la acesta pentru a utiliza alte blocuri funcționale și porturi, de exemplu, ADC, DAC, SPI, I2C etc. În viitor, aceste dispozitive vor fi luate în considerare mai detaliat.

PROGRAMARE
Astăzi, multe companii oferă instrumente pentru crearea și depanarea programelor pentru microcontrolere STM32. Acestea includ Keil de la ARM Ltd, IAR Embedded Workbench pentru ARM, Atol lic TrueStudio, CooCox IDE, GCC și Eclipse IDE. Dezvoltatorul poate alege software-ul în funcție de preferințele sale. Mai jos vom descrie setul de instrumente Keil uVision 4 de la compania Keil, care acceptă un număr mare de tipuri de microcontrolere, are un sistem dezvoltat de instrumente de depanare și poate fi folosit gratuit cu restricții privind dimensiunea codului generat de 32 kbytes ( care, de fapt, este maximul pentru microcontrolerele luate în considerare).

Începe ușor și rapid cu CooCox CoIDE.

Asadar, haideti sa începem. Accesați site-ul oficial CooCox și descărcați cea mai recentă versiune a CooCox CoIDE. Pentru a descărca trebuie să vă înregistrați, înregistrarea este simplă și gratuită. Apoi instalați fișierul descărcat și rulați-l.

CooCox CoIDE- un mediu de dezvoltare bazat pe Eclipse, care, pe lângă STM32, suportă o grămadă de alte familii de microcontrolere: Freescale, Holtek, NXP, Nuvoton, TI, Atmel SAM, Energy Micro etc. Cu fiecare nouă versiune de CoIDE, lista de microcontrolere este actualizată constant. După instalarea cu succes a CoIDE, rulați:

Va apărea fereastra de pornire a pasului 1, în care trebuie să selectați producătorul microcontrolerului nostru. Apăsați ST și mergeți la Pasul 2 (selectarea unui microcontroler), în care trebuie să selectați un anumit model. Avem STM32F100RBT6B, așa că faceți clic pe modelul corespunzător:

În partea dreaptă, fereastra Ajutor afișează scurte caracteristici ale fiecărui cip. După selectarea microcontrolerului de care avem nevoie, trecem la al treilea pas, Pasul 3 - la selectarea bibliotecilor necesare pentru lucru:

Să creăm un proiect simplu pentru a clipi un LED, așa cum este obișnuit pentru microcontrolere de învățare.

Pentru a face acest lucru, avem nevoie de biblioteca GPIO, când este activată, CoIDE vă va cere să creați un nou proiect. Faceți clic pe Da pe această propunere, indicați folderul în care va fi stocat proiectul nostru și numele acestuia. În același timp, CoIDE se va conecta la proiect și alte 3 necesare pentru ca biblioteca să funcționeze și, de asemenea, va crea toată structura de proiect necesară:

Un alt lucru bun despre CoIDE este că are capacitatea de a încărca exemple direct în mediul de dezvoltare. În fila Componente puteți vedea că există exemple pentru aproape fiecare bibliotecă, faceți clic pe GPIO (cu 4 exemple) și le vedeți:

Puteți adăuga propriile exemple acolo. După cum puteți vedea în captura de ecran de mai sus, exemplele conțin deja cod pentru a clipi LED-ul GPIO_Blink. Puteți face clic pe butonul de adăugare și va fi adăugat la proiect, dar ca fișier inclus, așa că o vom face diferit și pur și simplu vom copia întregul exemplu de cod în fișierul main.c. Singurul lucru este să înlocuiți linia void GPIO_Blink(void) cu int main(void). Așadar, apăsați F7 (sau selectați Project->Build din meniu) pentru a compila proiectul și... nu există așa noroc!

Mediul are nevoie de un compilator GCC, dar noi nu avem unul. Prin urmare, accesați pagina Instrumente GNU pentru procesoarele ARM Embedded, selectați tipul dvs. de sistem de operare din dreapta și descărcați cea mai recentă versiune a lanțului de instrumente. Apoi rulăm fișierul și instalăm gcc toolchain. În continuare, în setările CoIDE vom indica calea corectă către lanțul de instrumente:

Apăsați din nou F7 (Proiect->Build) și vedeți că compilarea a avut succes:

Tot ce rămâne este să flashi microcontrolerul. Pentru a face acest lucru, conectăm placa noastră la computer folosind USB. Apoi, în setările depanatorului, trebuie să instalați ST-Link; pentru a face acest lucru, selectați Proiect->Configurare în meniu și deschideți fila Debugger. Selectați ST-Link din lista derulantă și închideți fereastra:

Să încercăm să flash MK. În meniu, selectați Flash->Program Download (sau faceți clic pe pictograma corespunzătoare din bara de instrumente) și vedeți că MK-ul a fost flashat cu succes:

Vedem un LED care clipește pe placă, cred că nu are sens să furnizăm un videoclip sau o fotografie, pentru că... toată lumea a văzut-o.

De asemenea, în CoIDE funcționează diverse moduri de depanare; pentru a face acest lucru, apăsați CTRL+F5 (sau în meniul Debug->Debug):

Asta e tot. După cum puteți vedea, configurarea și lucrul cu CoIDE este foarte simplu. Sper că acest articol vă va încuraja să studiați microcontrolere STM32 foarte promițătoare și ieftine.

Pentru a crea un proiect minimal vom avea nevoie de: un controler stm32 (am un stm32f103), niște fire, un LED (pentru testare).
Nici macar nu vom atarna cuartul, pentru a nu complica procesul.
Este foarte convenabil să utilizați această placă adaptor cu LQFP:

Costă în jur de 1 USD. Dar nu este nevoie să otrăviți cărări mici.
Asamblam următorul circuit (pentru stm32f103 48 picioare):

Conectorul SWD contine 6 pini, deoarece pe STM32F4 discovery (pe care o folosesc) este 6, deși al 6-lea nu este folosit.
Atârnăm toate pământurile (GND) pe pământ, iar sursa de alimentare (VDD) pe sursa de alimentare (am răsucit totul împreună). Nu vom închide filtrele; oricum, fără cuarț nu putem vorbi despre nici un fel de precizie.
Pinout-ul stm32f103 arată astfel:

Alimentarea plăcii trebuie să fie separată (3,3V). Alimentarea de la SWD (1V) nu va fi suficientă.

Practic asta este. Introducem conectorul în placă, după ce au scos mai întâi jumperii de pe placă.
Rulăm st-util și vedem:

$ st-util 2012-09-10T15:14:05 INFO src/stlink-usb.c: -- exit_dfu_mode 2012-09-10T15:14:05 INFO src/stlink-common.c: Se încarcă parametrii dispozitivului.... 2012-09-10T15:14:05 INFO src/stlink-common.c: Dispozitivul conectat este: F1 Dispozitiv cu densitate medie, id 0x20036410 2012-09-10T15:14:05 INFO src/stlink-common.c: SRAM size : 0x5000 de octeți (20 KiB), Flash: 0x10000 de octeți (64 KiB) în pagini de 1024 de octeți ID-ul cipului este 00000410, ID-ul de bază este 1ba01477. KARL - ar trebui să citească înapoi ca 0x03, nu 60 02 00 00 init watchpoints Ascultare la *:4242...

Poți coase.

Iată un proiect pentru tine - o diodă intermitent pentru eclipsă. Descarca .
Dacă folosești IAR sau altceva, gesturile cu st-util nu sunt necesare.

Acțiune