Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • Windows Phone
  • Mikrokontroleri, procesori, projekti, programiranje. Zaštita bitova GPIO konfiguracije

Mikrokontroleri, procesori, projekti, programiranje. Zaštita bitova GPIO konfiguracije

Glavni registri I/O porta STM32 mikrokontrolera

Port se odnosi na određeni imenovani skup nogu mikrokontrolera. U STM mikrokontrolerima se nazivaju GPIOA, GPIOB, GPIOC, itd. I/O portovi u STM32 mikrokontrolerima imaju po pravilu 16 linija (noga). Linija označava jednu ili drugu nogu mikrokontrolera. Svaka linija porta može se konfigurirati na specifičan način i obavljati sljedeće funkcije:

  • digitalni ulaz;
  • digitalni izlaz;
  • ulaz eksternog prekida;
  • I/O funkcija ostalih modula mikrokontrolera.

Možete konfigurirati port za željeni način rada pomoću registara mikrokontrolera. Ovim registrima se može pristupiti direktno, a mogu se koristiti i posebne metode iz periferne biblioteke.

Pogledajmo glavne registre potrebne za rad sa I/O portovima.

Registri odgovorni za konfiguraciju porta

Prije nego što počnete raditi s izlaznim portom, morate ga konfigurirati za svoje potrebe.

Konfiguracijski registri su odgovorni za postavljanje ili konfiguraciju porta. U mikrokontrolerima porodica STM32F302xx, STM32F303xx i STM32F313xx, ovo su sljedeći registri:

  • GPIOx_MODER;
  • GPIOx_OTYPER;
  • GPIOx_OSPEEDR;
  • GPIOx_PUPDR.

GPIOx_MODER registar (gdje je x = A ... F)

To je 32 bita registar je odgovoran za način rada linije. Potrebna su 2 bita za konfiguraciju unaprijed definirane linije. Moguće su sljedeće kombinacije:

  • 00 - linija je postavljena za ulazak;
  • 01 - za izlaz;
  • 10- alternativni način rada;
  • 11 - analogni način rada.

GPIOx_TYPER registar (gdje je x = A ... F)


Ovaj registar se koristi za konfiguraciju tipa operacije na liniji. Koristi 16 bitova u radu, preostalih 16 je rezervirano. Uzima sljedeće vrijednosti:

  • 0 - push-pull mod;
  • 1 - otvoreni odvod

Registrirajte GPIOx_PUPDR (gdje je x = A ... F)


Podaci registra su odgovorni za izvlačenje. Uzima sljedeće vrijednosti:

  • 00 - bez aparatića
  • 01 - zatezanje u plusu hrane
  • 10 - povući na tlo

GPIOx_SPEEDR registar (gdje je x = A ... F)


Registar za podešavanje brzine linije.

  • 00 - 2 MHz;
  • 01 - 10 MHz;
  • 10 - 50MHz.

Izlazni registar (izlazni registar) GPIOx_ODR (gdje je x = A ... F) - registar izlaznih podataka


Ovaj registar se koristi za izlaz podataka na port. Prilikom upisivanja određenih vrijednosti u ovaj registar, slična vrijednost se postavlja na liniji (kraku). Pošto imamo 16 linija, a registar ima 32 bita, koristi se samo prvih (najmanje značajnih) 16 bita.

Ulazni registar (status porta ili registar ulaznih podataka) GPIOx_IDR (gdje je x = A ... F) - registar ulaznih podataka


Ovaj registar je samo za čitanje. Neka vrsta indikatora statusa porta. Analogni PINx u AVR mikrokontrolerima.

Registrirajte pobitno podešavanje izlaznog porta GPIOx_BSRR


Ovaj registar postavlja status pina u izlaznom portu bit po bit.

Više detalja o svim registrima određenog mikrokontrolera možete pronaći u referens manual.pdf koji se može preuzeti sa službene web stranice www.st.com

Postavljanje porta mikrokontrolera pomoću biblioteke

Također, port se može konfigurirati pomoću posebne biblioteke, koja sadrži različite metode za rad sa I/O registrima, a deklariraju se i posebne varijable. Ova biblioteka oslobađa programera od potrebe da "ručno" izračuna koju vrijednost treba upisati u određeni registar.

Pogledajmo primjer koda koji uključuje LED

#include "stm32f30x.h" // Zaglavlje uređaja #include "stm32f30x_rcc.h" #include "stm32f30x_gpio.h" void init_led (void) (RCC_APB2PeriphClockCmd (GPIOE, ENABLE, ENABLE GPIODIEfGPIDyet_definition_definition_defined; GPIODE_Mode_GPIIDenit; maximalna brzina); / Režim izlaza GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // Odredite nogu na koju je povezana GPIO_Init LED (GPIOE, GPIO_InitStructure); // Inicijalizacija strukture) int main (init_id) (struktura) int GPIO_Pin GPIO_Pin GPIO_Pin ); / Postavite visoko stanje na nozi dok (1) (_NOP (;))

Radi uštede energije, sve periferne jedinice mikrokontrolera su onemogućene. Da biste "aktivirali" ovu ili onu periferiju, prvo joj morate poslati sat signale.

Radimo sa GPIOE portom, tako da moramo omogućiti taktiranje pomoću metode

RCC_APB2PeriphClockCmd (uint32_t RCC_APB2Periph, FunctionalState NewState);

Što uzima dvije vrijednosti, prva je sam port koji trebamo omogućiti, a druga je stanje ovog porta, omogućeno ili onemogućeno.

Pokrivali smo rad sa bitskim operacijama i binarnim brojevima, postavljajući tako temelj za novu temu. U ovoj lekciji ćemo razmotriti još jedno pitanje: šta su registri i kako sa njima raditi?

Memorija i registri

Jedna od najvažnijih vještina potrebnih za rad s mikrokontrolerima je sposobnost interakcije s registrima. Hajde da to sami shvatimo, Šta je?

Općenito, registar je posebna vrsta memorije unutar mikrokontrolera koja se koristi za kontrolu procesora i perifernih uređaja. Svaki registar u ARM arhitekturi je memorijska ćelija i ima dužinu od 32 bita, pri čemu svaki bit može biti predstavljen kao sićušni prekidač kojim se kontroliše jedan ili drugi parametar mikrokontrolera.

Svaki od registara ima svoj serijski broj - adresu. Adresa registra je označena 32-bitnim brojem predstavljenim u heksadecimalnoj notaciji. Upisivanjem na adresu registra određene kombinacije jedinica i nula, koje su obično predstavljene u heksadecimalnom obliku, konfiguriše se i kontroliše jedan ili drugi čvor u MC. Podsjetimo da u programu za rad sa bitnim operacijama možemo predstaviti proizvoljan skup jedinica i nula kao heksadecimalni broj. Općenito, vrijedi napomenuti da postoje dvije vrste registara: registri opšte namjene i posebni registri. Prvi se nalaze unutar MK jezgre, a drugi su dio RAM memorije.

Vrijedi i to napomenuti Referentni priručnik koji smo preuzeli je jedna velika referenca za registre sadržane u ciljnom mikrokontroleru, a CMSIS biblioteka nam omogućava da operišemo sa simboličkim imenima registara umesto numeričkim adresama. Na primjer, u registar 0x40011018 možemo upućivati ​​jednostavno korištenjem simboličkog imena GPIOC_BSSR... Razmotrit ćemo konkretne primjere konfiguracije tokom analize našeg programa iz prve lekcije.

Dakle, obično se struktura registra opisuje u obliku male tabele sa naznakom:

  1. Imena registra i opis njegove namjene
  2. Registrirajte adrese ili pomaknite od osnovne adrese
  3. Zadane vrijednosti nakon resetiranja
  4. Vrsta pristupa ćelijama registra (čitanje, pisanje, čitanje/pisanje)
  5. Vrijednosti i opisi parametara snimljenih bitova
Pogledajmo primjer rada s registrima u konkretnoj situaciji kako bismo dobili opću ideju o principima postavljanja mikrokontrolera.

Raščlanjivanje koda iz prve lekcije

Dakle, prisjetimo se problema koji smo riješili u prvoj lekciji koristeći gotov primjer koda: morali smo napisati program koji bi naizmjenično uključivao dvije LED diode na Discovery ploči (možda ne dvije ako imate drugu verziju Discovery board) sa vremenskim intervalom ...

Pogledajmo još jednom kod programa koji smo koristili da naš MK potresa dvije noge na kojima se nalaze naše LED diode:

Main.c kod

