Kako postaviti pametne telefone i računala. Informativni portal
  • Dom
  • Windows Phone
  • Mikrokontroleri, procesori, projekti, programiranje. Zaštita GPIO konfiguracijskih bitova

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

Glavni registri I/O porta mikrokontrolera STM32

Port se odnosi na određeni imenovani skup nogu mikrokontrolera. U STM mikrokontrolerima se nazivaju GPIOA, GPIOB, GPIOC, itd. I/O portovi u mikrokontrolerima STM32 imaju, u 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;
  • vanjski ulaz prekida;
  • I/O funkcija ostalih modula mikrokontrolera.

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

Pogledajmo glavne registre potrebne za rad s 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 odgovorni su za postavljanje ili konfiguriranje porta. U mikrokontrolerima obitelji 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)

32-bitna je registar je odgovoran za način rada linije. Za konfiguriranje unaprijed definirane linije potrebna su 2 bita. 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 konfiguriranje tipa operacije na liniji. Koristi 16 bitova u radu, preostalih 16 je rezervirano. Uzima sljedeće vrijednosti:

  • 0 - način rada push-pull;
  • 1 - otvoreni odvod

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


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

  • 00 - bez aparatića
  • 01 - zatezanje do plusa hrane
  • 10 - povucite 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 liniju (kraku). Budući da imamo 16 redaka, a registar ima 32 bita, koristi se samo prvih (najmanje značajnih) 16 bita.

Ulazni registar (status priključka 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 bitnu postavku 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 priključka mikrokontrolera pomoću biblioteke

Također, port se može konfigurirati pomoću posebne biblioteke, koja sadrži različite metode za rad s I/O registrima, a deklariraju se posebne varijable. Ova knjižnica 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, ENABLE, ENABLEGPIODEF_GPIODIEf_GPIODief_GPSIPIEf_GPSIPiDienit; / Način izlaza GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // Odredite nogu na koju je spojena GPIO_Init LED (GPIOE, GPIO_InitStructure); // Inicijalizacija strukture) int main (init_id) (struktura) int GPIO_Pin GPIO_Pin GPIO_Pin GPIO_Pin GPIO / Postavite visoko stanje na nozi dok (1) (_NOP (;))

Radi uštede energije svi periferni uređaji mikrokontrolera su onemogućeni. Da biste "aktivirali" ovu ili onu periferiju, prvo joj morate poslati sat signale.

Radimo s 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.

Obradili smo rad s bitskim operacijama i binarnim brojevima, postavljajući tako temelje za novu temu. U ovoj lekciji razmotrit ćemo još jedno pitanje: što su registri i kako s njima raditi?

Memorija i registri

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

Općenito, registar je posebna vrsta memorije unutar mikrokontrolera koja se koristi za upravljanje procesorom i perifernim uređajima. Svaki registar u ARM arhitekturi je memorijska ćelija i ima duljinu od 32 bita, pri čemu se svaki bit može predstaviti kao sićušni prekidač kojim se kontrolira jedan ili drugi parametar mikrokontrolera.

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

Također je vrijedno napomenuti da Referentni priručnik koji smo preuzeli jedna je velika referenca za registre sadržane u ciljnom mikrokontroleru, a CMSIS knjižnica nam omogućuje rad sa simboličkim imenima registara umjesto numeričkim adresama. Na primjer, u registar 0x40011018 možemo upućivati ​​jednostavno korištenjem simboličkog naziva GPIOC_BSSR... Razmotrit ćemo konkretne primjere konfiguracije tijekom analize našeg programa iz prve lekcije.

Dakle, obično se struktura registra opisuje u obliku male tablice s naznakom:

  1. Registrirajte nazive i opise 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 predodžbu 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 palio dvije LED diode na ploči Discovery (možda ne dvije ako imate drugu verziju Discovery board) s vremenskim intervalom ...

Pogledajmo još jednom kod programa kojim smo naš MK držali dvije noge na kojima se nalaze naše LED diode:

Glavni.c kod

/ * Datoteka zaglavlja za našu obitelj mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; / * Konfigurirajte način rada portova PC8 i PC9 u Izlaz * / GPIOC -> MODER = 0x50000; / * Postavite vrstu izlaza na Push-Pull način * / 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 niz pitanja:
  1. Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?
  2. Kako uključiti i isključiti LED?
Odgovorit ćemo im redom.

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

Kako bismo vidjeli gdje se što nalazi na ploči Discovery, a posebno LED diode koje su nam potrebne, moramo otvoriti datoteku sheme, bilo onu koju smo preuzeli s web stranice ST, ili izravno s Keila:


Nakon otvaranja Schematica, vidjet ćemo dijagram svega što je na ploči - ST-Link krug, 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 spojene na GPIOC port na 8 i 9 pinova.

Kako mogu omogućiti 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 sata izravno sa sabirnice na kojoj se nalazi ovaj modul. Prema zadanim postavkama, taktiranje svih perifernih uređaja je onemogućeno kako bi se smanjila potrošnja energije.
  2. Postavljanje putem kontrolnih registara, promjenom parametara specifičnih za pojedini periferni uređaj
  3. Izravno pokretanje i korištenje rezultata modula
To jest, da bismo započeli, moramo početi taktirati na GPIOC portu. To se radi izravnim pristupom registru RCC koji je odgovoran za clockanje svega i svakoga i uključivanje satnog signala sa sabirnice na koju je spojen naš GPIO port.

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

Pronađi na koju sabirnicu je spojen naš GPIOC port može se pronaći u podatkovnoj tablici na našem MK-u u odjeljku Mapiranje memorije u tablici 16. Granične adrese perifernog registra STM32F051xx.


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


Idemo do ove točke i vidimo naš 32-bitni registar, njegovu offset adresu, zadanu vrijednost, način pristupa registru i nabrajanje za što je odgovoran svaki bit u registru.


Pogledamo tablicu i vidimo nešto što podsjeća na opciju za omogućavanje takta na GPIO portovima. Idite na opis i pronađite opciju koja nam je potrebna:


Sukladno tome, 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, moramo omogućiti odvojeno jedan bit iz grupe, bez utjecaja na ostatak, budući da ne bismo se trebali miješati i nepotrebno mijenjati druge postavke.

Na temelju materijala iz prethodne lekcije, znamo da za postavljanje određenog bita morate upotrijebiti logičku operaciju "ILI" za dodavanje trenutne vrijednosti registra s maskom koja sadrži one bitove koje je potrebno okrenuti na. Na primjer, dodajte zadanu vrijednost registra RCC-> AHBENR, t.j. 0x14 i broj 0x80000 tako omogućuju GPIOC taktiranje postavljanjem 19 bita:

Kako to možemo učiniti unutar programa? Prilično je jednostavno. U ovom slučaju imamo dvije mogućnosti:

  1. Izravno upisivanje u registar brojčane vrijednosti registra izravno preko njegove adrese.
  2. Konfiguracija pomoću CMSIS biblioteke
Ne postoji poseban problem u izravnom 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 obratiti na adrese registra izravno na adresi i napisati ovako:

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

Predlažem da otvorimo naš projekt, koji smo napravili u prvoj lekciji, ili odavde preuzmemo prethodno pripremljeni 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 obitelj 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 biblioteku CMSIS radi pregleda.

Kako biste se brzo kretali do mjesta gdje je deklarirana ova ili ona konstanta ili varijabla, u Keilu je implementirana prikladna funkcija. Desnom tipkom miša kliknite 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 programsko upravljanje 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:


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

Osim 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, dobivamo lakonski čitljiv zapis parametra koji nam je potreban u registru, čijom instalacijom započinjemo taktiranje na portu koji nam je potreban:

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

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

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

Prije svega, moramo 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. I/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 prema opisu, da bismo pinove PC8 i PC9 postavili u izlazni način rada, moramo upisati 01 u odgovarajuća polja GPIOC registra.

To se može učiniti izravnom instalacijom pomoću brojčanih 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 upute, naši PC8 i PC9 pinovi će prijeći u izlazni način rada.

Kako uključiti LED?

Ako obratimo pažnju na popis dostupnih registara za upravljanje GPIO portom, možemo vidjeti ODR registar:


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


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

To možemo učiniti izravnim 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
No, budući da mikrokontroler radi vrlo brzo, nećemo primijetiti promjenu stanja LED dioda i vizualno će se činiti da su obje stalno uključene. Kako bi stvarno treptali, uvest ćemo umjetno kašnjenje u obliku ciklusa koji će neko vrijeme okupirati MC beskorisnim proračunima. Dobivate 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++){} // Искусственная задержка
Time je završeno početno upoznavanje s registrima i metodama rada s njima.