/ * Datoteka zaglavlja za našu porodicu mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; / * Konfigurišite način rada portova PC8 i PC9 u izlazu * / GPIOC -> MODER = 0x50000; / * Postavite tip izlaza na Push-Pull mod * / GPIOC-> OTYPER = 0; / * Postavite brzinu port na Low * / GPIOC-> OSPEEDR = 0; dok (1) (/ * Uključite PC8 LED, isključite PC9 * / GPIOC-> ODR = 0x100; za (int i = 0; i<500000; i++){} // Искусственная задержка /* Зажигаем светодиод PC9, гасим PC8 */ GPIOC->ODR = 0x200; za (int i = 0; i<500000; i++){} // Искусственная задержка } }


Prije svega, kada radimo sa STM32, čak i za tako jednostavan zadatak kao što je uključivanje i isključivanje LED-a, prvo moramo odgovoriti na nekoliko pitanja:
  1. Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?
  2. Kako uključiti i isključiti LED?
Na njih ćemo odgovoriti redom.

Gdje su naše LED diode povezane? Koji pin mikrokontrolera?

Da bismo vidjeli gdje se sve nalazi na ploči Discovery, a posebno LED diode koje su nam potrebne, trebamo otvoriti datoteku sheme, bilo onu koju smo preuzeli sa ST web stranice ili direktno sa Keila:


Nakon otvaranja sheme, vidjet ćemo dijagram svega što se nalazi na ploči - ST-Link kolo, cjevovod svih perifernih uređaja i još mnogo toga. Trenutno nas zanimaju dvije LED diode, tražimo njihovu oznaku:


Kao što vidimo, naše LED diode su povezane na GPIOC port na 8 i 9 pinova.

Kako da omogućim taktiranje na željenom GPIO portu?

Općenito, svaki rad s periferijama u STM32 mikrokontrolerima svodi se na standardni slijed radnji:
  1. Omogućavanje takta odgovarajućeg perifernog modula. To se radi preko RCC registra slanjem signala takta direktno sa magistrale na kojoj se nalazi ovaj modul. Podrazumevano, taktiranje svih perifernih uređaja je onemogućeno kako bi se smanjila potrošnja energije.
  2. Postavljanje preko kontrolnih registara, promjenom parametara specifičnih za određeni periferni uređaj
  3. Direktno pokretanje i korištenje rezultata modula
Odnosno, da bismo započeli, moramo započeti taktiranje na GPIOC portu. To se radi direktno pristupom RCC registru, koji je odgovoran za klokovanje svega i svakoga i uključivanje satnog signala sa magistrale na koju je povezan naš GPIO port.

Pažnja! Pitanje u vezi sa sistemom takta, njegovom konfiguracijom i upotrebom, detaljno ćemo razmotriti u posebnom članku.

Pronađi na koju magistralu je povezan naš GPIOC port može se naći u Datasheet-u na našem MK-u u odjeljku Mapiranje memorije u Tabeli 16. Granične adrese perifernog registra STM32F051xx.


Kao što ste već primijetili, autobus koji nam je potreban zove se AHB2. Da biste se detaljnije upoznali sa registrom u kojem je omogućeno taktiranje na GPIO portu koji nam je potreban na AHB sabirnici, potrebno je otići na odgovarajući odjeljak u Referentnom priručniku. Po imenu registara možemo odrediti onaj koji nam je potreban:


Idemo do ove tačke i vidimo naš 32-bitni registar, njegovu ofset adresu, podrazumevanu vrednost, način pristupa registru i nabrajanje za šta je odgovoran svaki bit u registru.


Gledamo u tabelu i vidimo nešto što liči na opciju za omogućavanje takta na GPIO portovima. Idite na opis i pronađite opciju koja nam je potrebna:


U skladu s tim, ako postavimo 19 bita na vrijednost "1", to će omogućiti taktiranje na I / O C portu - odnosno na našem GPIOC-u. Osim toga, trebamo omogućiti odvojeno jedan bit iz grupe, bez utjecaja na ostatak, jer ne treba se mešati i nepotrebno menjati druga podešavanja.

Na osnovu materijala prethodne lekcije, znamo da za postavljanje određenog bita potrebno je logičkom operacijom "ILI" dodati trenutnu vrijednost registra sa maskom koja sadrži one bitove koje treba okrenuti on. Na primjer, dodajte zadanu vrijednost registra RCC-> AHBENR, tj. 0x14 i broj 0x80000 na taj način omogućavaju GPIOC taktiranje postavljanjem 19 bita:

Kako to možemo učiniti iz programa? Prilično je jednostavno. U ovom slučaju imamo dvije opcije:

  1. Upisivanje u registar direktno numeričke vrijednosti registra direktno preko njegove adrese.
  2. Konfiguracija pomoću CMSIS biblioteke
Ne postoji poseban problem u direktnom pisanju vrijednosti u registar, ali postoji nekoliko značajnih nedostataka. Prvo, takav kod postaje nečitljiv, a drugo, ne možemo odmah odrediti na koji se registar odnosi određena adresa u memoriji.

Odnosno, mogli bismo se pozvati na adrese registra direktno na adresi i napisati ovako:

IO uint32_t * register_address = (uint32_t *) 0x40021014U; // Adresa našeg registra u memoriji * (__ IO uint32_t *) register_address | = 0x80000; // Uključujemo 19 bita sa našim parametrom
Druga opcija mi se čini najatraktivnijom, jer CMSIS biblioteka je organizovana na način da se registru može pristupiti koristeći samo njegovo ime. Predprocesor će automatski zamijeniti sve digitalne vrijednosti adrese registra tokom obrade programskog teksta prije kompilacije. Pogledajmo pobliže ovo pitanje.

Predlažem da otvorimo naš projekat, koji smo napravili u prvoj lekciji, ili da preuzmemo prethodno pripremljeni odavde i izbrišemo cijeli sadržaj programa, ostavljajući samo uključenu datoteku zaglavlja, glavnu () funkciju i upute za omogućavanje takta ( trebat će nam za detaljnu analizu koda).

Naš kod će izgledati ovako:

/ * Datoteka zaglavlja za našu porodicu mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; )
Zadubimo se duboko u CMSIS biblioteku radi pregleda.

Da biste brzo došli do mjesta gdje je deklarirana ova ili ona konstanta ili varijabla, u Keil je implementirana zgodna funkcija. Desni klik na konstantu koja nam je potrebna, na primjer, na RCC:


I prelazimo u dubine CMSIS biblioteke, u kojoj ćemo vidjeti da svi registri dostupni za programsku kontrolu imaju oblik TypeDef struktura, uključujući naš RCC:


Nakon neuspjeha na ovaj način u RCC_TypeDef, vidjet ćemo strukturu u kojoj su opisana sva polja našeg registra:


Shodno tome, možemo se bezbedno pozvati na registar koji nam je potreban sa zapisom obrasca PERIPH_MODULE-> REGISTER i dodijeliti mu određeno značenje.

Pored mnemoničke oznake registara, postoje i oznake specifičnih bitova. Ako ne uspijemo deklarirati parametar RCC_AHBENR_GPIOCEN iz našeg programa, također ćemo vidjeti deklaraciju svih parametara:


Tako, koristeći CMSIS biblioteku, dobijamo lakonski čitljiv zapis parametra koji nam je potreban u registru, kroz čiju instalaciju započinjemo taktiranje na portu koji nam je potreban:

/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN;
Kao zadatak: koristite Keil-ove mogućnosti da odredite kako je adresa registra RCC-> AHBENR dobijena kao 0x40021014.

Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?

Dakle, znamo da su LED diode koje su nam potrebne povezane na GPIOC port na pinove PC8 i PC9. Moramo ih postaviti tako da LED svijetli. Želio bih odmah napraviti rezervaciju da ćemo GPIO portove detaljnije razmotriti u drugom članku, a ovdje ćemo se koncentrirati na rad s registrima.

Prije svega, trebamo prebaciti način rada pinova PC8 i PC9 u Output mod. Ostatak parametara porta može se ostaviti na zadanim vrijednostima. Idite na Referentni priručnik u odjeljku 9. U/O opće namjene (GPIO) i otvorite stavku odgovornu za način rada pinova GPIO porta i vidite da je MODER registar odgovoran za ovaj parametar:


Sudeći po opisu, da bismo pinove PC8 i PC9 postavili u izlazni mod, moramo upisati 01 u odgovarajuća polja GPIOC registra.

To se može učiniti direktnom instalacijom koristeći numeričke vrijednosti:


Ili korištenjem definicija iz biblioteke:

/ * Uključite taktiranje na GPIO portu * / GPIOC-> MODER | = GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
Nakon ove instrukcije, naši PC8 i PC9 pinovi će ići u izlazni mod.

Kako uključiti LED?

Ako obratimo pažnju na listu dostupnih registara za kontrolu GPIO porta, možemo vidjeti ODR registar:


Svaki od odgovarajućih bitova je odgovoran za jedan od pinova porta. Njegovu strukturu možete vidjeti u nastavku:


Da bi se omogućila naizmjenična promjena stanja LED dioda, potrebno je uključiti / isključiti 8 i 9 bita sa određenim vremenskim intervalom. Odnosno, naizmjenično dodijelite vrijednosti registra 0x100 i 0x200.

To možemo učiniti direktnim dodjeljivanjem vrijednosti registru:

GPIOC-> ODR = 0x100; // Uključite PC8, isključite PC9 GPIOC-> ODR = 0x200; // Uključite PC9, isključite PC8
Možemo koristiti definicije iz biblioteke:

GPIOC-> ODR = GPIO_ODR_8; // Uključite PC8, isključite PC9 GPIOC-> ODR = GPIO_ODR_9; // Uključite PC9, isključite PC8
Ali pošto mikrokontroler radi vrlo brzo, nećemo primijetiti promjenu stanja LED dioda i vizualno će se činiti da su obje stalno uključene. Da bi zaista treptali, uvest ćemo vještačko kašnjenje u vidu ciklusa koji će neko vrijeme zaokupiti MC beskorisnim proračunima. Dobijate sljedeći kod:

/ * Uključujemo PC8 LED, gasimo PC9 * / GPIOC-> ODR = GPIO_ODR_8; za (int i = 0; i<500000; i++){} // Искусственная задержка /* Зажигаем светодиод PC9, гасим PC8 */ GPIOC->ODR = GPIO_ODR_9; za (int i = 0; i<500000; i++){} // Искусственная задержка
Ovim je završeno početno upoznavanje sa registrima i metodama rada sa njima.

Provjeravamo rezultate našeg koda

Mali lijep dodatak na kraju članka: Keil ima odličan alat za otklanjanje grešaka s kojim možemo korak po korak kroz naš program i vidjeti trenutno stanje bilo koje periferne jedinice. Da biste to učinili, nakon preuzimanja firmvera nakon kompilacije, možemo kliknuti na dugme Start Debug Session:

U STM32 postoji mnogo vrlo praktičnih i fleksibilnih tajmera. Čak i najmlađi mikrokontroler (STM32F030F4P6) ima 4 takva tajmera.

Da bismo koristili tajmer, moramo uključiti datoteku biblioteke periferije stm32f10x_tim.c. Isto tako, kliknite desnim tasterom miša u radnom prostoru (levi prozor) na grupu StdPeriphLib, Add -> Add files, datoteku LibrariesSTM32F10x_StdPeriph_Driversrcstm32f10x_tim.c.

Također morate omogućiti korištenje zaglavlja za ovu datoteku. Otvorite stm32f10x_conf.h (desni klik na ime ove datoteke u kodu, "Otvori stm32f10x_conf.h". Dekomentirajte red #include "stm32f10x_tim.h".

9. Dodajte tajmer

Prazno kašnjenje petlje je bogohuljenje, posebno na tako moćnom kristalu kao što je STM32, sa gomilom tajmera. Stoga ćemo ovo odlaganje napraviti pomoću tajmera.

U STM32 postoje različiti tajmeri sa različitim skupom svojstava. Najjednostavniji su osnovni tajmeri, teži su tajmeri opšte namene, a najsloženiji su napredni tajmeri. Jednostavni mjerači vremena su ograničeni samo na brojanje otkucaja. Kod složenijih tajmera pojavljuje se PWM. Najsofisticiraniji tajmeri, na primjer, mogu generirati 3-fazni PWM sa direktnim i inverznim izlazima i mrtvim vremenom. Dovoljan nam je jednostavan tajmer, broj 6.

Malo teorije

Sve što trebamo od tajmera je da brojimo do određene vrijednosti i generišemo prekid (da, naučit ćemo i kako koristiti prekide). Tajmer TIM6 se taktuje sa sistemske magistrale, ali ne direktno, već preko preskalera - jednostavnog programabilnog brojača (samo pomislite, u SSSR-u su se proizvodila posebna mikrokola-brojača, a programabilna su bila u posebnom deficitu - a sada O takvom šalteru govorim samo u prolazu). Preskaler se može podesiti na bilo koju vrijednost od 1 (tj., puna frekvencija magistrale, 24 MHz, ide na mjerač) do 65536 (tj. 366 Hz).

Signali sata, zauzvrat, povećavaju interni brojač tajmera, počevši od nule. Čim vrijednost brojača dostigne vrijednost ARR, brojač se prelije i javlja se odgovarajući događaj. Po nastanku ovog događaja, tajmer ponovo učitava 0 u brojač i počinje da broji od nule. Istovremeno, može izazvati prekid (ako je konfigurisan).

U stvari, proces je malo složeniji: postoje dva ARR-a - eksterni i interni. Prilikom brojanja, trenutna vrijednost se tačno upoređuje sa internim registrom, a samo u slučaju prelivanja interni se ažurira sa eksternog. Dakle, možete bezbedno promeniti ARR dok tajmer radi - u bilo kom trenutku.

Kod

Kod će biti vrlo sličan prethodnom, jer inicijalizacija svih perifernih uređaja je ista - sa jedinim izuzetkom da TIM6 tajmer visi na APB1 magistrali. Stoga, omogućavanje tajmera: RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM6, ENABLE);

Sada postavljamo strukturu tipa TIM_TimeBaseInitTypeDef, inicijaliziramo je (TIM_TimeBaseStructInit), postavljamo je, prosljeđujemo je funkciji inicijalizacije tajmera (TIM_TimeBaseInit) i konačno uključujemo tajmer (TIM_Cmd).

Koji su magični brojevi? Kao što se sjećamo, sabirnica ima taktnu frekvenciju od 24 MHz (sa našim projektnim postavkama). Podešavajući preskaler tajmera na 24000, ovu frekvenciju podijelimo sa 24000 i dobijemo 1kHz. Upravo će ta frekvencija ići na ulaz brojača tajmera.

Vrijednost u brojaču je 1000. To znači da će se brojač preliti za 1000 taktova. za tačno 1 sekundu.

Nakon toga, zaista imamo radni tajmer. Ali to nije sve.

10. Pozabavimo se prekidima

U redu, prekida. Za mene su jednom (u vrijeme PIC-a) bili mračna šuma, i trudio sam se da ih uopće ne koristim - i stvarno nisam znao kako. Međutim, oni sadrže snagu, koju je općenito nedostojno zanemariti. Istina, prekidi u STM32 su još složenija stvar, posebno mehanizam njihovog pomjeranja; ali o tome kasnije.

Kao što smo ranije napomenuli, tajmer generiše prekid u trenutku prelivanja brojača - ako je obrada prekida ovog uređaja uopće omogućena, ovaj prekid je omogućen, a prethodni se briše. Analizirajući ovu frazu, razumijemo šta nam treba:

  1. Omogućite TIM6 tajmer prekide u potpunosti;
  2. Omogući prekid tajmera TIM6 za prelivanje brojača;
  3. Napišite proceduru za rukovanje prekidima;
  4. Nakon rukovanja prekidom, resetirajte ga.

Omogućavanje prekida

Iskreno, tu nema ništa komplikovano. Prije svega, omogućite TIM6 prekide: NVIC_EnableIRQ (TIM6_DAC_IRQn); Zašto takvo ime? Jer u STM32 jezgri, prekidi iz TIM6 i iz DAC-a imaju isti broj. Ne znam zašto se to radi - ekonomičnost, nedostatak soba ili samo neka nasljedna stvar - u svakom slučaju neće donijeti nikakve probleme, jer ovaj projekt ne koristi DAC. Čak i kada bi se u našem projektu koristio DAC, mogli bismo, prilikom ulaska u prekid, saznati ko ga je tačno uzrokovao. Gotovo svi ostali tajmeri imaju jedan prekid.

Konfiguriranje događaja izvora prekida: TIM_ITConfig (TIM6, TIM_DIER_UIE, ENABLE); - uključiti TIM6 tajmer prekid na događaju TIM_DIER_UIE, tj. Događaj ažuriranja ARR vrijednosti. Kao što se sjećamo sa slike, to se dešava istovremeno sa prelivanjem brojača - tako da je to upravo događaj koji nam je potreban.

Trenutno je kod za zadatke tajmera sljedeći:

Obrada prekida

Sada ne možete započeti projekat - prvi prekid iz tajmera neće pronaći svoj rukovalac, a kontroler će se zamrznuti (tačnije, ući će u HARD_FAULT rukovalac, što je u suštini ista stvar). Moraš to napisati.

Malo teorije

Mora imati vrlo specifično ime, void TIM6_DAC_IRQHandler (void). Ovaj naziv, takozvani vektor prekida, opisan je u startup datoteci (u našem projektu to je startup_stm32f10x_md_vl.s - možete sami vidjeti, red 126). U stvari, vektor je adresa rukovaoca prekida, a kada dođe do prekida, ARM jezgro se penje u početno područje (u koje se prevodi startup fajl - odnosno njegova lokacija je potpuno teško postavljena, na samom početku fleš memorije), traži vektor tamo i ide na pravo mesto u kodu.

Provjera događaja

Prva stvar koju treba da uradimo kada ulazimo u takav rukovalac je da proverimo koji događaj je pokrenuo prekid. Sada imamo samo jedan događaj, ali u stvarnom projektu može biti nekoliko događaja na jednom tajmeru. Stoga provjeravamo događaj i izvršavamo odgovarajući kod.

U našem programu ova provjera će izgledati ovako: ako (TIM_GetITStatus (TIM6, TIM_IT_Update)! = RESET) - sve je jasno, funkcija TIM_GetITStatus provjerava tajmer za navedeni događaj i vraća 0 ili 1.

Brisanje UIF zastavice

Drugi korak je brisanje zastavice prekida. Povratak na sliku: najnoviji UIF grafikon je zastavica prekida. Ako se ne obriše, sljedeći prekid neće moći biti pozvan, a kontroler će opet pasti u HARD_FAULT (ali šta je to!).

Akcija prekida

Jednostavno ćemo promijeniti stanje LED-a, kao u prvom programu. Razlika je u tome što sada naš program to otežava! U stvari, mnogo je ispravnije pisati na ovaj način.

Koristimo globalnu varijablu int state = 0;

11. Sav kod projekta sa tajmerom

Arhivirajte sa projektom tajmera.

Pa, usput, tajmer može sam prebaciti stopalo, bez prekida i ručne obrade. Ovo će biti naš treći projekat.

Ceo ciklus:

1. I/O portovi

2. Tajmer i prekidi

3. Izlazi tajmera

4. Eksterni prekidi i NVIC

5. Instalirajte FreeRTOS

Nedavno me je kolega navukao na ideju stvaranja pametne kuće, čak sam uspio naručiti desetine različitih senzora za sebe. Postavilo se pitanje o izboru Mikrokontroler(u daljem tekstu MK) ili ploče. Nakon dugog traženja, pronašao sam nekoliko opcija. Među njima su bili Arduino(uključujući njegove klonove, od kojih je jedan naručio samo radi maženja) i Launchpad, ali sve je to suvišno i glomazno (iako je programski mnogo jednostavnije, ali neću pokretati temu o holivarima, svako ima svoj ukus). Kao rezultat toga, odlučio sam da se ne odlučim za gotovu ploču, već da uzmem samo MK i uradim sve od nule. Kao rezultat toga, birao sam između Atmel attiny (2313), Atmel ATmega(Odlučio sam da odbijem jer nisam mogao da ga nađem za adekvatan novac), STM32(korteks na jezgru ARM). Već sam imao vremena da se igram sa tinejdžerom, pa sam uzeo sebe STM32VL-Discovery... Ovo se može nazvati uvodom u seriju članaka o STM32... Odmah ću napraviti rezervaciju, autor većine ovih članaka neću biti ja, jer I sam samo učim, ovdje ih objavljujem prvenstveno za sebe, tako da je zgodnije pretraživati ​​ako nešto zaboravim. I tako idemo!