Provjera rezultata našeg koda

Mali lijepi dodatak na kraju članka: Keil ima izvrstan alat za uklanjanje pogreš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 gumb Start Debug Session:

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

Da bismo koristili mjerač vremena, moramo uključiti datoteku biblioteke periferije stm32f10x_tim.c. Isto tako, desnom tipkom miša kliknite radni prostor (lijevi prozor) na StdPeriphLib grupu, Dodaj -> Dodaj datoteke, datoteku LibrariesSTM32F10x_StdPeriph_Driversrcstm32f10x_tim.c.

Također morate omogućiti korištenje zaglavlja za ovu datoteku. Otvorite stm32f10x_conf.h (desno kliknite na naziv ove datoteke u kodu, "Otvori stm32f10x_conf.h". Dekomentirajte redak #include "stm32f10x_tim.h".

9. Dodajte mjerač vremena

Odgoda prazne petlje je bogohuljenje, pogotovo na tako moćnom kristalu kao što je STM32, s hrpom mjerača vremena. Stoga ćemo ovu odgodu napraviti pomoću mjerača vremena.

U STM32 postoje različiti mjerači vremena s različitim skupom svojstava. Najjednostavniji su osnovni mjerači vremena, teži su mjerači vremena opće namjene, a najsloženiji su napredni mjerači vremena. Jednostavni mjerači vremena ograničeni su samo na brojanje otkucaja. U složenijim mjeračima vremena pojavljuje se PWM. Najsofisticiraniji mjerači vremena, na primjer, mogu generirati 3-fazni PWM s izravnim i inverznim izlazima i mrtvim vremenom. Dovoljan nam je jednostavan mjerač vremena, broj 6.

Malo teorije

Sve što trebamo od timera je brojati do određene vrijednosti i generirati prekid (da, naučit ćemo i kako koristiti prekide). Mjerač vremena TIM6 se taktira sa sistemske sabirnice, ali ne izravno, već preko predskalera - jednostavnog programabilnog brojača (samo razmislite, posebni mikrosklopovi-brojači proizvedeni su u SSSR-u, a programibilni su bili u posebnom deficitu - a sada O takvom brojaču govorim samo u prolazu). Predskaler se može postaviti na bilo koju vrijednost od 1 (tj. puna frekvencija sabirnice, 24 MHz, ide na mjerač) do 65536 (tj. 366 Hz).

Signali sata, zauzvrat, povećavaju unutarnji brojač timera, počevši od nule. Čim vrijednost brojača dosegne vrijednost ARR, brojač se prelijeva i događa se odgovarajući događaj. Nakon pojave ovog događaja, mjerač vremena ponovno učitava 0 u brojač i počinje brojati od nule. Istodobno, može pokrenuti prekid (ako je konfiguriran).

Zapravo, proces je malo kompliciraniji: postoje dva ARR-a - vanjski i unutarnji. Tijekom brojanja, trenutna vrijednost se uspoređuje točno s internim registrom, a samo u slučaju prelijevanja interni se ažurira iz vanjskog. Stoga možete sigurno promijeniti ARR dok tajmer radi - u bilo kojem trenutku.

Kod

Kod će biti vrlo sličan prethodnom, budući da inicijalizacija svih perifernih uređaja je ista - s jedinom iznimkom da TIM6 timer visi na sabirnici APB1. Stoga, omogućavanje mjerača vremena: RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM6, ENABLE);