Opće informacije

Mikrokontroleri porodice STM32 sadrži do sedam 16-bitnih I/O portova pod nazivom PORTA do PORTG. U konkretnom modelu mikrokontroler bez izuzetka, svi pinovi portova su dostupni, čiji ukupan broj zavisi od tipa kućišta i naveden je u DataSheet-u za odgovarajuću podporodicu.

Da biste omogućili port x, prvo ga morate povezati na APB2 sabirnicu postavljanjem odgovarajućeg IOPxEN bita u registru omogućavanja sata perifernih jedinica RCC_APB2ENR:

Upravljanje lukom STM32 izvedeno korištenjem skupova od sedam 32-bitnih registara:

  • GPIOx_CRL, GPIOx_CRH- postaviti modove rada svakog od bitova porta kao ulaza ili izlaza, odrediti konfiguraciju ulaznih i izlaznih stupnjeva.
  • GPIOx_IDR- registar ulaznih podataka za očitavanje fizičkog stanja porta x pinova.
  • GPIOx_ODR- izlazni registar upisuje podatke direktno u port.
  • GPIOx_BSRR- registrirajte se za atomsko resetiranje i postavljanje bitova porta.
  • GPIOx_BSR- registrirajte se za čiste bitove porta.
  • GPIOx_LCKR- registar zaključavanja konfiguracije pinova.

Načini rada GPIO pinova

Načini rada pojedinačnih pinova određeni su kombinacijom bitova MODEy i CNFy registri GPIOx_CRL i GPIOx_CRH(u daljem tekstu: naziv x-porta, broj bita y-porta).

GPIOx_CRL- registar konfiguracije pinova 0 ... 7 porta x:

Struktura registra GPIOx_CRH slična struktura GPIOx_CRL i dizajniran je za kontrolu načina rada pinova višeg porta (bitovi 8 ... 15).

MODEy bitovi naznačenih registara određuju smjer izlaza i ograničenje brzine prebacivanja u izlaznom modu:

  • MODEy = 00: Način unosa (stanje nakon resetiranja);
  • MODEy = 01: Režim izlaza, maksimalna brzina - 10MHz;
  • MODEy = 10: Režim izlaza, maksimalna brzina - 2MHz;
  • MODEy = 11: Režim izlaza, maksimalna brzina je 50MHz.

CNF bitovi postavljaju konfiguraciju izlaznih stupnjeva odgovarajućih pinova:

u načinu prijave:

  • CNFy = 00: Analogni ulaz;
  • CNFy = 01: Ulaz u trećem stanju (stanje nakon resetovanja);
  • CNFy = 10: Ulaz sa pull-up otpornikom (ako je PxODR = 1) ili pull-down (ako je PxODR = 0);
  • CNFy = 11: Rezervirano.

u izlaznom modu:

  • CNFy = 00: Push-pull izlaz opće namjene;
  • CNFy = 01: Izlaz otvorenog odvoda opšte namjene;
  • CNFy = 10: Push-pull izlaz sa alternativnom funkcijom;
  • CNFy = 11: Otvoreni odvod s alternativnom funkcijom.

Kako bi se povećala otpornost na buku, svi ulazni baferi sadrže Schmidt trigere. Dio zaključaka STM32 opremljen zaštitnim diodama povezanim na common rail i power rail su označeni u podatkovnom listu kao FT (tolerantno 5V) - kompatibilan sa 5 volti.

Zaštita bitova GPIO konfiguracije

Za zaštitu bitova u konfiguracijskim registrima od neovlaštenog upisivanja u STM32 Registar zaključavanja podešavanja je obezbeđen GPIOx_LCKR
GPIOx_LCKR- registrirajte se za blokiranje postavki izlaza porta:

Da biste zaštitili postavke individualnog pina porta, mora se postaviti odgovarajući LCKy bit. Zatim izvršite sekvencijalno upisivanje u kategoriju LCKK vrijednosti "1" - "0" - "1" i dvije operacije čitanja registra LCKR, koji će, u slučaju uspješnog blokiranja, dati za bit LCKK vrijednosti "0" i "1".

Zaštita bitova za podešavanje će ostati na snazi ​​do sljedećeg ponovnog pokretanja mikrokontrolera.

Datoteka periferne definicije mikrokontroleriSTM32 definiše zasebne grupe registara, ujedinjene zajedničkom funkcionalnom svrhom (uključujući GPIO), kao strukture jezika C, a sami registri kao elementi ove strukture.

STM32 - od nule do RTOS-a. 2: Tajmer i prekidi

Na primjer:

GPIOC-> BSRR- registar BSRR postavljen / brisanje porta GPIOC.
Koristimo definicije iz datoteke stm32f10x.h da ilustrujemo rad sa I/O registrima mikrokontrolera STM32F100RB instaliran u starter kit STM32VLDISCOVERY:

Pisanje i čitanje GPIO

Za portove za pisanje i čitanje, unos GPIOx_IDR i slobodan dan GPIOx_ODR registre podataka.

Upisi u izlazni registar ODR port konfigurisan za izlaz postavlja nivoe izlaza svih bitova porta u skladu sa snimljenom vrednošću. Ako je pin konfiguriran kao pull-up ulaz, stanje odgovarajućeg bita registra ODR aktivira povlačenje izlaza na sabirnicu napajanja (pull-up, ODR = 1) ili zajedničku sabirnicu mikrokontrolera (pull-down, ODR = 0).

Čitanje registra IDR vraća vrijednost stanja pinova mikrokontrolera konfiguriranih kao ulazi:

Brisanje i postavljanje bitova porta

Za atomsko resetiranje i postavljanje bitova GPIO u mikrokontrolerima STM32 registar namijenjen GPIOx_BSRR... Tradicionalno za arhitekturu ARM način upravljanja bitovima registra koji ne zahtijeva korištenje operacije tog tipa čitanje-izmjena-pisanje omogućava vam postavljanje i brisanje bitova porta jednostavnim upisivanjem jednog u postavljene bitove BS (BitSet) i reset BR (BitReset) registar BSRR... U ovom slučaju, upisivanje u registar nula bitova ne utiče na stanje odgovarajućih pinova.

GPIOx_BSRR- registrirajte se za resetiranje i postavljanje bitova porta:

Alternativne funkcije GPIO i njihovo preraspoređivanje (premapiranje)
Gotovo svi vanjski krugovi za posebne namjene STM32(uključujući vodove za povezivanje kvarcnih rezonatora, JTAG / SWD i tako dalje) mogu se omogućiti na odgovarajućim pinovima mikrokontrolera ili odvojiti od njih da bi se mogli koristiti kao pinovi opće namjene. Izbor alternativne izlazne funkcije vrši se pomoću registara s prefiksom „AFIO”_.
Osim toga, registri AFIO _ omogućavaju vam da odaberete nekoliko opcija za lokaciju posebnih funkcija na pinovima mikrokontrolera. Ovo se posebno odnosi na izlaze komunikacionih sučelja, tajmera (registra AFIO_MAPR), pinovi vanjskih prekida (registri AFIO_EXTICR) itd.

Za više detalja pogledajte dokumente "Referentni priručnik" odgovarajućoj podgrupi mikrokontrolera.

Projekti za članak:

  1. µVision 4.13a-> STM32GPIO_emcu_uV
  2. IAR ARM 6.0-> STM32GPIO_emcu_iar
  3. IAR ARM 6.21-> STM32GPIO_emcu_iar_V6.21

Za vožnju GPIOSTM32 Možete koristiti makroe napisane kao alternativu onima koji su daleko od optimalnih prema mnogim bibliotekama iz ST-a: gpio_emcu.h

Dodatni materijal:

  1. STM32F10xxx Referentni priručnik. Referentni vodič za programere
  2. STM32F100xx Referentni priručnik. Referentni vodič za programere
  3. STM32F105xx, STM32F107xx Datasheet
  4. STM32F100x4, STM32F100x6, STM32F100x8, STM32F100xB Tehnički list
  5. Vodič za kreiranje projekata za STM32DISCOVERY u IAR-u
  6. Vodič za kreiranje projekata za STM32DISCOVERY u MDK-ARM, uVision

Ostali dijelovi

  1. (ovaj dio) STM32 programiranje. Dio 1. GPIO, STM32 I/O portovi
  2. STM32 programiranje. Dio 2. STM32 sat sistem
  3. STM32 programiranje. Dio 3. Sistem prekida
  4. STM32 programiranje. Dio 4. Eksterni prekidi EXTI

Osnovni tajmeri u STM32

Tajmeri su takvi periferni uređaji STM32 kontrolera koji nam omogućavaju da vrlo precizno brojimo vremenske intervale. Ovo je možda jedna od najvažnijih i najčešće korištenih funkcija, ali postoje i druge. Za početak, postoje tajmeri različitog stepena hladnoće u STM32 kontrolerima. Najjednostavniji su Basictajmeri ... Oni su dobri jer ih je vrlo lako konfigurirati i upravljati s minimalnim brojem registara. Sve što mogu da urade je da odbrojavaju vremenske intervale i generišu prekide kada tajmer dostigne unapred određenu vrednost. Sljedeća grupa ( tajmeri opšte namene ) je mnogo hladniji od prvog, znaju generirati PWM, mogu brojati impulse koji dolaze do određenih nogu, možete spojiti enkoder itd. A najbolji tajmer je tajmer za naprednu kontrolu , mislim da ga neću još dugo koristiti, pošto za sada nemam potrebu da upravljam trofaznim elektromotorom. Da bi upoznavanje sa tajmerima trebalo biti sa nečim jednostavnijim, odlučio sam da uzmem Basic tajmere. Zadatak koji sam sebi postavio: Neka tajmer generiše prekide svake sekunde.

Prije svega, napominjem da su Basic tajmeri (TIM6 i TIM7) priključeni na APB1 sabirnicu, pa ako se frekvencija impulsa takta na njoj promijeni, tajmeri će početi brže ili sporije otkucavati. Ako ništa ne promijenite u postavkama takta i ostavite ih na zadanim, onda frekvenciju APB1 je 24 MHz, pod uslovom da je eksterni kristal povezan na frekvenciju od 8 MHz. Općenito, STM32 sistem taktiranja je vrlo zamršen i pokušaću da napišem poseban post o njemu normalno. Za sada, koristimo samo ona podešavanja takta koja su postavljena kodom koji automatski generiše CooCox. Vrijedi početi od najvažnijeg registra - TIMx_CNT(u daljem tekstu x je broj osnovnog tajmera 6 ili 7). Ovo je 16-bitni registar za brojanje koji se direktno bavi brojanjem vremena. Svaki put iz autobusa APB1 dolazi impuls takta, sadržaj ovog registra se povećava za jedan. Kada se registar prelije, sve počinje od nule. Uz našu zadanu frekvenciju sabirnice APB1, tajmer otkucava 24 miliona puta u jednoj sekundi! Ovo je jako nedovoljno, pa stoga tajmer ima predskaler, kojim možemo kontrolisati pomoću registra TIMx_PSC... Upisivanjem vrijednosti 24000-1 u njega, nametnut ćemo registar brojanja TIMx_CNT povećavati njegovu vrijednost svake milisekunde (Frekvencija APB1 podijelite brojem u registru preskalera i dobijete koliko se puta brojač povećava u sekundi). Jedinica se mora oduzeti jer ako je registar nula, to znači da je uključen i djelitelj sa jedan. Sada, kada registar brojanja dostigne 1000, možemo sa sigurnošću reći da je prošla tačno jedna sekunda! I zašto sada ispitivati ​​registar brojanja i čekati da se tamo pojavi 1000? Ovo nije naš metod, jer možemo koristiti prekide! Ali problem je što imamo samo jedan prekid, a on se javlja kada se brojač vrati na nulu. Da bi se brojač resetovao pre roka, a ne kada dostigne 0xFFFF, koristi se registar TIMx_ARR... U njega upisujemo broj na koji registar treba računati TIMx_CNT pre resetovanja na nulu. Ako želimo da se prekid javlja jednom u sekundi, onda tu treba da upišemo 1000. Što se vremena tiče, to je sve, ali sam tajmer neće početi da otkucava. Mora se uključiti postavljanjem bita CEN u registru TIMx_CR1... Ovaj bit vam omogućava da započnete brojanje, odnosno ako ga obrišete, brojanje će se zaustaviti (vaš K.O.).

Tajmeri na STM32. Podešavanje osnovnog tajmera

Ima i drugih bitova u registru, ali nama nisu posebno zanimljivi. Ali nas zanima još jedan dio, ali već u registru TIMx_DIER... To se zove UIE, postavljanjem omogućavamo tajmeru da generiše prekide kada se registar brojanja resetuje. To je sve, nije čak ni komplikovanije nego kod nekih AVR-a. Dakle, mali sažetak: Za korištenje osnovnog tajmera potrebno vam je:

  1. Postavite predskaler tako da tajmer ne otkucava brzo ( TIMx_PSC)
  2. Postavite granicu do koje tajmer mora završiti prije resetiranja ( TIMx_ARR)
  3. Uključite odbrojavanje po malo CEN u registru TIMx_CR1
  4. Omogući prekid prekoračenja bita UIE u registru TIMx_DIER

Evo jednostavnog niza. A sada je došlo vrijeme da ga sami nabavite, znate šta, i pokušate da zatreperite ove nesretne LED diode po milioniti put, ali uz pomoć tajmera 🙂

#include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" int main () (GPIO_InitTypeDef PORT; // Uključite port C i tajmer 6 RCC_APB2PeriphClockClockCmd) izlaz PORT.GPIO_Pin = (GPIO_Pin_9 | GPIO_Pin_8); PORT.GPIO_Mode = GPIO_Mode_Out_PP; PORT.GPIO_Speed ​​= GPIO_Speed_2MHz; GPIO_Init> GPIOC, & P000 = delilac da je tajmer 0 10 6 puta po sekundi 0 //RR tick-0 Tako da se prekid dogodi jednom u sekundi TIM6-> DIER | = TIM_DIER_UIE; // omogući prekid tajmera TIM6-> CR1 | = TIM_CR1_CEN; // Počni odbrojavanje! NVIC_EnableIRQ (TIM6_DAC_IRQn); // Omogući TIM6_DAC_IRQn; // Omogući TIM6_DAC_IRQn (prekid dok (IRQn) // Program ne radi ništa u praznoj petlji)) // TIM6_DAC rukovalac prekida void TIM6_DAC_IRQHandler (void) (TIM6-> SR & = ~ TIM_SR_UIF; // Obriši zastavicu UIF GPIOC-> ODR ^ = (GPIO_Pin_9 | GPIO_Pin_8); // Invertirajte stanje LED dioda)

Vrijedi dodati malu napomenu rukovaocu prekida. Činjenica je da ga koriste dvije periferne jedinice odjednom: tajmer 6 i DAC. To znači da ako napišete program koji dozvoljava prekide sa oba ova periferna uređaja, onda je u tijelu rukovatelja potrebno provjeriti koji je od njih uzrokovao prekid. U našem slučaju to nisam uradio, jer ne može doći do DAC prekida. Nije konfigurisan, a prekidi su podrazumevano onemogućeni. Sljedeći put ćemo pogledati tajmere opće namjene i njihovu praktičnu primjenu.

PWM generacija u STM32

U prethodnom članku o osnovnim tajmerima još jednom smo treperili LED diodama, ali ovog puta ćemo ići mnogo dalje i pokušati probati kako natjerati STM32 kontroler da generiše PWM. Da bismo to učinili, morat ćemo koristiti jedan od tajmera opće namjene, jer oni imaju sve što je potrebno za to. Ostatak funkcionalnosti ovih tajmera je svakako impresivan, ali u mojoj praksi to još nije dobro došao. Iako je moguće da će mi u budućnosti biti korisne takve korisne značajke kao što je funkcija brojanja vanjskih impulsa i mogućnost upravljanja rotacijama enkodera u hardveru. Ali za sada, pozabavimo se PWM-om. Postoji takav sklop kontrolera, tri otpornika i RGB LED koji ćemo kontrolirati. Kontrola je da glatko osvetlite i potamnite svaku boju. Naravno, možete uzeti tri različite LED diode ako nema RGB.

Povezali smo LED na ove pinove s razlogom. Tajmeri opće namjene mogu generirati PWM samo na određenim pinovima. Pošto ćemo koristiti tajmer 2, na raspolaganju su nam 4 noge (PA0-PA3). Da bi ih tajmer koristio, morate ga omogućiti na dva mjesta: Konfigurirajte tri kraka (PA1-PA3) kao izlaz s alternativnom funkcijom i dozvolite povlačenje ovih krakova u postavkama tajmera za generiranje PWM-a. Za ovo nam je potreban registar CCER

Ako jedan od bitova označenih plavom bojom postavite na jedan, tajmeru će biti dozvoljeno da koristi odgovarajuću nogu za PWM. Iz dijagrama možete vidjeti da moramo postaviti bitove CC2E, CC3E i CC4E... Sada treba da konfigurišemo PWM način rada: Direktan ili Inverzni (ne pretendujem da sam ispravan u terminologiji). Razlika je prilično očigledna - kod direktnog PWM-a, što je veći broj u registru za poređenje, veći je radni ciklus PWM-a. U slučaju inverznog PWM-a, tačno je suprotno. Upišite nulu u registar poređenja - faktor popunjavanja je 100%.

Rad sa jednostavnim tajmerima za otkrivanje STM32 F4

Za odabir načina rada koriste se dva registra CCMR1 i CCMR2:

Za podešavanje svakog kanala dodijeljeno je čak 8 bitova! Ali srećom nas zanimaju samo tri OCxM bita koje sam označio plavom bojom. Oni koji su označeni sivom bojom su isti bitovi, ali sa drugačijim imenom, koriste se ako je kanal tajmera u režimu snimanja. Neću razmatrati sve kombinacije bitova, jer većina njih nema nikakve veze sa PWM. Potrebne su nam samo dvije kombinacije bita:

Direct PWM

Inverzni PWM

Imam RGB LED sa zajedničkom katodom i stoga koristim inverzni PWM. Dakle, moramo postaviti sva tri OCxM bita za tri kanala na kojima vise LED diode. I to je sve! PWM podešavanje je završeno, sada samo trebate pokrenuti tajmer postavljanjem CEN bita u CR1 registru. Za kontrolu radnog ciklusa, jednostavno upišite broj od 0x0000 do 0xFFFF u CCR registre x, gdje x broj kanala. Zapravo, sljedeći kod implementira ono što je zamišljeno na početku ovog članka: Povećava svjetlinu LED-a, a zatim ga smanjuje na nulu i prelazi na sljedeći.