Sada postavljamo strukturu tipa TIM_TimeBaseInitTypeDef, inicijaliziramo je (TIM_TimeBaseStructInit), postavljamo je, prosljeđujemo je funkciji inicijalizacije timera (TIM_TimeBaseInit) i na kraju uključujemo mjerač vremena (TIM_Cmd).

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

Vrijednost u brojaču je 1000. To znači da će se brojač preliti u 1000 taktova. u točno 1 sekundi.

Nakon toga stvarno imamo radni mjerač vremena. 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 za njihovo pomicanje; ali o tome kasnije.

Kao što smo ranije primijetili, timer generira prekid u trenutku prelijevanja 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 što nam treba:

  1. Omogućite TIM6 timer prekide u potpunosti;
  2. Omogući prekid timera TIM6 za prelijevanje brojača;
  3. Napišite proceduru za rukovanje prekidima;
  4. Nakon što obradite prekid, resetirajte ga.

Omogućavanje prekida

Iskreno, ovdje uopće nema ništa komplicirano. Prije svega, omogućite TIM6 prekide: NVIC_EnableIRQ (TIM6_DAC_IRQn); Zašto takav naziv? 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 to 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 tko ga je točno uzrokovao. Gotovo svi ostali mjerači vremena imaju jedan prekid.

Konfiguriranje događaja izvora prekida: TIM_ITConfig (TIM6, TIM_DIER_UIE, ENABLE); - uključite prekid TIM6 timera na događaju TIM_DIER_UIE, t.j. Događaj ažuriranja ARR vrijednosti. Kao što se sjećamo sa slike, to se događa istovremeno s prelivanjem brojača - dakle upravo je to događaj koji nam treba.

Trenutno je kod za zadatke tajmera sljedeći:

Rukovanje prekidima

Sada ne možete pokrenuti projekt - prvi prekid iz timera neće pronaći svoj rukovalac, a kontroler će se zamrznuti (točnije, ući će u HARD_FAULT rukovalac, što je u biti ista stvar). Morate to napisati.

Malo teorije

Mora imati vrlo specifičan naziv, void TIM6_DAC_IRQHandler (void). Taj naziv, tzv. prekidni vektor, opisan je u startup datoteci (u našem projektu to je startup_stm32f10x_md_vl.s - možete sami vidjeti, redak 126). Zapravo, vektor je adresa rukovatelja prekida, a kada dođe do prekida, jezgra ARM-a se penje u početno područje (u koje se prevodi pokretačka datoteka – odnosno njezina je lokacija potpuno teško postavljena, na samom početku flash memorije), tamo traži vektor i ide na pravo mjesto u kodu.

Provjera događaja

Prva stvar koju trebamo učiniti kada ulazimo u takav rukovatelj je provjeriti koji je događaj pokrenuo prekid. Sada imamo samo jedan događaj, ali u stvarnom projektu može biti nekoliko događaja na jednom mjeraču vremena. 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 mjerač vremena za navedeni događaj i vraća 0 ili 1.

Brisanje UIF zastave

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

Prekini radnju

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

Koristimo globalnu varijablu int stanje = 0;

11. Cijeli kod projekta s timerom

Arhivirajte s projektom timera.

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

Cijeli ciklus:

1. I/O portovi

2. Tajmer i prekidi

3. Timer izlazi

4. Vanjski prekidi i NVIC

5. Instalirajte FreeRTOS

Nedavno me kolega navukao na ideju stvaranja pametne kuće, čak sam uspio naručiti desetke različitih senzora za sebe. Postavilo se pitanje o izboru Mikrokontroler(u daljnjem tekstu MK) ili ploče. Nakon dugog traženja, pronašao sam nekoliko opcija. Među njima je bilo 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 puno jednostavnije, ali neću pokretati temu o holivarima, svatko ima svoj ukus). Kao rezultat toga, odlučio sam se ne odlučiti za gotovu ploču, već uzeti samo MK i učiniti sve od nule. Kao rezultat toga, birao sam između Atmel attiny (2313), Atmel ATmega(Odlučio sam odbiti jer ga nisam mogao pronaći za adekvatan novac), STM32(korteks na jezgri RUKA). Već sam imao vremena igrati se s 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 obitelji STM32 sadrže do sedam 16-bitnih I/O portova pod nazivom PORTA do PORTG. U konkretnom modelu mikrokontroler bez iznimke, dostupni su svi pinovi priključka, čiji ukupan broj ovisi o vrsti kućišta i naveden je u DataSheet-u za odgovarajuću podobitelji.

Da biste omogućili port x, prvo ga morate spojiti na sabirnicu APB2 postavljanjem odgovarajućeg bita IOPxEN u registar za omogućavanje sata perifernih jedinica RCC_APB2ENR:

Upravljanje lukom STM32 provodi se pomoću skupova od sedam 32-bitnih registara:

  • GPIOx_CRL, GPIOx_CRH- postaviti načine 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 zapisuje podatke izravno u port.
  • GPIOx_BSRR- registrirajte se za atomsko resetiranje i postavljanje bitova priključka.
  • GPIOx_BSR- registrirajte se za čiste portne bitove.
  • GPIOx_LCKR- registar zaključavanja konfiguracije pinova.

Načini rada GPIO pinova

Načini rada pojedinih pinova određeni su kombinacijom bitova MODEy i CNFy registre GPIOx_CRL i GPIOx_CRH(u daljnjem 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: Izlazni način rada, maksimalna brzina - 10MHz;
  • MODEy = 10: Izlazni način rada, maksimalna brzina - 2MHz;
  • MODEy = 11: Izlazni način rada, 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 resetiranja);
  • CNFy = 10: Ulaz s pull-up otpornikom (ako je PxODR = 1) ili pull-down (ako je PxODR = 0);
  • CNFy = 11: Rezervirano.

u izlaznom modu:

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

Kako bi se povećala otpornost na buku, svi ulazni međuspremnici sadrže Schmidtove okidače. Dio zaključaka STM32 opremljen zaštitnim diodama spojenim na zajedničku sabirnicu i sabirnica napajanja označeni su u podatkovnoj tablici kao FT (tolerantno 5V) - kompatibilno s 5 volti.

Zaštita GPIO konfiguracijskih bitova

Za zaštitu bitova u konfiguracijskim registrima od neovlaštenog upisivanja u STM32 osiguran je registar zaključavanja postavki GPIOx_LCKR
GPIOx_LCKR- registrirajte se za blokiranje postavki izlaza porta:

Za zaštitu postavki pojedinog pina porta, mora se postaviti odgovarajući LCKy bit. Zatim izvršite uzastopno pisanje u kategoriju LCKK vrijednosti "1" - "0" - "1" i dvije operacije čitanja registra LCKR, što ć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 definira zasebne skupine 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: mjerač vremena i prekidi

Na primjer:

GPIOC-> BSRR- registar BSRR postavljen / brisanje porta GPIOC.
Koristimo definicije iz datoteke stm32f10x.h da ilustriramo rad s 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 konfiguriran za izlaz postavlja izlazne razine svih bitova porta u skladu sa snimljenom vrijednošć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 RUKA način upravljanja bitovima registra koji ne zahtijeva korištenje operacije tipa čitanje-izmjena-pisanje omogućuje vam postavljanje i brisanje bitova porta jednostavnim upisivanjem jednog u postavljene bitove BS (BitSet) i resetirajte BR (BitReset) Registar BSRR... U ovom slučaju upisivanje u registar nultih bitova ne utječe na stanje odgovarajućih pinova.

GPIOx_BSRR- registrirajte se za resetiranje i postavljanje bitova porta:

Alternativne funkcije GPIO i njihovo preraspoređivanje (ponovno mapiranje)
Gotovo svi vanjski krugovi za posebne namjene STM32(uključujući vodove za spajanje kvarcnih rezonatora, JTAG / SWD i tako dalje) može se omogućiti na odgovarajućim pinovima mikrokontrolera ili odvojiti od njih kako bi se mogli koristiti kao pinovi opće namjene. Izbor alternativne izlazne funkcije provodi se pomoću registara s prefiksom "AFIO”_.
Osim toga, registri AFIO _ omogućuju vam da odaberete nekoliko opcija za smještaj posebnih funkcija na pinovima mikrokontrolera. To se posebno odnosi na izlaze komunikacijskih sučelja, mjerača vremena (registra AFIO_MAPR), pinovi vanjskih prekida (registri AFIO_EXTICR) itd.

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

Projekti za članak:

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

Za upravljanje GPIOSTM32 Možete koristiti makronaredbe napisane kao alternativu onima koje su daleko od optimalnih prema mnogim knjižnicama iz ST-a: gpio_emcu.h

Dodatni materijal:

  1. STM32F10xxx Referentni priručnik. Referentni vodič za razvojne programere
  2. STM32F100xx Referentni priručnik. Referentni vodič za razvojne programere
  3. STM32F105xx, STM32F107xx Datasheet
  4. STM32F100x4, STM32F100x6, STM32F100x8, STM32F100xB Tehnički list
  5. Vodič za izradu projekata za STM32DISCOVERY u IAR-u
  6. Vodič za izradu 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 satni sustav
  3. STM32 programiranje. Dio 3. Sustav prekida
  4. STM32 programiranje. Dio 4. Vanjski prekidi EXTI

Osnovni mjerači vremena u STM32

Tajmeri su takve periferije STM32 kontrolera koje nam omogućuju vrlo precizno brojanje vremenskih intervala. Ovo je možda jedna od najvažnijih i najčešće korištenih funkcija, ali postoje i druge. Za početak, u STM32 kontrolerima postoje mjerači vremena različitog stupnja hladnoće. Najjednostavniji su Osnovni, temeljnimjerači vremena ... Dobri su jer ih je vrlo lako konfigurirati i upravljati s minimalnim brojem registara. Sve što mogu učiniti je odbrojavati vremenske intervale i generirati prekide kada mjerač vremena dosegne unaprijed određenu vrijednost. Sljedeća grupa ( mjerači vremena opće namjene ) je puno hladniji od prvog, znaju generirati PWM, mogu brojati impulse koji dolaze na određene noge, možete spojiti enkoder itd. A najcool timer je tajmer za napredno upravljanje , mislim da ga neću koristiti još jako dugo jer za sada nemam potrebu za upravljanjem trofaznim elektromotorom. Za početak upoznavanja s mjeračima vremena trebao bi biti nešto jednostavnije, odlučio sam uzeti Basic mjerače vremena. Zadatak koji sam sebi postavio: Neka timer generira prekide svake sekunde.