Proces se ponavlja u nedogled, prelepo izgleda 🙂

#include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" void kašnjenje (void) (volatile uint32_t i; for (i = 1; i! = 0xF000; i main ++);) int () (// Uključi port A RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA, ENABLE); // Uključi tajmer 2 RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE); GPIO_InitType); GPIO_InitType; GPIO_InitType izlaz nećemo koristiti za nas; PORT.GPIO_Speed ​​= GPIO_Speed_2MHz; GPIO_Init (GPIOA, & PORT); // Dozvoli tajmeru da koristi noge PA1, PA2, PA3 za PWM = TIM2-> CC | TIM_CCER_CC4E); // Za sva tri kanala zadaje se inverzni PWM TIM2-> CCMR1 | = (TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2) ;. TIM2-> CCMR2 | = (TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2);! // Početak tajmer TIM2-> CR1 | = TIM_CR1_CEN ; // Nakon ovog wow upisujemo podatke u TIM2-> CCRx - i svjetlina LED dioda se mijenja uint32_t pwm_arr = (0,0,6553,13107,19660,26214,32768, 39321,45875,52428,58935,); uint8_t i; dok (1) (za (i = 1; i<=11;i++) { TIM2->CCR3 = pwm_arr [i]; kašnjenje (); ) za (i = 11; i> = 1; i—) (TIM2-> CCR3 = pwm_arr [i]; kašnjenje ();) za (i = 1; i<=10;i++) { TIM2->CCR2 = pwm_arr [i]; kašnjenje (); ) za (i = 11; i> = 1; i—) (TIM2-> CCR2 = pwm_arr [i]; kašnjenje ();) za (i = 1; i<=10;i++) { TIM2->CCR4 = pwm_arr [i]; kašnjenje (); ) za (i = 11; i> = 1; i—) (TIM2-> CCR4 = pwm_arr [i]; kašnjenje ();)))

Nadam se da će vam ovaj kod pomoći da pokrenete PWM na STM32 i da će mi pomoći da ne zaboravim šta sam pušio skoro pola dana. Jednostavna pitanja možete napisati ispod.

Džepni osciloskop "Lori" na mikrokontroleru STM32F103

Maxim Kerimov
decembar 2016

Formulacija problema

Napravite najjednostavniji džepni osciloskop uz minimalno ulaganje vremena i novca.

Lista komponenti

  • Kineski klon Maple Mini ploče sa STM32F103C8T6 mikrokontrolerom.
  • Displej 1.8 TFT 128 × 160 SPI sa ST7735 drajverom.
  • Pet otpornika i dva kondenzatora (slika 3).
  • Linearni regulator malog pada AMS1117-3.3 (opciono).
  • Stezaljka sonda "pinceta" - 2 kom.
  • Dugme je minijaturno, normalno otvoreno bez fiksiranja, uz klik.

Rice. 1. Probni rad osciloskopa. Sinusoidu stvara zvučni blaster, stoga je stepenasti.

Specifikacije

7 opsega sa stopom podjele (ćelije): 7 µS, 28 µS, 113 µS, 559 µS, 2 mS, 10 mS, 20 mS.
Osjetljivost: 0,25 i 1,0 V / div.
Maksimalna ulazna amplituda: 6 V.
Ulazna impedansa: 20 kΩ.
Napajanje: 4 AA baterije.
Struja potrošnje: 80 mA.

Koju frekvenciju signala možete vidjeti?

U teoriji, možete vidjeti 477 kHz. Teoretski je moguće razlikovati meandar od pile na frekvencijama od 350 kHz i niže. U praksi je manje-više udobno posmatrati signale do 200 kHz. Veličina ćelije: 20 x 20 px.

"Brzina pomeranja" našeg osciloskopa zavisi od brzine ADC-a. U STM32F103, kapacitet ADC-a je fiksiran na 12. Ovo je jedan i po puta više nego što nam je potrebno. U STM32F407, na primjer, dubina bita se može smanjiti, što će skratiti vrijeme mjerenja. Ali to je druga priča sa drugačijim budžetom.

Rice. 2. Povezivanje ekrana.

Rice. 3. Napajanje i ulazni krug.

Razdjelnik napona R1-R2 se koristi za kontrolu nivoa napunjenosti baterije. U gornjem desnom uglu ekrana nalazi se ikona baterije, kao na mobilnom telefonu (nije prikazana na fotografiji).

Eksterni regulator napona nije uvijek potreban. Ploča mikrokontrolera ima sopstveni regulator od 3.3V 100mA. Ako napajate ekran sa njega, on će se zagrejati. Na pločama drugog tipa (sa velikim JTAG konektorom) je instaliran AMS1117, nije im potreban eksterni. Neki displeji takođe imaju AMS1117 (i kratkospojnik). Odlučite sami.

U seriju sa baterijama ima smisla staviti prekidač za napajanje PD9-1 ili slično.

Ako želite povećati veličinu svoje impedanse, možete dodati neinvertirajući sljedbenik na op-amp na ulaz, što će vam omogućiti da postignete vrijednost od 1 MΩ ili više. Op-amp bi trebao biti napajan direktno iz baterija napona od 4,8 - 5,4 V.

Princip rada

Pola programskog teksta čine sve vrste inicijalizacija. Princip rada digitalnog osciloskopa je jednostavan i očigledan.

ADC vrši seriju kontinuiranih uzastopnih mjerenja nivoa signala. Rezultirajuće vrijednosti se dodaju u memoriju pomoću DMA. Svaki put mjerimo i određujemo trajanje serije mjerenja. Ovako saznajemo cijenu podjele vremenske ose.

Analizirajući snimljene vrijednosti nivoa signala, tražimo prvi ekstrem, nakon čega iscrtavamo signal na ekranu. Tako da pokušavamo da napravimo neku vrstu sinhronizacije. Dobro radi na glatkim signalima i gotovo je beskoristan na širokopojasnim signalima.

Omogućavamo korisniku da uživa u slici jednu sekundu, dok mi sami prozivamo dugme. Kratkim pritiskom na dugme menjate opsege u krug. Dug pritisak menja osetljivost.

STM32 za početnike. Lekcija 3. STM32 tajmeri.

Onda se sve ponavlja.

Koristim CooCox CoIDE okruženje za kompilaciju. Nisam uploadovao Cox projekt ovdje jer sadrži apsolutne putanje do datoteka. Lakše je stvoriti novi nego ispraviti sve puteve. Nakon kreiranja projekta, ne zaboravite povezati biblioteke: RCC, GPIO, DMA, SPI, TIM, ADC.

Sašio sam ga koristeći ST-Link V2 programator-debugger. Moguće je i bez njega, preko USB-serijskog adaptera.

Korišteni materijali:
Projekt škotskog majstora Pingumacpenguina
Adafruit display
STM32 Čuvanje ADC podataka pomoću DMA

Tekst programa

  • main.c
  • lcd7735.c - Displej i SPI. Inicijalizacija i funkcije.
  • delay.c - Brojač: inicijalizacija, funkcije pauze.
  • ADC.c - ADC i DMA.
  • font7x15.h - Font.

STM32 od nule. Tajmeri.

Postoji nekoliko tajmera u STM32 mikrokontrolerima koji mogu raditi u modusu modulacije širine impulsa. Svi mjerači vremena osim osnovnih mjerača vremena (TIM6 i TIM7) imaju ovu funkciju.