Prije svega, napominjem da su Basic mjerači vremena (TIM6 i TIM7) spojeni na sabirnicu APB1, pa ako se frekvencija takta na njoj promijeni, timeri će početi otkucavati brže ili sporije. Ako ništa ne promijenite u postavkama takta i ostavite ih na zadanim, onda frekvenciju APB1 je 24 MHz, pod uvjetom da je vanjski kristal spojen na frekvenciju od 8 MHz. Općenito, sustav takta STM32 je vrlo zamršen i pokušat ću o njemu normalno napisati zaseban post. Za sada, koristimo samo one postavke takta koje su postavljene kodom koji automatski generira CooCox. Vrijedi početi s najvažnijim registrom - TIMx_CNT(u daljnjem tekstu x je broj osnovnog mjerača vremena 6 ili 7). Ovo je 16-bitni registar za brojanje koji se izravno bavi odbrojavanjem vremena. Svaki put iz autobusa APB1 dolazi taktni impuls, 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, mjerač vremena otkucava 24 milijuna puta u jednoj sekundi! Ovo je vrlo nedostatno, pa stoga timer ima predskaler, kojim možemo kontrolirati pomoću registra TIMx_PSC... Upisivanjem vrijednosti 24000-1 u njega ćemo forsirati registar brojanja TIMx_CNT povećavati njegovu vrijednost svake milisekunde (Frekvencija APB1 podijelite s brojem u registru predskalera 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 djelitelj s jedan. Sada, kada registar brojanja dosegne 1000, možemo sa sigurnošću reći da je prošla točno jedna sekunda! I zašto sada ispitivati ​​registar brojanja i čekati da se tamo pojavi 1000? Ovo nije naša metoda, jer možemo koristiti prekide! Ali problem je u tome što imamo samo jedan prekid, a javlja se kada se brojač vrati na nulu. Da bi se brojač resetirao prije roka, a ne kada dosegne 0xFFFF, koristi se registar TIMx_ARR... U njega upisujemo broj na koji bi registar trebao računati TIMx_CNT prije resetiranja na nulu. Ako želimo da se prekid javlja jednom u sekundi, onda tu trebamo upisati 1000. Što se vremena tiče, to je sve, ali sam timer neće početi otkucavati. Mora se uključiti postavljanjem bita CEN u registru TIMx_CR1... Ovaj bit vam omogućuje da počnete brojati, odnosno ako ga izbrišete, brojanje će se zaustaviti (vaš K.O.).

Tajmeri na STM32. Postavljanje osnovnog mjerača vremena

U registru ima i drugih bitova, ali nam nisu posebno zanimljivi. Ali nas zanima još jedan dio, ali već u registru TIMx_DIER... To se zove UIE, njegovim postavljanjem omogućujemo timeru da generira prekide kada se registar brojanja resetuje. To je sve, nije ni kompliciranije nego u nekim AVR-ima. Dakle, mali sažetak: Za korištenje osnovnog mjerača vremena potrebno vam je:

  1. Postavite predskaler tako da mjerač vremena 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 slijeda. A sada je vrijeme da ga sami nabavite, znate što, i pokušate zatreptati ove nesretne LED diode po milijunti put, ali uz pomoć mjerača vremena 🙂

#include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" int main () (GPIO_InitTypeDef PORT; // Omogući port C i mjerač vremena 6 RCC_APB2PeriphClockCmd za konfiguraciju LED-a s //RPipGB konfiguracijom; 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 djelitelj = da je timer 0 0 0 0 puta u sekundi; da se prekid događa jednom u sekundi TIM6-> DIER | = TIM_DIER_UIE; // omogući prekid timera TIM6-> CR1 | = TIM_CR1_CEN; // Počni odbrojavati! NVIC_EnableIRQ (TIM6_DAC_IRQn); // Omogući TIM6_DAC_IRQn; // Omogući TIM6_DAC_IRQn (/prekini dok / Program ne radi ništa u praznoj petlji)) // TIM6_DAC rukovalac prekidanjem void TIM6_DAC_IRQHandler (void) (TIM6-> SR & = ~ TIM_SR_UIF; // Obriši zastavu UIF GPIOC-> ODR ^ = (GPIO_Pin_9 | GPIO_Pin_8); / Invertirajte stanje LED dioda)

Vrijedno je dodati malu napomenu rukovatelju prekida. Činjenica je da ga koriste dvije periferne jedinice odjednom: timer 6 i DAC. To znači da ako napišete program koji dopušta prekide s oba ova periferna uređaja, tada je u tijelu rukovatelja potrebno provjeriti koji je od njih uzrokovao prekid. U našem slučaju to nisam učinio jer ne može doći do DAC prekida. Nije konfiguriran, a prekidi su onemogućeni prema zadanim postavkama. Sljedeći put ćemo pogledati mjerače vremena opće namjene i njihovu praktičnu primjenu.

PWM generacija u STM32

U prethodnom članku o osnovnim mjeračima vremena još jednom smo treptali LED diodama, a ovaj put ćemo ići puno dalje i pokušati shvatiti kako natjerati STM32 kontroler da generira PWM. Da bismo to učinili, morat ćemo koristiti jedan od mjerača vremena opće namjene, jer oni imaju sve što je potrebno za to. Ostatak funkcionalnosti ovih mjerača vremena svakako je 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 sposobnost rukovanja 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 glatko osvijetliti i potamniti svaku boju. Naravno, možete uzeti tri različite LED diode ako nema RGB.

S razlogom smo spojili LED na ove pinove. Tajmeri opće namjene mogu generirati PWM samo na određenim pinovima. Budući da ćemo koristiti timer 2, na raspolaganju su nam 4 noge (PA0-PA3). Da bi ih mjerač vremena mogao koristiti, morate ga omogućiti na dva mjesta: Konfigurirajte tri kraka (PA1-PA3) kao izlaz s alternativnom funkcijom i dopustite povlačenje ovih krakova u postavkama timera za generiranje PWM-a. Za to nam je potreban registar CCER

Ako jedan od bitova označenih plavom bojom postavite na jedan, timeru će biti dopušteno koristiti odgovarajuću nogu za PWM. Iz dijagrama možete vidjeti da trebamo postaviti bitove CC2E, CC3E i CC4E... Sada moramo konfigurirati PWM način rada: Direct ili Inverse (ne pretvaram se da sam točan u terminologiji). Razlika je sasvim očita - kod izravnog PWM-a, što je veći broj u registru za usporedbu, veći je radni ciklus PWM-a. U slučaju inverznog PWM-a, točno je suprotno. Upišite nulu u registar za usporedbu - faktor popunjavanja je 100%.

Rad s jednostavnim mjeračima vremena otkrivanja STM32 F4

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

Za postavku svakog kanala dodijeljeno je čak 8 bitova! No, 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 s drugim imenom, koriste se ako je kanal timera u načinu snimanja. Neću razmatrati sve kombinacije bitova, jer većina njih nema nikakve veze s PWM-om. Potrebne su nam samo dvije kombinacije bitova:

Izravni 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! Postavljanje PWM-a je završeno, sada samo trebate pokrenuti mjerač vremena 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 je smanjuje na nulu i prelazi na sljedeći.

Proces se ponavlja u nedogled, prelijepo 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 mjerač vremena 2 RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE); GPIO_InitType); GPIO_InitType GPIO_InitType GPIO_InitType izlaz i nećemo koristiti GPIOAF_GPIO izlaz. PORT.GPIO_Speed ​​= GPIO_Speed_2MHz; GPIO_Init (GPIOA, & PORT); // Dopusti timeru 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 timer TIM2-> CR1 | = TIM_CR1_CEN ; // Nakon ovoga oh, zapisujemo podatke u TIM2-> CCRx - i svjetlina LED dioda se mijenja uint32_t pwm_arr = (0,0,6553,13107,19660,26214,32768, 39321,45875,52428,585382,); uint8_t i; dok (1) (za (i = 1; i<=11;i++) { TIM2->CCR3 = pwm_arr [i]; odgoda (); ) za (i = 11; i> = 1; i—) (TIM2-> CCR3 = pwm_arr [i]; kašnjenje ();) za (i = 1; i<=10;i++) { TIM2->CCR2 = pwm_arr [i]; odgoda (); ) za (i = 11; i> = 1; i—) (TIM2-> CCR2 = pwm_arr [i]; kašnjenje ();) za (i = 1; i<=10;i++) { TIM2->CCR4 = pwm_arr [i]; odgoda (); ) 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 što sam pušio skoro pola dana. Jednostavna pitanja možete napisati u nastavku.

Džepni osciloskop "Lori" na mikrokontroleru STM32F103

Maksim Kerimov
prosinca 2016

Formulacija problema

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

Popis komponenti

  • Kineski klon Maple Mini ploče s mikrokontrolerom STM32F103C8T6.
  • Zaslon 1.8 TFT 128 × 160 SPI sa ST7735 drajverom.
  • Pet otpornika i dva kondenzatora (slika 3).
  • Linearni regulator malog ispadanja AMS1117-3.3 (opcija).
  • Stezna sonda "pinceta" - 2 kom.
  • Tipka je minijaturna, normalno otvorena bez fiksiranja, uz klik.

Riža. 1. Probni rad osciloskopa. Sinusoidu stvara zvučni blaster, stoga je stepenasti.

Tehnički podaci

7 raspona sa stopom podjele (stanice): 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 impedancija: 20 kΩ.
Napajanje: 4 AA baterije.
Struja potrošnje: 80 mA.

Koji frekvencijski signal 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 ugodno promatrati signale do 200 kHz. Veličina ćelije: 20 x 20 px.

"Brzina pomicanja" našeg osciloskopa ovisi o brzini ADC-a. U STM32F103 kapacitet ADC-a je fiksiran na 12. To je jedan i pol 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 s drugačijim budžetom.

Riža. 2. Povezivanje zaslona.

Riža. 3. Napajanje i ulazni krug.

Razdjelnik napona R1-R2 koristi se za kontrolu razine napunjenosti baterije. U gornjem desnom kutu ekrana nalazi se ikona baterije, kao na mobitelu (nije prikazana na fotografiji).

Vanjski regulator napona nije uvijek potreban. Ploča mikrokontrolera ima vlastiti 3.3V 100mA regulator. Ako napajate zaslon s njega, on će se zagrijati. Na pločama drugog tipa (s velikim JTAG konektorom) postoji samo AMS1117, ne treba im vanjski. Neki zasloni također imaju AMS1117 (i kratkospojnik). Odlučite sami.

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

Ako želite povećati veličinu svoje impedancije, možete dodati neinvertirajući sljedbenik na op-pojačalu na ulaz, što će vam omogućiti da postignete vrijednost od 1 MΩ ili više. Op-pojačalo bi se trebalo napajati izravno iz baterija napona 4,8 - 5,4 V.

Princip rada

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

ADC vrši niz kontinuiranih uzastopnih mjerenja razine signala. Rezultirajuće vrijednosti se dodaju u memoriju pomoću DMA. Svaki put mjerimo i određujemo trajanje serije mjerenja. Tako saznajemo cijenu podjele vremenske osi.

Analizirajući snimljene vrijednosti razine signala, tražimo prvi ekstrem, nakon čega iscrtavamo signal na ekranu. Dakle, pokušavamo napraviti svojevrsnu sinkronizaciju. Dobro radi na glatkim signalima i gotovo je beskoristan na širokopojasnim signalima.

Dopuštamo korisniku da uživa u slici jednu sekundu, a mi sami prozivamo gumb. Kratkim pritiskom na tipku mijenjate raspone u krug. Dugi pritisak mijenja osjetljivost.

STM32 za početnike. Lekcija 3. STM32 mjerači vremena.

Zatim se sve ponavlja.

Koristim CooCox CoIDE okruženje za kompilaciju. Ovdje nisam prenio Cox projekt jer sadrži apsolutne putove do datoteka. Lakše je stvoriti novi nego ispraviti sve puteve. Nakon izrade projekta, ne zaboravite spojiti 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-Serial adaptera.