To je sve, ovo je dovoljno da [U STM32 mikrokontrolerima postoji nekoliko tajmera sposobnih za rad u modusu modulacije širine impulsa. Svi mjerači vremena osim osnovnih mjerača vremena (TIM6 i TIM7) imaju ovu funkciju.

Navest ću primjer korištenja TIM3 tajmera u ovom načinu rada.

To je sve, ovo je dovoljno za] (http://catethysis.ru/stm32-%e2%86%92-%d0%bf%d0%be%d1%80%d1%82%d1%8b-gpio / “ STM32 → GPIO portovi”) pojavljuje se PWM signal. Kako se to radi?

Tajmer prima impulse takta sa APB magistrale, čija je frekvencija polovina frekvencije jezgre (u našem slučaju 24 MHz) (link na RCC), i oni prolaze kroz predskaler koji smo postavili na 10 – tj. ispada 1.2MHz. Tajmer je podešen da odbrojava 1000 taktova, nakon čega uzima novu vrijednost iz ARR registra, koju ne mijenjamo – tj. istih 1000, ovo je period PWM signala. Na početku ciklusa, tajmer daje "1" na izlaz, a nakon 200 ciklusa takta vraća se na "0" - ovo je PWM radni ciklus.

Pokrivali smo rad sa bitskim operacijama i binarnim brojevima, postavljajući tako temelj za novu temu. U ovoj lekciji ćemo razmotriti još jedno pitanje: šta su registri i kako sa njima raditi?

Memorija i registri

Jedna od najvažnijih vještina potrebnih za rad s mikrokontrolerima je sposobnost interakcije s registrima. Hajde da to sami shvatimo, Šta je?

Općenito, registar je posebna vrsta memorije unutar mikrokontrolera koja se koristi za kontrolu procesora i perifernih uređaja. Svaki registar u ARM arhitekturi je memorijska ćelija i ima dužinu od 32 bita, pri čemu svaki bit može biti predstavljen kao sićušni prekidač kojim se kontroliše jedan ili drugi parametar mikrokontrolera.

Svaki od registara ima svoj serijski broj - adresu. Adresa registra je označena 32-bitnim brojem predstavljenim u heksadecimalnoj notaciji. Upisivanjem na adresu registra određene kombinacije jedinica i nula, koje su obično predstavljene u heksadecimalnom obliku, konfiguriše se i kontroliše jedan ili drugi čvor u MC. Podsjetimo da u programu za rad sa bitnim operacijama možemo predstaviti proizvoljan skup jedinica i nula kao heksadecimalni broj. Općenito, vrijedi napomenuti da postoje dvije vrste registara: registri opšte namjene i posebni registri. Prvi se nalaze unutar MK jezgre, a drugi su dio RAM memorije.

Vrijedi i to napomenuti Referentni priručnik koju smo preuzeli u prvoj lekciji je jedna velika referenca za registre sadržane u ciljnom mikrokontroleru, a CMSIS biblioteka nam omogućava da radimo sa simboličkim imenima registara umesto numeričkim adresama. Na primjer, u registar 0x40011018 možemo upućivati ​​jednostavno korištenjem simboličkog imena GPIOC_BSSR... Razmotrit ćemo konkretne primjere konfiguracije u toku raščlanjivanja našeg programa iz.

Dakle, obično se struktura registra opisuje u obliku male tabele sa naznakom:

  1. Imena registra i opis njegove namjene
  2. Registrirajte adrese ili pomaknite od osnovne adrese
  3. Zadane vrijednosti nakon resetiranja
  4. Vrsta pristupa ćelijama registra (čitanje, pisanje, čitanje/pisanje)
  5. Vrijednosti i opisi parametara snimljenih bitova
Pogledajmo primjer rada s registrima u konkretnoj situaciji kako bismo dobili opću ideju o principima postavljanja mikrokontrolera.

Raščlanjivanje koda iz prve lekcije

Dakle, prisjetimo se problema koji smo riješili koristeći gotov primjer koda: morali smo napisati program koji bi omogućio naizmjenično uključivanje dvije LED diode na ploči Discovery (možda ne dvije, ako imate drugu verziju Discoveryja tabla) sa vremenskim intervalom.

Pogledajmo još jednom kod programa koji smo koristili da naš MK potresa dvije noge na kojima se nalaze naše LED diode:

Main.c kod

/ * Datoteka zaglavlja za našu porodicu mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; / * Konfigurišite način rada portova PC8 i PC9 u izlazu * / GPIOC -> MODER = 0x50000; / * Postavite tip izlaza na Push-Pull mod * / GPIOC-> OTYPER = 0; / * Postavite brzinu port na Low * / GPIOC-> OSPEEDR = 0; dok (1) (/ * Uključite PC8 LED, isključite PC9 * / GPIOC-> ODR = 0x100; za (int i = 0; i<500000; i++){} // Искусственная задержка /* Зажигаем светодиод PC9, гасим PC8 */ GPIOC->ODR = 0x200; za (int i = 0; i<500000; i++){} // Искусственная задержка } }


Prije svega, kada radimo sa STM32, čak i za tako jednostavan zadatak kao što je uključivanje i isključivanje LED-a, prvo moramo odgovoriti na nekoliko pitanja:
  1. Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?
  2. Kako uključiti i isključiti LED?
Na njih ćemo odgovoriti redom.

Gdje su naše LED diode povezane? Koji pin mikrokontrolera?

Da bismo vidjeli gdje se sve nalazi na ploči Discovery, a posebno LED diode koje su nam potrebne, trebamo otvoriti datoteku sheme, bilo onu koju smo preuzeli sa ST web stranice ili direktno sa Keila:


Nakon otvaranja sheme, vidjet ćemo dijagram svega što se nalazi na ploči - ST-Link kolo, cjevovod svih perifernih uređaja i još mnogo toga. Trenutno nas zanimaju dvije LED diode, tražimo njihovu oznaku:


Kao što vidimo, naše LED diode su povezane na GPIOC port na 8 i 9 pinova.

Kako da omogućim taktiranje na željenom GPIO portu?

Općenito, svaki rad s periferijama u STM32 mikrokontrolerima svodi se na standardni slijed radnji:
  1. Omogućavanje takta odgovarajućeg perifernog modula. To se radi preko RCC registra slanjem signala takta direktno sa magistrale na kojoj se nalazi ovaj modul. Podrazumevano, taktiranje svih perifernih uređaja je onemogućeno kako bi se smanjila potrošnja energije.
  2. Postavljanje preko kontrolnih registara, promjenom parametara specifičnih za određeni periferni uređaj
  3. Direktno pokretanje i korištenje rezultata modula
Odnosno, da bismo započeli, moramo započeti taktiranje na GPIOC portu. To se radi direktno pristupom RCC registru, koji je odgovoran za klokovanje svega i svakoga i uključivanje satnog signala sa magistrale na koju je povezan naš GPIO port.

Pažnja! Pitanje u vezi sa sistemom takta, njegovom konfiguracijom i upotrebom, detaljno ćemo razmotriti u posebnom članku.

Pronađi na koju magistralu je povezan naš GPIOC port može se naći u Datasheet-u na našem MK-u u odjeljku Mapiranje memorije u Tabeli 16. Granične adrese perifernog registra STM32F051xx.


Kao što ste već primijetili, autobus koji nam je potreban zove se AHB2. Da biste se detaljnije upoznali sa registrom u kojem je omogućeno taktiranje na GPIO portu koji nam je potreban na AHB sabirnici, potrebno je otići na odgovarajući odjeljak u Referentnom priručniku. Po imenu registara možemo odrediti onaj koji nam je potreban:


Idemo do ove tačke i vidimo naš 32-bitni registar, njegovu ofset adresu, podrazumevanu vrednost, način pristupa registru i nabrajanje za šta je odgovoran svaki bit u registru.


Gledamo u tabelu i vidimo nešto što liči na opciju za omogućavanje takta na GPIO portovima. Idite na opis i pronađite opciju koja nam je potrebna:


U skladu s tim, ako postavimo 19 bita na vrijednost "1", to će omogućiti taktiranje na I / O C portu - odnosno na našem GPIOC-u. Osim toga, trebamo omogućiti odvojeno jedan bit iz grupe, bez utjecaja na ostatak, jer ne treba se mešati i nepotrebno menjati druga podešavanja.

Na osnovu materijala prethodne lekcije, znamo da za postavljanje određenog bita potrebno je logičkom operacijom "ILI" dodati trenutnu vrijednost registra sa maskom koja sadrži one bitove koje treba okrenuti on. Na primjer, dodajte zadanu vrijednost registra RCC-> AHBENR, tj. 0x14 i broj 0x80000 na taj način omogućavaju GPIOC taktiranje postavljanjem 19 bita:

Kako to možemo učiniti iz programa? Prilično je jednostavno. U ovom slučaju imamo dvije opcije:

  1. Upisivanje u registar direktno numeričke vrijednosti registra direktno preko njegove adrese.
  2. Konfiguracija pomoću CMSIS biblioteke
Ne postoji poseban problem u direktnom pisanju vrijednosti u registar, ali postoji nekoliko značajnih nedostataka. Prvo, takav kod postaje nečitljiv, a drugo, ne možemo odmah odrediti na koji se registar odnosi određena adresa u memoriji.

Odnosno, mogli bismo se pozvati na adrese registra direktno na adresi i napisati ovako:

IO uint32_t * register_address = (uint32_t *) 0x40021014U; // Adresa našeg registra u memoriji * (__ IO uint32_t *) register_address | = 0x80000; // Uključujemo 19 bita sa našim parametrom
Druga opcija mi se čini najatraktivnijom, jer CMSIS biblioteka je organizovana na način da se registru može pristupiti koristeći samo njegovo ime. Predprocesor će automatski zamijeniti sve digitalne vrijednosti adrese registra tokom obrade programskog teksta prije kompilacije. Pogledajmo pobliže ovo pitanje.

Predlažem da otvorimo naš projekat, koji smo napravili u prvoj lekciji, ili da preuzmemo prethodno pripremljeni odavde i izbrišemo cijeli sadržaj programa, ostavljajući samo uključenu datoteku zaglavlja, glavnu () funkciju i upute za omogućavanje takta ( trebat će nam za detaljnu analizu koda).

Naš kod će izgledati ovako:

/ * Datoteka zaglavlja za našu porodicu mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; )
Zadubimo se duboko u CMSIS biblioteku radi pregleda.

Da biste brzo došli do mjesta gdje je deklarirana ova ili ona konstanta ili varijabla, u Keil je implementirana zgodna funkcija. Desni klik na konstantu koja nam je potrebna, na primjer, na RCC:


I prelazimo u dubine CMSIS biblioteke, u kojoj ćemo vidjeti da svi registri dostupni za programsku kontrolu imaju oblik TypeDef struktura, uključujući naš RCC:


Nakon neuspjeha na ovaj način u RCC_TypeDef, vidjet ćemo strukturu u kojoj su opisana sva polja našeg registra:


Shodno tome, možemo se bezbedno pozvati na registar koji nam je potreban sa zapisom obrasca PERIPH_MODULE-> REGISTER i dodijeliti mu određeno značenje.

Pored mnemoničke oznake registara, postoje i oznake specifičnih bitova. Ako ne uspijemo deklarirati parametar RCC_AHBENR_GPIOCEN iz našeg programa, također ćemo vidjeti deklaraciju svih parametara:


Tako, koristeći CMSIS biblioteku, dobijamo lakonski čitljiv zapis parametra koji nam je potreban u registru, kroz čiju instalaciju započinjemo taktiranje na portu koji nam je potreban:

/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN;
Kao zadatak: koristite Keil-ove mogućnosti da odredite kako je adresa registra RCC-> AHBENR dobijena kao 0x40021014.

Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?

Dakle, znamo da su LED diode koje su nam potrebne povezane na GPIOC port na pinove PC8 i PC9. Moramo ih postaviti tako da LED svijetli. Želio bih odmah napraviti rezervaciju da ćemo GPIO portove detaljnije razmotriti u drugom članku, a ovdje ćemo se koncentrirati na rad s registrima.

Prije svega, trebamo prebaciti način rada pinova PC8 i PC9 u Output mod. Ostatak parametara porta može se ostaviti na zadanim vrijednostima. Idite na Referentni priručnik u odjeljku 9. U/O opće namjene (GPIO) i otvorite stavku odgovornu za način rada pinova GPIO porta i vidite da je MODER registar odgovoran za ovaj parametar:


Sudeći po opisu, da bismo pinove PC8 i PC9 postavili u izlazni mod, moramo upisati 01 u odgovarajuća polja GPIOC registra.

To se može učiniti direktnom instalacijom koristeći numeričke vrijednosti:


Ili korištenjem definicija iz biblioteke:

/ * Uključite taktiranje na GPIO portu * / GPIOC-> MODER | = GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
Nakon ove instrukcije, naši PC8 i PC9 pinovi će ići u izlazni mod.

Kako uključiti LED?

Ako obratimo pažnju na listu dostupnih registara za kontrolu GPIO porta, možemo vidjeti ODR registar:


Svaki od odgovarajućih bitova je odgovoran za jedan od pinova porta. Njegovu strukturu možete vidjeti u nastavku:


Da bi se omogućila naizmjenična promjena stanja LED dioda, potrebno je uključiti / isključiti 8 i 9 bita sa određenim vremenskim intervalom. Odnosno, naizmjenično dodijelite vrijednosti registra 0x100 i 0x200.

To možemo učiniti direktnim dodjeljivanjem vrijednosti registru:

GPIOC-> ODR = 0x100; // Uključite PC8, isključite PC9 GPIOC-> ODR = 0x200; // Uključite PC9, isključite PC8
Možemo koristiti definicije iz biblioteke:

GPIOC-> ODR = GPIO_ODR_8; // Uključite PC8, isključite PC9 GPIOC-> ODR = GPIO_ODR_9; // Uključite PC9, isključite PC8
Ali pošto mikrokontroler radi vrlo brzo, nećemo primijetiti promjenu stanja LED dioda i vizualno će se činiti da su obje stalno uključene. Da bi zaista treptali, uvest ćemo vještačko kašnjenje u vidu ciklusa koji će neko vrijeme zaokupiti MC beskorisnim proračunima. Dobijate sljedeći kod:

/ * Uključujemo PC8 LED, gasimo PC9 * / GPIOC-> ODR = GPIO_ODR_8; za (int i = 0; i<500000; i++){} // Искусственная задержка /* Зажигаем светодиод PC9, гасим PC8 */ GPIOC->ODR = GPIO_ODR_9; za (int i = 0; i<500000; i++){} // Искусственная задержка
Ovim je završeno početno upoznavanje sa registrima i metodama rada sa njima.

Provjeravamo rezultate našeg koda

Mali lijep dodatak na kraju članka: Keil ima odličan alat za otklanjanje grešaka s kojim možemo korak po korak kroz naš program i vidjeti trenutno stanje bilo koje periferne jedinice. Da biste to učinili, nakon preuzimanja firmvera nakon kompilacije, možemo kliknuti na dugme Start Debug Session:

GPIO I/O portovi u STM32 imaju 16 linija, od kojih se svaka može konfigurisati po potrebi. Podržane su funkcije digitalnog ulaza, digitalnog izlaza, ulaza eksternog prekida i I/O funkcija ostalih modula mikrokontrolera. STM32 programiranje za rad sa GPIO bazira se na korišćenju konfiguracionih registara, čitanja, pisanja, zaštite konfiguracije i registra pristupa bitu.

Registar konfiguracije porta.

Nizak registar konfiguracije porta (GPIOx_CRL) (x = A..G)

Visoki registar konfiguracije porta (GPIOx_CRH) (x = A..G)

Za programiranje načina rada STM32 I/O portova koriste se dva 32-bitna registra za svaki GPIO. Oni vam omogućavaju da prilagodite način rada svake pojedinačne linije. Registar GPIOx_CRL je odgovoran za redove sa brojevima od 0 do 7, GPIOx_CRH - za linije 8-15. Za svaki od njih registar ima dva dvocifrena polja CNFy i MODEy. Prvi određuje vrstu operacije linije, drugi - smjer razmjene duž linije. svi bitovi se čitaju / pišu.

Registrirajte GPIOx_CRL

Bitregistar

Polje

I/O linija

Registracijski bit

Polje

Ulazni red /povlačenje

Registrirajte GPIOX_CRH

Registracijski bit

Polje

I/O linija

Registracijski bit

Polje

I/O linija

Polje MODEy može imati sljedeće vrijednosti:

  • 00 - linija radi za unos. Ovo stanje se uspostavlja nakon resetovanja.
  • 01 - linija radi na izlazu, sa maksimalnom frekvencijom prebacivanja od 10 MHz
  • 10 - linija radi za izlaz, sa maksimalnom frekvencijom prebacivanja od 20 MHz
  • 11 - linija radi na izlazu, sa maksimalnom frekvencijom prebacivanja od 50 MHz

Polje CNFy ovisi o smjeru prijenosa. Kada se radi na ulazu (MODEy = 0), dostupna su sljedeća stanja:

  • 00 - analogni ulaz.
  • 01 - ulaz je u trećem stanju. (Instaliran nakon resetiranja).
  • 10 - ulaz sa pull-up otpornikom
  • 11 - Rezervisano za buduću upotrebu.

Kada se radi na izlazu (MODEy> 0), polje CNFy može imati sljedeća stanja:

  • 00 - digitalni izlaz
  • 01 - digitalni izlaz sa otvorenim odvodom
  • 10 - digitalni izlaz spojen na specijalizirane blokove
  • 11 - digitalni izlaz spojen na specijalizirane blokove sa otvorenim odvodom

Postavke mijenjaju zaštitni registar

Registar zaključavanja konfiguracije porta (GPIOx_LCKR) (x = A..G)

Polje

Polje

Postavite zaključani bit u GPIOx_LCKR Da bi se onemogućila promjena postavki porta u STM32 mikrokontrolerima, koristi se registar GPIOx_LCKR. Njegovih najmanjih 15 bitova je odgovorno za odgovarajuće linije I/O porta. Bit 16, postavljen na 1, omogućava podešavanje zaključavanja promjene. svi bitovi se čitaju / pišu. Da otežamo život korisnicima ;-) , koristi se poseban algoritam za postavljanje zaštite. Ako se primjenjuje, sljedeća promjena konfiguracije dostupna je tek nakon resetiranja. Algoritam za postavljanje zaštite je sljedeći:

  1. Postavite bit 16 GPIOx_LCKR.
  2. Obriši bit 16 GPIOx_LCKR.
  3. Postavite bit 16 GPIOx_LCKR.
  4. Pročitajte GPIOx_LCKR
  5. Ponovo pročitajte GPIOx_LCKR