Korišteni materijali:
Projekt škotskog majstora Pingumacpenguina
Adafruit zaslon
STM32 Spremanje ADC podataka pomoću DMA

Tekst programa

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

STM32 od nule. Tajmeri.

U STM32 mikrokontrolerima postoji nekoliko mjerača vremena 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 za [U mikrokontrolerima STM32 postoji nekoliko mjerača vremena 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 timera 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”) pojavi se PWM signal. Kako se to radi?

Tajmer prima impulse takta s APB sabirnice, čija je frekvencija polovica frekvencije jezgre (u našem slučaju 24 MHz) (link na RCC), a oni prolaze kroz predskaler koji smo postavili na 10 – t.j. ispada 1,2MHz. Tajmer je konfiguriran da broji 1000 taktova, nakon čega uzima novu vrijednost iz ARR registra, koju ne mijenjamo – t.j. istih 1000, ovo je period PWM signala. Na početku ciklusa, timer ispušta "1" na izlaz, a nakon 200 ciklusa takta vraća se na "0" - ovo je PWM radni ciklus.

Obradili smo rad s bitskim operacijama i binarnim brojevima, postavljajući tako temelje za novu temu. U ovoj lekciji razmotrit ćemo još jedno pitanje: što su registri i kako s njima raditi?

Memorija i registri

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

Općenito, registar je posebna vrsta memorije unutar mikrokontrolera koja se koristi za upravljanje procesorom i perifernim uređajima. Svaki registar u ARM arhitekturi je memorijska ćelija i ima duljinu od 32 bita, pri čemu se svaki bit može predstaviti kao sićušni prekidač kojim se kontrolira jedan ili drugi parametar mikrokontrolera.

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

Također je vrijedno napomenuti da Referentni priručnik koju smo preuzeli u prvoj lekciji jedna je velika referenca za registre sadržane u ciljnom mikrokontroleru, a CMSIS knjižnica nam omogućuje rad sa simboličkim imenima registara umjesto numeričkim adresama. Na primjer, u registar 0x40011018 možemo upućivati ​​jednostavno korištenjem simboličkog naziva GPIOC_BSSR... Razmotrit ćemo konkretne primjere konfiguracije tijekom raščlanjivanja našeg programa iz.

Dakle, obično se struktura registra opisuje u obliku male tablice s naznakom:

  1. Registrirajte nazive i opise 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 predodžbu o principima postavljanja mikrokontrolera.

Raščlanjivanje koda iz prve lekcije

Dakle, prisjetimo se problema koji smo riješili pomoću gotovog primjera koda: trebali 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 ploča) s vremenskim intervalom.

Pogledajmo još jednom kod programa kojim smo naš MK držali dvije noge na kojima se nalaze naše LED diode:

Glavni.c kod

/ * Datoteka zaglavlja za našu obitelj mikrokontrolera * / #include "stm32f0xx.h" / * Tijelo glavnog programa * / int main (void) (/ * Uključite taktiranje na GPIO portu * / RCC-> AHBENR | = RCC_AHBENR_GPIOCEN; / * Konfigurirajte način rada portova PC8 i PC9 u Izlaz * / GPIOC -> MODER = 0x50000; / * Postavite vrstu izlaza na Push-Pull način * / 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 niz pitanja:
  1. Kako konfigurirati potrebne GPIO pinove tako da možete uključiti LED?
  2. Kako uključiti i isključiti LED?
Odgovorit ćemo im redom.

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

Kako bismo vidjeli gdje se što nalazi na ploči Discovery, a posebno LED diode koje su nam potrebne, moramo otvoriti datoteku sheme, bilo onu koju smo preuzeli s web stranice ST, ili izravno s Keila:


Nakon otvaranja Schematica, vidjet ćemo dijagram svega što je na ploči - ST-Link krug, 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 spojene na GPIOC port na 8 i 9 pinova.

Kako mogu omogućiti 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 sata izravno sa sabirnice na kojoj se nalazi ovaj modul. Prema zadanim postavkama, taktiranje svih perifernih uređaja je onemogućeno kako bi se smanjila potrošnja energije.
  2. Postavljanje putem kontrolnih registara, promjenom parametara specifičnih za pojedini periferni uređaj
  3. Izravno pokretanje i korištenje rezultata modula
To jest, da bismo započeli, moramo početi taktirati na GPIOC portu. To se radi izravnim pristupom registru RCC koji je odgovoran za clockanje svega i svakoga i uključivanje satnog signala sa sabirnice na koju je spojen naš GPIO port.

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

Pronađi na koju sabirnicu je spojen naš GPIOC port može se pronaći u podatkovnoj tablici na našem MK-u u odjeljku Mapiranje memorije u tablici 16. Granične adrese perifernog registra STM32F051xx.


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


Idemo do ove točke i vidimo naš 32-bitni registar, njegovu offset adresu, zadanu vrijednost, način pristupa registru i nabrajanje za što je odgovoran svaki bit u registru.


Pogledamo tablicu i vidimo nešto što podsjeća na opciju za omogućavanje takta na GPIO portovima. Idite na opis i pronađite opciju koja nam je potrebna:


Sukladno tome, 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, moramo omogućiti odvojeno jedan bit iz grupe, bez utjecaja na ostatak, budući da ne bismo se trebali miješati i nepotrebno mijenjati druge postavke.

Na temelju materijala iz prethodne lekcije, znamo da za postavljanje određenog bita morate upotrijebiti logičku operaciju "ILI" za dodavanje trenutne vrijednosti registra s maskom koja sadrži one bitove koje je potrebno okrenuti na. Na primjer, dodajte zadanu vrijednost registra RCC-> AHBENR, t.j. 0x14 i broj 0x80000 tako omogućuju GPIOC taktiranje postavljanjem 19 bita:

Kako to možemo učiniti unutar programa? Prilično je jednostavno. U ovom slučaju imamo dvije mogućnosti:

  1. Izravno upisivanje u registar brojčane vrijednosti registra izravno preko njegove adrese.
  2. Konfiguracija pomoću CMSIS biblioteke
Ne postoji poseban problem u izravnom 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 obratiti na adrese registra izravno na adresi i napisati ovako:

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

Predlažem da otvorimo naš projekt, koji smo napravili u prvoj lekciji, ili odavde preuzmemo prethodno pripremljeni 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 obitelj 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 biblioteku CMSIS radi pregleda.

Kako biste se brzo kretali do mjesta gdje je deklarirana ova ili ona konstanta ili varijabla, u Keilu je implementirana prikladna funkcija. Desnom tipkom miša kliknite 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 programsko upravljanje 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:


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

Osim 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, dobivamo lakonski čitljiv zapis parametra koji nam je potreban u registru, čijom instalacijom započinjemo taktiranje na portu koji nam je potreban:

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

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

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

Prije svega, moramo 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. I/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 prema opisu, da bismo pinove PC8 i PC9 postavili u izlazni način rada, moramo upisati 01 u odgovarajuća polja GPIOC registra.

To se može učiniti izravnom instalacijom pomoću brojčanih 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 upute, naši PC8 i PC9 pinovi će prijeći u izlazni način rada.

Kako uključiti LED?

Ako obratimo pažnju na popis dostupnih registara za upravljanje GPIO portom, možemo vidjeti ODR registar:


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


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

To možemo učiniti izravnim 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
No, budući da mikrokontroler radi vrlo brzo, nećemo primijetiti promjenu stanja LED dioda i vizualno će se činiti da su obje stalno uključene. Kako bi stvarno treptali, uvest ćemo umjetno kašnjenje u obliku ciklusa koji će neko vrijeme okupirati MC beskorisnim proračunima. Dobivate 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++){} // Искусственная задержка
Time je završeno početno upoznavanje s registrima i metodama rada s njima.

Provjera rezultata našeg koda

Mali lijepi dodatak na kraju članka: Keil ima izvrstan alat za uklanjanje pogreš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 gumb Start Debug Session:

GPIO I/O portovi u STM32 imaju 16 linija, od kojih se svaki može konfigurirati prema potrebi. Podržane su funkcije digitalnog ulaza, digitalnog izlaza, ulaza vanjskog prekida i I/O funkcija ostalih modula mikrokontrolera. STM32 programiranje za rad s GPIO temelji se na korištenju konfiguracijskih registara, čitanja, pisanja, zaštite konfiguracije i registra pristupa bitu.

Registri konfiguracije porta.

Niski 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. Omogućuju vam da prilagodite način rada bilo koje pojedinačne linije. Registar GPIOx_CRL odgovoran je za redove s brojevima od 0 do 7, GPIOx_CRH - za redove 8-15. Za svaki od njih registar ima dva dvoznamenkasta 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 redak /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 resetiranja.
  • 01 - linija radi na izlazu, s maksimalnom frekvencijom prebacivanja od 10 MHz
  • 10 - linija radi na izlazu, s maksimalnom frekvencijom prebacivanja od 20 MHz
  • 11 - linija radi na izlazu, s maksimalnom frekvencijom prebacivanja od 50 MHz

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

  • 00 - analogni ulaz.
  • 01 - ulaz je u trećem stanju. (Instalira se nakon resetiranja).
  • 10 - ulaz s pull-up otpornikom
  • 11 - Pridržano za buduću upotrebu.

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

  • 00 - digitalni izlaz
  • 01 - digitalni izlaz s otvorenim odvodom
  • 10 - digitalni izlaz spojen na specijalizirane blokove
  • 11 - digitalni izlaz spojen na specijalizirane blokove s 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 Kako bi onemogućili promjenu postavki porta u STM32 mikrokontrolerima, koristi se registar GPIOx_LCKR. Njegovih najmanjih 15 bitova odgovorni su za odgovarajuće linije I/O porta. Bit 16, postavljen na 1, omogućuje 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 primijeni, 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. Ponovno pročitajte GPIOx_LCKR

Registri za postavljanje 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 skupine - port registre i registre za postavljanje pojedinačnih bitova.

Registar izlaza ulaza/izlaza

Registar izlaznih podataka priključka (GPIOx_ODR) (x = A..G)

Polje

Polje

Ovaj registar je širok 32 bita, ali se koristi samo donjih 16 bita. Bitovi od 16 do 31 se ne koriste. Prilikom upisivanja bilo koje vrijednosti u GPIOx_ODR, ova se vrijednost 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 Rezervirajte
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1
Polje 15 IDR 14 IDR 13 IDR 12 IDR 11 IDR 10 IDR 9 IDR 8 IDR 7 IDR 6 IDR 5 IDR IDR4 IDR3 IDR2 IDR1 IDR0

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

Registar bitnih operacija

Registar bitova porta/resetiranja (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ćuje upućivanje na određenu I/O liniju mikrokontrolera STM32. Upisivanjem jednog u jedan od najznačajnijih bitova resetira se linijski izlaz, a pisanjem jednog u najmanje značajne bitove postavlja se razina signala na visokoj razini odgovarajuće linije. Registar je zapisan u formatu riječi, s nultim bitovima koji nemaju učinka. Registrski bitovi su samo za pisanje.

Resetirajte registar

Registar bita za poništavanje porta (GPIOx_BRR) (x = A..G)

Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Polje Rezervirajte
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 visoku razinu linije postavljene u registru GPIOx_ODR. Koristi se samo donjih 16 bitova, dostupnih samo za pisanje.

Vrhunski povezani članci