Registri za podešavanje stanja linije

Za razliku od uobičajenih 8-bitnih modela, STM32 ima nekoliko registara odgovornih za stanje linija I/O porta. Uobičajeno se dijele u dvije grupe - portne registre i registre za postavljanje pojedinačnih bitova.

I/O port izlazni registar

Registar izlaznih podataka porta (GPIOx_ODR) (x = A..G)

Polje

Polje

Ovaj registar je širok 32 bita, ali se koristi samo nižih 16 bita. Bitovi 16 do 31 se ne koriste. Kada upisujete bilo koju vrijednost u GPIOx_ODR, ova vrijednost se postavlja na izlazne linije odgovarajućeg porta. Bitovi registra su samo za čitanje/pisanje.

Ulazni registar

Registar ulaznih podataka porta (GPIOx_IDR) (x = A..G)

Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Polje Rezerva
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1
Polje IDR15 IDR14 IDR13 IDR12 IDR11 IDR10 IDR9 IDR8 IDR7 IDR6 IDR5 IDR4 IDR3 IDR2 IDR1 IDR0

Slično izlaznom registru, ulazni registar ima samo 16 najmanjih bitova od 32. Čitanje GPIOx_IDR vraća statusnu vrijednost svih portova. Bitovi registra su samo za čitanje.

Registar bitnih operacija

Postavljanje bitova porta / resetiranje registara (GPIOx_BSRR) (x = A..G)

Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Polje BR15 BR14 BR13 BR12 BR11 BR10 BR9 BR8 BR7 BR6 BR5 BR4 BR3 BR2 BR1 BR0
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1
Polje BS15 BS14 BS13 BS12 BS11 BS10 BS9 BS8 BS7 BS6 BS5 BS4 BS3 BS2 BS1 BS0

Ovaj registar vam omogućava upućivanje na određenu I/O liniju STM32 mikrokontrolera. Upisivanje jednog u jedan od najznačajnijih bitova resetuje linijski izlaz, a upisivanje jednog u najmanje značajne bitove postavlja nivo signala na visokom nivou odgovarajuće linije. Registar je upisan u formatu riječi, s nultim bitovima koji nemaju efekta. Registrski bitovi su samo za pisanje.

Resetirajte registar

Reset bita porta (GPIOx_BRR) (x = A..G)

Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Polje Rezerva
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1
Polje BR15 BR14 BR13 BR12 BR11 BR10 BR9 BR8 BR7 BR6 BR5 BR4 BR3 BR2 BR1 BR0

Ovaj registar resetira visoki nivo linije postavljene u registru GPIOx_ODR. Koriste se samo nižih 16 bita koji su dostupni samo za pisanje.

Top srodni članci