2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Š’ pirmā daļa Es mēģināju stāstÄ«t hobiju elektronikas inženieriem, kuri uzauguÅ”i no Arduino biksēm, kā un kāpēc viņiem vajadzētu lasÄ«t datu lapas un citu mikrokontrolleru dokumentāciju. Teksts izrādÄ«jās liels, tāpēc praktiskus piemērus apsolÄ«ju parādÄ«t atseviŔķā rakstā. Nu viņŔ sevi sauca par piena sēni...

Å odien es jums parādÄ«Å”u, kā izmantot datu lapas, lai atrisinātu diezgan vienkārÅ”us, bet daudziem projektiem nepiecieÅ”amos uzdevumus STM32 (Blue Pill) un STM8 kontrolleros. Visi demo projekti ir veltÄ«ti manām mīļākajām gaismas diodēm, mēs tās apgaismosim lielos daudzumos, kam bÅ«s jāizmanto visādas interesantas perifērijas ierÄ«ces.

Teksts atkal izrādījās milzīgs, tāpēc ērtības labad veidoju saturu:

STM32 Blue Pill: 16 gaismas diodes ar DM634 draiveri
STM8: seŔu PWM tapu iestatīŔana
STM8: 8 RGB gaismas diodes uz trim tapām, pārtraukumi

Atruna: Es neesmu inženieris, nepretendēju uz dziļām zināŔanām elektronikā, raksts ir paredzēts tādiem amatieriem kā es. PatiesÄ«bā es sevi uzskatÄ«ju par mērÄ·auditoriju pirms diviem gadiem. Ja kāds man toreiz bÅ«tu teicis, ka datu lapas nepazÄ«stamā mikroshēmā nav biedējoÅ”i lasÄ«t, es nebÅ«tu veltÄ«jis daudz laika, meklējot dažus koda gabalus internetā un izgudrojot kruÄ·us ar Ŕķērēm un lÄ«mlenti.

Å ajā rakstā galvenā uzmanÄ«ba tiek pievērsta datu lapām, nevis projektiem, tāpēc kods var nebÅ«t ļoti glÄ«ts un bieži vien ir ierobežots. PaÅ”i projekti ir ļoti vienkārÅ”i, lai gan piemēroti pirmajai iepazÄ«Å”anai ar jauno mikroshēmu.

Es ceru, ka mans raksts palÄ«dzēs kādam lÄ«dzÄ«gā hobija iegremdÄ“Å”anas posmā.

STM32

16 gaismas diodes ar DM634 un SPI

Neliels projekts, izmantojot Blue Pill (STM32F103C8T6) un DM634 LED draiveri. Izmantojot datu lapas, mēs noskaidrosim draiveri, STM IO portus un konfigurēsim SPI.

DM634

Taivānas mikroshēma ar 16 16 bitu PWM izejām, var savienot ķēdēs. Zemākās klases 12 bitu modelis ir zināms no vietējā projekta Lightpack. Savulaik, izvēloties starp DM63x un labi zināmo TLC5940, es izvēlējos DM vairāku iemeslu dēļ: 1) Aliexpress TLC noteikti ir viltots, bet Å”is nav; 2) DM ir autonoms PWM ar savu frekvenču Ä£eneratoru; 3) to varēja lēti iegādāties Maskavā, nevis gaidÄ«t sÅ«tÄ«jumu no Ali. Un, protams, bija interesanti iemācÄ«ties paÅ”am vadÄ«t mikroshēmu, nevis izmantot gatavu bibliotēku. Tagad mikroshēmas galvenokārt tiek piedāvātas SSOP24 iepakojumā, tās ir viegli pielodēt ar adapteri.

Tā kā ražotājs ir taivānietis, datu lapas mikroshēma ir rakstÄ«ta Ä·Ä«nieÅ”u angļu valodā, kas nozÄ«mē, ka tas bÅ«s jautri. Vispirms skatāmies uz pinout (Pin savienojums), lai saprastu, kurai kājiņai ar ko pieslēgt, un tapu aprakstu (Pin Apraksts). 16 tapas:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Līdzstrāvas izlietnes avoti (atvērta kanalizācija)

Izlietne / Atvērta kanalizācijas izvade ā€“ notekas; ieplÅ«stoŔās strāvas avots; izeja ir savienota ar zemi aktÄ«vā stāvoklÄ« - gaismas diodes ir savienotas ar draiveri ar katodiem. Elektriski tā, protams, nav ā€œatvērta kanalizācijaā€ (atvērta kanalizācija), taču datu lapās Å”is apzÄ«mējums tapām drenāžas režīmā bieži ir atrodams.

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Ārējie rezistori starp REXT un GND, lai iestatītu izejas strāvas vērtību

Starp REXT tapu un zemējumu ir uzstādÄ«ts atsauces rezistors, kas kontrolē izeju iekŔējo pretestÄ«bu, skatiet diagrammu datu lapas 9. lappusē. DM634 Å”o pretestÄ«bu var kontrolēt arÄ« ar programmatÅ«ru, iestatot kopējo spilgtumu (globālais spilgtums); Å ajā rakstā es neiedziļināŔos, es vienkārÅ”i ievietoÅ”u Å”eit 2.2ā€“3 kOhm rezistoru.

Lai saprastu, kā vadīt mikroshēmu, apskatīsim ierīces saskarnes aprakstu:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Jā, lÅ«k, Ä·Ä«nieÅ”u angļu valoda visā tās krāŔņumā. To tulkot ir problemātiski, ja vēlaties, varat to saprast, bet ir arÄ« cits veids - apskatiet, kā datu lapā ir aprakstÄ«ts savienojums ar funkcionāli lÄ«dzÄ«gu TLC5940:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
... Lai ievadÄ«tu datus ierÄ«cē, ir nepiecieÅ”ami tikai trÄ«s tapas. SCLK signāla augoŔā mala novirza datus no SIN tapas uz iekŔējo reÄ£istru. Kad visi dati ir ielādēti, Ä«ss augsts XLAT signāls aiztur secÄ«gi pārsÅ«tÄ«tos datus iekŔējos reÄ£istros. IekŔējie reÄ£istri ir vārti, ko iedarbina XLAT signāla lÄ«menis. Visi dati vispirms tiek pārsÅ«tÄ«ti vissvarÄ«gākais bits.

AizbÄ«dnis ā€“ fiksators/fiksators/slēdzene.
AugoŔā mala ā€“ pulsa priekŔējā mala
MSB vispirms ā€“ nozÄ«mÄ«gākais (kreisais) bits uz priekÅ”u.
pulksteņa datiem ā€“ pārsÅ«tÄ«t datus secÄ«gi (pa bitiem).

Vārds aizÅ”aujamais bieži atrodams mikroshēmu dokumentācijā un tiek tulkots dažādos veidos, tāpēc sapratnes labad atļauÅ”os

neliela izglÄ«tÄ«bas programmaLED draiveris bÅ«tÄ«bā ir maiņu reÄ£istrs. "Maiņa" (maiņa) nosaukumā - datu kustÄ«ba pa bitiem ierÄ«ces iekÅ”ienē: katrs jauns iekŔā ievietots bits nospiež visu ķēdi uz priekÅ”u. Tā kā maiņas laikā neviens nevēlas novērot haotisku gaismas diožu mirgoÅ”anu, process notiek buferreÄ£istros, kas no darba reÄ£istriem atdalÄ«ti ar slāpētāju (aizÅ”aujamais) ir sava veida uzgaidāmā telpa, kurā biti ir sakārtoti vēlamajā secÄ«bā. Kad viss ir gatavs, aizvars atveras un uzgaļi dodas uz darbu, nomainot iepriekŔējo partiju. Vārds aizÅ”aujamais mikroshēmu dokumentācijā gandrÄ«z vienmēr nozÄ«mē Ŕādu slāpētāju neatkarÄ«gi no tā, kādās kombinācijās tas tiek izmantots.

Tātad datu pārsÅ«tÄ«Å”ana uz DM634 tiek veikta Ŕādi: iestatiet DAI ievadi uz tālās gaismas diodes nozÄ«mÄ«gākā bita vērtÄ«bu, velciet DCK uz augÅ”u un uz leju; iestatiet DAI ievadi uz nākamā bita vērtÄ«bu, velciet DCK; un tā tālāk, lÄ«dz visi biti ir pārsÅ«tÄ«ti (iegriezies), pēc kura velkam LAT. To var izdarÄ«t manuāli (bit-sprādziens), taču labāk ir izmantot Ä«paÅ”i Å”im nolÅ«kam pielāgotu SPI interfeisu, jo tas ir pieejams mÅ«su STM32 divos eksemplāros.

Zilā tablete STM32F103

Ievads: STM32 kontrolieri ir daudz sarežģītāki nekā Atmega328, nekā varētu Ŕķist biedējoÅ”i. Turklāt enerÄ£ijas taupÄ«Å”anas nolÅ«kos gandrÄ«z visas perifērijas ierÄ«ces sākumā tiek izslēgtas, un pulksteņa frekvence ir 8 MHz no iekŔējā avota. Par laimi, STM programmētāji uzrakstÄ«ja kodu, kas nodroÅ”ina mikroshēmu lÄ«dz ā€œaprēķinātajamā€ 72 MHz, un visu man zināmo IDE autori to iekļāva inicializācijas procedÅ«rā, tāpēc mums nav nepiecieÅ”ams pulkstenis (bet jÅ«s varat, ja jÅ«s patieŔām vēlaties). Bet jums bÅ«s jāieslēdz perifērijas ierÄ«ces.

Dokumentācija: Blue Pill ir aprīkota ar populāro STM32F103C8T6 mikroshēmu, tam ir divi noderīgi dokumenti:

Datu lapā mūs varētu interesēt:

  • Pinouts ā€“ skaidu pinouts ā€“ gadÄ«jumā, ja nolemjam dēļus izgatavot paÅ”i;
  • Memory Map ā€“ atmiņas karte konkrētai mikroshēmai. Uzziņu rokasgrāmatā ir karte visai lÄ«nijai, un tajā ir minēti reÄ£istri, kuru mÅ«su rÄ«cÄ«bā nav.
  • Pin Definition tabula ā€“ uzskaita tapu galvenās un alternatÄ«vās funkcijas; ā€œzilajai tableteiā€ internetā var atrast ērtākus attēlus ar tapu sarakstu un to funkcijām. Tāpēc mēs nekavējoties googlē Blue Pill pinout un paturam Å”o attēlu pie rokas:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
NB: bildē no interneta bija kļūda, kas tika atzÄ«mēta komentāros, paldies par to. Bilde ir nomainÄ«ta, bet Ŕī ir mācÄ«ba - labāk pārbaudÄ«t informāciju nevis no datu lapām.

Mēs noņemam datu lapu, atveram uzziņu rokasgrāmatu un turpmāk izmantojam tikai to.
ProcedÅ«ra: nodarbojamies ar standarta ievadi/izvadi, konfigurējam SPI, ieslēdzam nepiecieÅ”amās perifērijas ierÄ«ces.

Ieejas izejas

Atmega328 I/O ir ieviests ārkārtÄ«gi vienkārÅ”i, tāpēc STM32 iespēju pārpilnÄ«ba var radÄ«t neskaidrÄ«bas. Tagad mums ir vajadzÄ«gi tikai secinājumi, bet pat tiem ir četras iespējas:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
atvērta noteka, push-pull, alternatīva push-pull, alternatīva atvērta noteka

"Vilkt stumt" (stumt vilkt) ir parasta Arduino izvade, tapa var iegÅ«t vērtÄ«bu HIGH vai LOW. Bet ar "atvērto noteku" ir grÅ«tÄ«bas, lai gan patiesÄ«bā Å”eit viss ir vienkārÅ”i:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Izvades konfigurācija / ja ports ir pieŔķirts izvadei: / iespējots izvades buferis: / ā€“ atvērts iztukÅ”oÅ”anas režīms: ā€œ0ā€ izvades reÄ£istrā iespējo N-MOS, ā€œ1ā€ izvades reÄ£istrā atstāj portu Hi-Z režīmā ( P-MOS nav aktivizēts ) / ā€“ push-pull režīms: ā€œ0ā€ izejas reÄ£istrā aktivizē N-MOS, ā€œ1ā€ izvades reÄ£istrā aktivizē P-MOS.

Visas atŔķirÄ«bas starp atvērtu kanalizāciju (atvērta kanalizācija) no ā€œpush-pullā€ (stumt vilkt) ir tas, ka pirmajā tapā nevar pieņemt HIGH stāvokli: ierakstot to izvades reÄ£istrā, tas pāriet augstas pretestÄ«bas režīmā (augstas pretestÄ«bas, Sveiks-Z). Ierakstot nulli, tapa uzvedas vienādi abos režīmos gan loÄ£iski, gan elektriski.

Parastā izvades režīmā tapa vienkārÅ”i pārraida izvades reÄ£istra saturu. "AlternatÄ«vā" to kontrolē attiecÄ«gās perifērijas ierÄ«ces (sk. 9.1.4):

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Ja porta bits ir konfigurēts kā alternatīvas funkcijas tapa, tapu reģistrs ir atspējots un tapa ir savienota ar perifērijas tapu.

Katra tapa alternatīva funkcionalitāte ir aprakstīta PIN definīcijas Datu lapa atrodas uz lejupielādētā attēla. Uz jautājumu, ko darīt, ja tapai ir vairākas alternatīvas funkcijas, atbildi sniedz zemsvītras piezīme datu lapā:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Ja vairākas perifērijas ierÄ«ces izmanto vienu tapu, lai izvairÄ«tos no konflikta starp alternatÄ«vām funkcijām, vienlaikus jāizmanto tikai viena perifērijas ierÄ«ce, kas tiek pārslēgta, izmantojot perifērijas pulksteņa iespējoÅ”anas bitu (attiecÄ«gajā RCC reÄ£istrā).

Visbeidzot, tapām izvades režīmā ir arÄ« pulksteņa ātrums. Å Ä« ir vēl viena enerÄ£ijas taupÄ«Å”anas funkcija; mÅ«su gadÄ«jumā mēs to vienkārÅ”i iestatām uz maksimumu un aizmirstam.

Tātad: mēs izmantojam SPI, kas nozÄ«mē, ka diviem kontaktiem (ar datiem un ar pulksteņa signālu) jābÅ«t "alternatÄ«vai push-pull funkcijai", bet vēl vienam (LAT) jābÅ«t "parastam push-pull". Bet pirms to pieŔķirÅ”anas, tiksim galā ar SPI.

SPI

Vēl viena neliela izglītības programma

SPI jeb Serial Peripheral Interface (serial peripheral Interface) ir vienkārÅ”s un ļoti efektÄ«vs interfeiss MK savienoÅ”anai ar citiem MK un ārpasauli kopumā. Tās darbÄ«bas princips jau ir aprakstÄ«ts iepriekÅ”, kur par Ä·Ä«nieÅ”u LED draiveri (atsauces rokasgrāmatā skatiet 25. sadaļu). SPI var darboties galvenā (ā€œmasterā€) un slave (ā€œslaveā€) režīmā. SPI ir četri pamata kanāli, no kuriem ne visus var izmantot:

  • MOSI, galvenā izeja / vergu ieeja: Ŕī tapa pārsÅ«ta datus galvenajā režīmā un saņem datus pakārtotā režīmā;
  • MISO, galvenā ieeja / vergu izeja: gluži pretēji, tas saņem galvenajā un pārraida vergu;
  • SCK, Serial Clock: iestata datu pārraides frekvenci galvenajā ierÄ«cē vai saņem pulksteņa signālu slave. BÅ«tÄ«bā sitienu sitieni;
  • SS, Slave Select: ar Ŕī kanāla palÄ«dzÄ«bu vergs zina, ka no viņa kaut ko vēlas. Uz STM32 to sauc par NSS, kur N = negatÄ«vs, t.i. kontrolieris kļūst par vergu, ja Å”ajā kanālā ir zemējums. Tas labi apvienojas ar Open Drain Output režīmu, taču tas ir cits stāsts.

Tāpat kā viss pārējais, SPI STM32 ir bagāta ar funkcionalitāti, kas padara to nedaudz grÅ«ti saprotamu. Piemēram, tas var strādāt ne tikai ar SPI, bet arÄ« ar I2S interfeisu, un dokumentācijā to apraksti ir sajaukti, ir nepiecieÅ”ams savlaicÄ«gi nogriezt lieko. MÅ«su uzdevums ir ārkārtÄ«gi vienkārÅ”s: mums vienkārÅ”i jānosÅ«ta dati, izmantojot tikai MOSI un SCK. Mēs pārejam uz sadaļu 25.3.4 (pusdupleksā komunikācija, pusdupleksā komunikācija), kur atrodam 1 pulkstenis un 1 vienvirziena datu vads (1 pulksteņa signāls un 1 vienvirziena datu straume):

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Å ajā režīmā lietojumprogramma izmanto SPI tikai pārraides vai tikai saņemÅ”anas režīmā. / Tikai pārraides režīms ir lÄ«dzÄ«gs dupleksajam režīmam: dati tiek pārsÅ«tÄ«ti uz pārraides tapu (MOSI galvenajā režīmā vai MISO pakārtotā režīmā), un saņemÅ”anas tapu (attiecÄ«gi MISO vai MOSI) var izmantot kā parasto I/O tapu. . Å ajā gadÄ«jumā lietojumprogrammai ir tikai jāignorē Rx buferis (ja tas tiek nolasÄ«ts, tur netiks pārsÅ«tÄ«ti dati).

Lieliski, MISO pin ir brÄ«vs, pievienosim tam LAT signālu. ApskatÄ«sim Slave Select, kuru uz STM32 var vadÄ«t programmatiski, kas ir ārkārtÄ«gi ērti. Tāda paÅ”a nosaukuma rindkopu lasām sadaļā 25.3.1 SPI VispārÄ«gs apraksts:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
ProgrammatÅ«ras vadÄ«bas NSS (SSM = 1) / Slave atlases informācija ir ietverta SPI_CR1 reÄ£istra SSI bitā. Ārējais NSS pin paliek brÄ«vs citām lietojumprogrammu vajadzÄ«bām.

Laiks rakstīt uz reģistriem. Es nolēmu izmantot SPI2, meklēt tā bāzes adresi datu lapā - sadaļā 3.3 Atmiņas karte:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Nu, sāksim:

#define _SPI2_(mem_offset) (*(volatile uint32_t *)(0x40003800 + (mem_offset)))

Atveriet sadaļu 25.3.3 ar paÅ”saprotamu nosaukumu ā€œSPI konfigurÄ“Å”ana galvenajā režīmāā€:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

1. SPI_CR2 reģistrā iestatiet sērijas pulksteņa frekvenci ar bitiem BR[0:1].

ReÄ£istri ir apkopoti tāda paÅ”a nosaukuma uzziņu rokasgrāmatas sadaļā. Adreses maiņa (Adreses nobÄ«de) CR1 ā€” 0x00, pēc noklusējuma visi biti ir notÄ«rÄ«ti (AtiestatÄ«t vērtÄ«bu 0x0000):

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

BR biti iestata kontroliera pulksteņa dalītāju, tādējādi nosakot frekvenci, kādā SPI darbosies. Mūsu STM32 frekvence būs 72 MHz, LED draiveris saskaņā ar tā datu lapu darbojas ar frekvenci līdz 25 MHz, tāpēc jādala ar četri (BR[2:0] = 001).

#define _SPI_CR1 0x00

#define BR_0        0x0008
#define BR_1        0x0010
#define BR_2        0x0020

_SPI2_ (_SPI_CR1) |= BR_0;// pclk/4

2. Iestatiet CPOL un CPHA bitus, lai definētu saistÄ«bu starp datu pārsÅ«tÄ«Å”anu un sērijas pulksteņa laiku (skatiet diagrammu 240. lpp.)

Tā kā mēs Å”eit lasām datu lapu, nevis skatāmies shēmas, sÄ«kāk apskatÄ«sim CPOL un CPHA bitu teksta aprakstu 704. lappusē (SPI vispārÄ«gais apraksts):

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Pulksteņa fāze un polaritāte
Izmantojot SPI_CR1 reģistra CPOL un CPHA bitus, varat programmatiski atlasīt četras laika attiecības. CPOL (pulksteņa polaritātes) bits kontrolē pulksteņa signāla stāvokli, kad netiek pārsūtīti dati. Šis bits kontrolē galveno un pakārtoto režīmu. Ja CPOL ir atiestatīts, atpūtas režīmā SCK tapa ir zema. Ja ir iestatīts CPOL bits, atpūtas režīma laikā SCK tapa ir augsta.
Kad ir iestatÄ«ts CPHA (pulksteņa fāzes) bits, augstais bitu slazds ir SCK signāla otrā mala (krÄ«t, ja CPOL ir skaidrs, palielinās, ja ir iestatÄ«ts CPOL). Dati tiek uztverti ar otro pulksteņa signāla izmaiņu. Ja CPHA bits ir tÄ«rs, augstais bitu slazds ir SCK signāla augoŔā mala (krÄ«toŔā mala, ja ir iestatÄ«ta CPOL, augoŔā mala, ja CPOL ir notÄ«rÄ«ta). Dati tiek uztverti pie pirmās pulksteņa signāla maiņas.

ApgÅ«stot Ŕīs zināŔanas, mēs nonākam pie secinājuma, ka abiem bitiem jāpaliek nullēm, jo Mēs vēlamies, lai SCK signāls paliktu zems, kad tas netiek izmantots, un dati tiktu pārraidÄ«ti uz impulsa pieaugoŔās malas (sk. Rising Edge DM634 datu lapā).

Starp citu, Å”eit mēs pirmo reizi saskārāmies ar vārdu krājuma iezÄ«mi ST datu lapās: tajās ir rakstÄ«ta frāze ā€œatiestatÄ«t bitu uz nulliā€. lai mazliet atiestatÄ«tuUn ne lai mazliet notÄ«rÄ«tu, piemēram, Atmega.

3. Iestatiet DFF bitu, lai noteiktu, vai datu bloks ir 8 bitu vai 16 bitu formātā

Es Ä«paÅ”i paņēmu 16 bitu DM634, lai netraucētu pārsÅ«tÄ«t 12 bitu PWM datus, piemēram, DM633. Ir lietderÄ«gi iestatÄ«t DFF uz vienu:

#define DFF         0x0800

_SPI2_ (_SPI_CR1) |= DFF; // 16-bit mode

4. Konfigurējiet LSBFIRST bitu SPI_CR1 reģistrā, lai noteiktu bloka formātu

LSBFIRST, kā norāda nosaukums, vispirms konfigurē pārraidi ar vismazāko bitu. Bet DM634 vēlas saņemt datus, sākot no visnozīmīgākā bita. Tāpēc mēs atstājam to atiestatīt.

5. Aparatūras režīmā, ja ir nepiecieŔama ievade no NSS kontakta, visas baitu pārsūtīŔanas secības laikā uz NSS kontakta ievadiet augstu signālu. NSS programmatūras režīmā iestatiet SSM un SSI bitus SPI_CR1 reģistrā. Ja NSS tapu izmanto kā izvadi, ir jāiestata tikai SSOE bits.

Instalējiet SSM un SSI, lai aizmirstu par NSS aparatūras režīmu:

#define SSI         0x0100
#define SSM         0x0200

_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high

6. MSTR un SPE biti ir jāiestata (tie paliek iestatÄ«ti tikai tad, ja NSS signāls ir augsts)

Faktiski ar Å”iem bitiem mēs apzÄ«mējam savu SPI kā galveno un ieslēdzam to:

#define MSTR        0x0004
#define SPE         0x0040

_SPI2_ (_SPI_CR1) |= MSTR; //SPI master
//ŠŗŠ¾Š³Š“Š° Š²ŃŠµ Š³Š¾Ń‚Š¾Š²Š¾, Š²ŠŗŠ»ŃŽŃ‡Š°ŠµŠ¼ SPI
_SPI2_ (_SPI_CR1) |= SPE;

SPI ir konfigurēts, uzreiz rakstÄ«sim funkcijas, kas sÅ«ta baitus draiverim. Turpināt lasÄ«t 25.3.3 ā€œSPI konfigurÄ“Å”ana galvenajā režīmāā€:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Datu pārsūtīŔanas pasūtījums
PārsūtīŔana sākas, kad baits tiek ierakstīts Tx buferī.
Datu baits tiek ielādēts maiņu reÄ£istrā plkst paralēli režīmā (no iekŔējās kopnes) pirmā bita pārraides laikā, pēc kura tas tiek pārsÅ«tÄ«ts uz secÄ«gi MOSI tapas režīms, pirmais vai pēdējais bits uz priekÅ”u atkarÄ«bā no LSBFIRST bita iestatÄ«juma CPI_CR1 reÄ£istrā. TXE karodziņŔ tiek iestatÄ«ts pēc datu pārraides no Tx bufera uz maiņu reÄ£istru, kā arÄ« Ä£enerē pārtraukumu, ja ir iestatÄ«ts TXEIE bits CPI_CR1 reÄ£istrā.

Es izcēlu dažus vārdus tulkojumā, lai pievērstu uzmanÄ«bu vienai SPI ievieÅ”anas iezÄ«mei STM kontrolleros. Uz Atmega TXE karogs (Tx tukÅ”s, Tx ir tukÅ”s un gatavs datu saņemÅ”anai) tiek iestatÄ«ts tikai pēc visa baita nosÅ«tÄ«Å”anas uz āru. Un Å”eit Å”is karogs tiek iestatÄ«ts pēc tam, kad baits ir ievietots iekŔējā maiņu reÄ£istrā. Tā kā tas tiek virzÄ«ts tur ar visiem bitiem vienlaikus (paralēli), un pēc tam dati tiek pārsÅ«tÄ«ti secÄ«gi, TXE tiek iestatÄ«ts pirms baita pilnÄ«gas nosÅ«tÄ«Å”anas. Tas ir svarÄ«gi, jo mÅ«su LED draivera gadÄ«jumā pēc nosÅ«tÄ«Å”anas mums ir jāizvelk LAT tapa viss datus, t.i. Ar TXE karogu vien mums nepietiks.

Tas nozÄ«mē, ka mums ir vajadzÄ«gs cits karogs. ApskatÄ«sim 25.3.7. ā€” ā€œStatusa karogiā€:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
<ā€¦>
2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
AIZņemts karogs
BSY karogu iestata un notÄ«ra aparatÅ«ra (rakstÄ«Å”anai tajā nav nekādas ietekmes). BSY karodziņŔ norāda SPI komunikācijas slāņa stāvokli.
Tas tiek atiestatīts:
kad pārsÅ«tÄ«Å”ana ir pabeigta (izņemot galvenajā režīmā, ja pārsÅ«tÄ«Å”ana ir nepārtraukta)
kad SPI ir atspējots
kad rodas galvenā režīma kļūda (MODF=1)
Ja pārsÅ«tÄ«Å”ana nav nepārtraukta, BSY karodziņŔ tiek notÄ«rÄ«ts starp katru datu pārsÅ«tÄ«Å”anu

Labi, tas noderēs. Noskaidrosim, kur atrodas Tx buferis. Lai to izdarÄ«tu, izlasiet ā€œSPI datu reÄ£istrsā€:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Biti 15:0 DR[15:0] Datu reģistrs
Saņemtie vai pārsūtāmie dati.
Datu reÄ£istrs ir sadalÄ«ts divos buferos - viens rakstÄ«Å”anai (pārsÅ«tÄ«Å”anas buferis) un viens lasÄ«Å”anai (saņemÅ”anas buferis). Ierakstot datu reÄ£istrā, tiek ierakstÄ«ts Tx buferis, un nolasot no datu reÄ£istra, tiks atgriezta vērtÄ«ba, kas atrodas Rx buferÄ«.

Un statusa reģistrs, kurā ir atrodami karogi TXE un BSY:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Mēs rakstām:

#define _SPI_DR  0x0C
#define _SPI_SR  0x08

#define BSY         0x0080
#define TXE         0x0002

void dm_shift16(uint16_t value)
{
    _SPI2_(_SPI_DR) = value; //send 2 bytes
    while (!(_SPI2_(_SPI_SR) & TXE)); //wait until they're sent
}

Tā kā mums ir jāpārraida 16 reizes divi baiti, atkarÄ«bā no LED draivera izvadu skaita, apmēram Ŕādi:

void sendLEDdata()
{
    LAT_low();
    uint8_t k = 16;
    do
    {   k--;
        dm_shift16(leds[k]);
    } while (k);

    while (_SPI2_(_SPI_SR) & BSY); // finish transmission

    LAT_pulse();
}

Taču mēs vēl nezinām, kā izvilkt LAT tapu, tāpēc atgriezīsimies pie I/O.

Piespraudes pieŔķirŔana

STM32F1 reÄ£istri, kas ir atbildÄ«gi par tapu stāvokli, ir diezgan neparasti. Skaidrs, ka to ir vairāk nekā Atmega, taču tie arÄ« atŔķiras no citiem STM čipiem. 9.1. sadaļa GPIO vispārÄ«gs apraksts:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Katrs no vispārējas nozÄ«mes I/O portiem (GPIO) ir divi 32 bitu konfigurācijas reÄ£istri (GPIOx_CRL un GPIOx_CRH), divi 32 bitu datu reÄ£istri (GPIOx_IDR un GPIOx_ODR), 32 bitu iestatÄ«Å”anas/atiestatÄ«Å”anas reÄ£istrs (GPIOx_BSRR), 16 bitu atiestatÄ«Å”anas reÄ£istrs (GPIOx_BRR) un 32 bitu reÄ£istrs. bitu bloÄ·Ä“Å”anas reÄ£istrs (GPIOx_LCKR).

Pirmie divi reÄ£istri ir neparasti un arÄ« diezgan neērti, jo 16 portu tapas ir izkaisÄ«tas pa tiem formātā ā€œÄetri biti uz brāliā€. Tie. tapas no nulles lÄ«dz septiņām ir CRL, bet pārējās ir CRH. Tajā paŔā laikā atlikuÅ”ajos reÄ£istros veiksmÄ«gi ir visu porta tapu biti - bieži vien paliek puse ā€œrezervētaā€.

VienkārŔības labad sāksim no saraksta beigām.

Mums nav nepiecieŔams bloķēŔanas reģistrs.

IestatÄ«Å”anas un atiestatÄ«Å”anas reÄ£istri ir diezgan smieklÄ«gi ar to, ka tie daļēji dublē viens otru: visu var rakstÄ«t tikai BSRR, kur augstākie 16 biti atiestatÄ«s tapu uz nulli, bet zemākie tiks iestatÄ«ti uz 1, vai arÄ« jÅ«s varat arÄ« izmantojiet BRR, kura apakŔējie 16 biti atiestata tikai tapu . Man patÄ«k otrais variants. Å ie reÄ£istri ir svarÄ«gi, jo tie nodroÅ”ina atomu piekļuvi tapām:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Atomu iestatīŔana vai atiestatīŔana
Programmējot GPIOx_ODR bitu lÄ«menÄ«, pārtraukumi nav jāatspējo: vienu vai vairākus bitus var mainÄ«t ar vienu atomu rakstÄ«Å”anas operāciju APB2. To panāk, maināmā bita iestatÄ«Å”anas/atiestatÄ«Å”anas reÄ£istrā (GPIOx_BSRR vai, tikai atiestatÄ«Å”anai, GPIOx_BRR), ierakstot "1". Citi biti paliks nemainÄ«gi.

Datu reÄ£istriem ir diezgan paÅ”saprotami nosaukumi - IDR = ievade Virzienu reÄ£istrs, ievades reÄ£istrs; ODR = izvade Virzienu reÄ£istrs, izvades reÄ£istrs. PaÅ”reizējā projektā tie mums nebÅ«s vajadzÄ«gi.

Un visbeidzot, kontroles reģistri. Tā kā mūs interesē otrie SPI tapas, proti, PB13, PB14 un PB15, mēs nekavējoties skatāmies uz CRH:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Un mēs redzam, ka mums būs kaut kas jāraksta bitos no 20 līdz 31.

Mēs jau iepriekÅ” esam izdomājuÅ”i, ko mēs vēlamies no tapām, tāpēc Å”eit es iztikÅ”u bez ekrānuzņēmuma, teikÅ”u tikai to, ka MODE norāda virzienu (ievade, ja abi biti ir iestatÄ«ti uz 0) un tapas ātrumu (mums vajag 50MHz, t.i. abas tapas uz ā€œ1ā€), un CNF iestata režīmu: parastais ā€œpush-pullā€ ā€“ 00, ā€œalternatÄ«vaisā€ ā€“ 10. Pēc noklusējuma, kā redzams iepriekÅ”, visām tapām ir treÅ”ais bits no apakÅ”as (CNF0), tas iestata tos režīmā peldoŔā ievade.

Tā kā es plānoju ar Å”o mikroshēmu darÄ«t kaut ko citu, vienkārŔības labad esmu definējis visas iespējamās MODE un CNF vērtÄ«bas gan apakŔējam, gan augŔējam vadÄ«bas reÄ£istram.

Kaut kā Ŕādi

#define CNF0_0 0x00000004
#define CNF0_1 0x00000008
#define CNF1_0 0x00000040
#define CNF1_1 0x00000080
#define CNF2_0 0x00000400
#define CNF2_1 0x00000800
#define CNF3_0 0x00004000
#define CNF3_1 0x00008000
#define CNF4_0 0x00040000
#define CNF4_1 0x00080000
#define CNF5_0 0x00400000
#define CNF5_1 0x00800000
#define CNF6_0 0x04000000
#define CNF6_1 0x08000000
#define CNF7_0 0x40000000
#define CNF7_1 0x80000000
#define CNF8_0 0x00000004
#define CNF8_1 0x00000008
#define CNF9_0 0x00000040
#define CNF9_1 0x00000080
#define CNF10_0 0x00000400
#define CNF10_1 0x00000800
#define CNF11_0 0x00004000
#define CNF11_1 0x00008000
#define CNF12_0 0x00040000
#define CNF12_1 0x00080000
#define CNF13_0 0x00400000
#define CNF13_1 0x00800000
#define CNF14_0 0x04000000
#define CNF14_1 0x08000000
#define CNF15_0 0x40000000
#define CNF15_1 0x80000000

#define MODE0_0 0x00000001
#define MODE0_1 0x00000002
#define MODE1_0 0x00000010
#define MODE1_1 0x00000020
#define MODE2_0 0x00000100
#define MODE2_1 0x00000200
#define MODE3_0 0x00001000
#define MODE3_1 0x00002000
#define MODE4_0 0x00010000
#define MODE4_1 0x00020000
#define MODE5_0 0x00100000
#define MODE5_1 0x00200000
#define MODE6_0 0x01000000
#define MODE6_1 0x02000000
#define MODE7_0 0x10000000
#define MODE7_1 0x20000000
#define MODE8_0 0x00000001
#define MODE8_1 0x00000002
#define MODE9_0 0x00000010
#define MODE9_1 0x00000020
#define MODE10_0 0x00000100
#define MODE10_1 0x00000200
#define MODE11_0 0x00001000
#define MODE11_1 0x00002000
#define MODE12_0 0x00010000
#define MODE12_1 0x00020000
#define MODE13_0 0x00100000
#define MODE13_1 0x00200000
#define MODE14_0 0x01000000
#define MODE14_1 0x02000000
#define MODE15_0 0x10000000
#define MODE15_1 0x20000000

MÅ«su tapas atrodas uz porta B (bāzes adrese ā€“ 0x40010C00), kods:

#define _PORTB_(mem_offset) (*(volatile uint32_t *)(0x40010C00 + (mem_offset)))

#define _BRR  0x14
#define _BSRR 0x10
#define _CRL  0x00
#define _CRH  0x04

//ŠøсŠæŠ¾Š»ŃŒŠ·ŃƒŠµŠ¼ стŠ°Š½Š“Š°Ń€Ń‚Š½Ń‹Š¹ SPI2: MOSI Š½Š° B15, CLK Š½Š° B13
//LAT Šæусть Š±ŃƒŠ“ŠµŃ‚ Š½Š° Š½ŠµŠøсŠæŠ¾Š»ŃŒŠ·ŃƒŠµŠ¼Š¾Š¼ MISO ā€“ B14

//Š¾Ń‡ŠøщŠ°ŠµŠ¼ Š“ŠµŃ„Š¾Š»Ń‚Š½Ń‹Š¹ Š±Šøт, Š¾Š½ Š½Š°Š¼ тŠ¾Ń‡Š½Š¾ Š½Šµ Š½ŃƒŠ¶ŠµŠ½
_PORTB_ (_CRH) &= ~(CNF15_0 | CNF14_0 | CNF13_0 | CNF12_0);

//Š°Š»ŃŒŃ‚ŠµŃ€Š½Š°Ń‚ŠøŠ²Š½Ń‹Šµ фуŠ½ŠŗцŠøŠø Š“Š»Ń MOSI Šø SCK
_PORTB_ (_CRH) |= CNF15_1 | CNF13_1;

//50 ŠœŠ“ц, MODE = 11
_PORTB_ (_CRH) |= MODE15_1 | MODE15_0 | MODE14_1 | MODE14_0 | MODE13_1 | MODE13_0;

Un attiecīgi jūs varat rakstīt definīcijas LAT, kuras raustīs BRR un BSRR reģistri:

/*** LAT pulse ā€“ high, then low */
#define LAT_pulse() _PORTB_(_BSRR) = (1<<14); _PORTB_(_BRR) = (1<<14)

#define LAT_low() _PORTB_(_BRR) = (1<<14)

(LAT_zems tikai pēc inerces, tā vienmēr ir bijis, lai paliek)

Tagad viss ir lieliski, bet tas nedarbojas. Tā kā Å”is ir STM32, tie ietaupa elektroenerÄ£iju, kas nozÄ«mē, ka jums ir jāiespējo nepiecieÅ”amo perifērijas ierīču pulksteņa funkcija.

Ieslēdziet pulksteni

Pulkstenis, kas pazÄ«stams arÄ« kā pulkstenis, ir atbildÄ«gs par pulksteni. Un jau varējām pamanÄ«t saÄ«sinājumu RCC. Mēs to meklējam dokumentācijā: Ŕī ir Reset un Clock Control.

Kā jau minēts iepriekÅ”, par laimi, visgrÅ«tāko pulksteņa tēmas daļu mums veica cilvēki no STM, par ko mēs viņiem ļoti pateicamies (vēlreiz iedoÅ”u saiti uz Di Halta vietne, lai bÅ«tu skaidrs, cik tas ir mulsinoÅ”i). Mums ir nepiecieÅ”ami tikai reÄ£istri, kas ir atbildÄ«gi par perifērijas pulksteņa iespējoÅ”anu (Peripheral Clock Enable Registers). Pirmkārt, atradÄ«sim RCC bāzes adresi, tā atrodas ā€œMemory Mapā€ paŔā sākumā:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

#define _RCC_(mem_offset) (*(volatile uint32_t *)(0x40021000 + (mem_offset)))

Un tad vai nu noklikŔķiniet uz saites, kur mēģināt kaut ko atrast plāksnē, vai, daudz labāk, izlasiet iespējojoÅ”o reÄ£istru aprakstus no sadaļām par iespējot reÄ£istrus. Kur mēs atradÄ«sim RCC_APB1ENR un RCC_APB2ENR:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Un attiecīgi tajos ir biti, kas ietver SPI2, IOPB (I/O ports B) un alternatīvo funkciju (AFIO) taktiku.

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

#define IOPBEN 0x0008
#define SPI2EN 0x4000
#define AFIOEN 0x0001

//Š²ŠŗŠ»ŃŽŃ‡Š°ŠµŠ¼ тŠ°ŠŗтŠøрŠ¾Š²Š°Š½ŠøŠµ ŠæŠ¾Ń€Ń‚Š° B Šø Š°Š»ŃŒŃ‚. фуŠ½ŠŗцŠøŠ¹
_RCC_(_APB2ENR) |= IOPBEN | AFIOEN;

//Š²ŠŗŠ»ŃŽŃ‡Š°ŠµŠ¼  тŠ°ŠŗтŠøрŠ¾Š²Š°Š½ŠøŠµ SPI2
_RCC_(_APB1ENR) |= SPI2EN;

Galīgo kodu var atrast Ŕeit.

Ja ir iespēja un vēlme pārbaudÄ«t, tad pieslēdz DM634 Ŕādi: DAI pie PB15, DCK uz PB13, LAT pie PB14. Mēs barojam draiveri no 5 voltiem, neaizmirstiet pieslēgt zemējumu.

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

STM8 PWM

PWM uz STM8

Kad es tikai plānoju Å”o rakstu, es nolēmu, piemēram, mēģināt apgÅ«t kādu nepazÄ«stama mikroshēmas funkcionalitāti, izmantojot tikai datu lapu, lai es netiktu pie kurpnieka bez zābakiem. STM8 bija ideāli piemērots Å”ai lomai: pirmkārt, man bija pāris Ä·Ä«nieÅ”u dēļi ar STM8S103, otrkārt, tas nav Ä«paÅ”i populārs, un tāpēc kārdinājums lasÄ«t un atrast risinājumu internetā balstās tieÅ”i uz Å”o risinājumu trÅ«kumu.

Mikroshēmai arÄ« ir datu lapas Šø rokasgrāmata RM0016, pirmajā ir pinout un reÄ£istra adreses, otrajā - viss pārējais. STM8 ir ieprogrammēts C valodā briesmÄ«gā IDE ST vizuālā attÄ«stÄ«ba.

Pulkstenis un I/O

Pēc noklusējuma STM8 darbojas ar 2 MHz frekvenci, tas nekavējoties jālabo.

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
HSI (ātrgaitas iekŔējais) pulkstenis
HSI pulksteņa signāls tiek iegÅ«ts no iekŔēja 16 MHz RC oscilatora ar programmējamu dalÄ«tāju (no 1 lÄ«dz 8). Tas ir iestatÄ«ts pulksteņa dalÄ«tāju reÄ£istrā (CLK_CKDIVR).
Piezīme: sākumā HSI RC oscilators ar dalītāju 8 tiek izvēlēts kā galvenais pulksteņa signāla avots.

Datu lapā atrodam reÄ£istra adresi, refman aprakstu un redzam, ka reÄ£istrs ir jādzÄ“Å”:

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

Tā kā mēs palaidÄ«sim PWM un pievienosim gaismas diodes, apskatÄ«sim kontaktdakÅ”u:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Mikroshēma ir maza, daudzas funkcijas ir apturētas uz tām paŔām tapām. Tas, kas ir kvadrātiekavās, ir ā€œalternatÄ«va funkcionalitāteā€, to pārslēdz ā€œopciju baitiā€ (opciju baiti) ā€“ kaut kas lÄ«dzÄ«gs Atmega droÅ”inātājiem. JÅ«s varat mainÄ«t to vērtÄ«bas programmētiski, bet tas nav nepiecieÅ”ams, jo Jaunā funkcionalitāte tiek aktivizēta tikai pēc pārstartÄ“Å”anas. VienkārŔāk ir izmantot ST Visual Programmer (lejupielādēts kopā ar Visual Develop), kas var mainÄ«t Å”os baitus. Spraude parāda, ka pirmā taimera CH1 un CH2 tapas ir paslēptas kvadrātiekavās; STVP ir jāiestata AFR1 un AFR0 biti, un otrs pārsÅ«tÄ«s arÄ« otrā taimera CH1 izvadi no PD4 uz PC5.

Tādējādi gaismas diodes vadīs 6 tapas: PC6, PC7 un PC3 pirmajam taimeram, PC5, PD3 un PA3 otrajam.

PaŔu I/O tapu iestatīŔana STM8 ir vienkārŔāka un loģiskāka nekā STM32:

  • pazÄ«stams no Atmega DDR datu virzienu reÄ£istra (Datu virzienu reÄ£istrs): 1 = izvade;
  • pirmais vadÄ«bas reÄ£istrs CR1, kad tas tiek izvadÄ«ts, iestata push-pull režīmu (1) vai atvērtu aizplÅ«Å”anu (0); tā kā gaismas diodes pievienoju mikroshēmai ar katodiem, tad Å”eit atstāju nulles;
  • otrais vadÄ«bas reÄ£istrs CR2, izejot, iestata takts frekvenci: 1 = 10 MHz

#define PA_DDR     *(volatile uint8_t *)0x005002
#define PA_CR2     *(volatile uint8_t *)0x005004
#define PD_DDR     *(volatile uint8_t *)0x005011
#define PD_CR2     *(volatile uint8_t *)0x005013
#define PC_DDR     *(volatile uint8_t *)0x00500C
#define PC_CR2     *(volatile uint8_t *)0x00500E

PA_DDR = (1<<3); //output
PA_CR2 |= (1<<3); //fast
PD_DDR = (1<<3); //output
PD_CR2 |= (1<<3); //fast
PC_DDR = ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //output
PC_CR2 |= ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //fast

PWM iestatījums

Vispirms definēsim terminus:

  • PWM frekvence ā€“ biežums, ar kādu taimeris tikŔķ;
  • Automātiskā pārlādÄ“Å”ana, AR ā€“ automātiski ielādējamā vērtÄ«ba, lÄ«dz kurai taimeris skaitÄ«s (impulsa periods);
  • Atjaunināt notikumu, UEV ā€“ notikums, kas notiek, kad taimeris ir ieskaitÄ«jis AR;
  • PWM darba cikls ā€“ PWM darba cikls, ko bieži sauc par ā€œdarba koeficientuā€;
  • Uzņemiet/salÄ«dziniet vērtÄ«bu ā€“ uztverÅ”anas/salÄ«dzināŔanas vērtÄ«ba, lÄ«dz kurai taimeris ir ieskaitÄ«jies kaut ko darÄ«s (PWM gadÄ«jumā tas invertē izejas signālu);
  • IepriekŔējas ielādes vērtÄ«ba ā€“ iepriekÅ” ielādēta vērtÄ«ba. SalÄ«dziniet vērtÄ«bu nevar mainÄ«ties, kamēr taimeris tikŔķ, pretējā gadÄ«jumā PWM cikls pārtrÅ«ks. Tāpēc jaunas pārraidÄ«tās vērtÄ«bas tiek ievietotas buferÄ« un izvilktas, kad taimeris sasniedz atpakaļskaitÄ«Å”anas beigas un tiek atiestatÄ«ts;
  • IzlÄ«dzināts ar malu Šø Centrā izlÄ«dzinātie režīmi ā€“ izlÄ«dzinājums gar robežu un centrā, tāds pats kā Atmel Ātra PWM Šø Fāzei pareizs PWM.
  • OCiREF, izvades salÄ«dzināŔanas atsauces signāls ā€“ atskaites izejas signāls, faktiski tas, kas parādās uz atbilstoŔās tapas PWM režīmā.

Kā jau redzams no pinout, diviem taimeriem ir PWM iespējas ā€“ pirmajam un otrajam. Abi ir 16 bitu, pirmajam ir daudz papildu funkciju (jo Ä«paÅ”i tas var skaitÄ«t gan uz augÅ”u, gan uz leju). Mums abiem jāstrādā vienādi, tāpēc nolēmu sākt ar acÄ«mredzami nabadzÄ«gāko otro, lai nejauÅ”i neizmantotu kaut ko, kas tur nav. Problēma ir tāda, ka visu taimeru PWM funkcionalitātes apraksts atsauces rokasgrāmatā ir sadaļā par pirmo taimeri (17.5.7 PWM režīms), tāpēc jums visu laiku ir jālēkā uz priekÅ”u un atpakaļ visā dokumentā.

PWM uz STM8 ir svarīga priekŔrocība salīdzinājumā ar PWM uz Atmega:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Robežas līdzināts PWM
Konta konfigurācija no apakŔas uz augŔu
ApakŔējā skaitÄ«Å”ana ir aktÄ«va, ja DIR bits TIM_CR1 reÄ£istrā ir notÄ«rÄ«ts
Piemērs
Piemērā tiek izmantots pirmais PWM režīms. PWM atsauces signāls OCiREF tiek turēts augstā līmenī, kamēr TIM1_CNT < TIM1_CCRI. Pretējā gadījumā tas aizņem zemu līmeni. Ja salīdzinājuma vērtība TIM1_CCRI reģistrā ir lielāka par automātiskās ielādes vērtību (TIM1_ARR reģistrs), OCiREF signāls tiek turēts uz 1. Ja salīdzināmā vērtība ir 0, OCiREF tiek turēts uz nulles....

STM8 taimeris laikā atjaunināŔanas pasākums vispirms pārbauda salÄ«dzināt vērtÄ«bu, un tikai pēc tam rada atsauces signālu. Atmega taimeris vispirms pieskrÅ«vē un pēc tam salÄ«dzina, kā rezultātā compare value == 0 izeja ir adata, ar kuru kaut kā jātiek galā (piemēram, programmatiski apgriežot loÄ£iku).

Tātad, ko mēs vēlamies darÄ«t: 8 bitu PWM (AR == 255), skaitot no apakÅ”as uz augÅ”u, lÄ«dzinājums gar robežu. Tā kā spuldzes ir savienotas ar mikroshēmu ar katodiem, PWM vajadzētu izvadÄ«t 0 (ieslēgts LED), lÄ«dz salÄ«dzināt vērtÄ«bu un 1 pēc.

Par dažiem jau esam lasÄ«juÅ”i PWM režīms, tāpēc mēs atrodam vajadzÄ«go otrā taimera reÄ£istru, atsauces rokasgrāmatā meklējot Å”o frāzi (18.6.8 - TIMx_CCMR1):

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
110: Pirmais PWM režīms ā€“ skaitot no apakÅ”as uz augÅ”u, pirmais kanāls ir aktÄ«vs, kamēr TIMx_CNT < TIMx_CCR1. Pretējā gadÄ«jumā pirmais kanāls ir neaktÄ«vs. [tālāk dokumentā ir kļūdaina copy-paste no 1. taimera] 111: Otrais PWM režīms ā€“ skaitot no apakÅ”as uz augÅ”u, pirmais kanāls ir neaktÄ«vs, kamēr TIMx_CNT < TIMx_CCR1. Pretējā gadÄ«jumā pirmais kanāls ir aktÄ«vs.

Tā kā gaismas diodes ir savienotas ar MK ar katodiem, mums der otrais režīms (arī pirmais, bet mēs to vēl nezinām).

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
3. bits OC1PE: iespējot 1. tapas priekÅ”ielādÄ“Å”anu
0: TIMx_CCR1 priekÅ”ielādÄ“Å”anas reÄ£istrs ir atspējots. JÅ«s varat rakstÄ«t uz TIMx_CCR1 jebkurā laikā. Jaunā vērtÄ«ba darbojas nekavējoties.
1: TIMx_CCR1 priekÅ”ielādÄ“Å”anas reÄ£istrs ir iespējots. LasÄ«Å”anas/rakstÄ«Å”anas operācijas piekļūst iepriekŔējas ielādes reÄ£istram. IepriekÅ” ielādētā vērtÄ«ba TIMx_CCR1 tiek ielādēta ēnu reÄ£istrā katra atjaunināŔanas notikuma laikā.
*PiezÄ«me. Lai PWM režīms darbotos pareizi, ir jāiespējo priekÅ”ielādÄ“Å”anas reÄ£istri. Tas nav nepiecieÅ”ams viena signāla režīmā (OPM bits ir iestatÄ«ts TIMx_CR1 reÄ£istrā).

Labi, ieslēdzam visu, kas nepiecieÅ”ams otrā taimera trim kanāliem:

#define TIM2_CCMR1 *(volatile uint8_t *)0x005307
#define TIM2_CCMR2 *(volatile uint8_t *)0x005308
#define TIM2_CCMR3 *(volatile uint8_t *)0x005309

#define PWM_MODE2   0x70 //PWM mode 2, 0b01110000
#define OCxPE       0x08 //preload enable

TIM2_CCMR1 = (PWM_MODE2 | OCxPE);
TIM2_CCMR2 = (PWM_MODE2 | OCxPE);
TIM2_CCMR3 = (PWM_MODE2 | OCxPE);

AR sastāv no diviem astoņu bitu reÄ£istriem, viss ir vienkārÅ”s:

#define TIM2_ARRH  *(volatile uint8_t *)0x00530F
#define TIM2_ARRL  *(volatile uint8_t *)0x005310

TIM2_ARRH = 0;
TIM2_ARRL = 255;

Otrais taimeris var skaitÄ«t tikai no apakÅ”as uz augÅ”u, lÄ«dzinājums gar robežu, nekas nav jāmaina. IestatÄ«sim frekvences dalÄ«tāju, piemēram, uz 256. Otrajam taimeram dalÄ«tājs ir iestatÄ«ts TIM2_PSCR reÄ£istrā un ir divu pakāpju:

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

Atliek tikai ieslēgt secinājumus un paÅ”u otro taimeri. Pirmo problēmu atrisina reÄ£istri Uzņemt/SalÄ«dzināt dot iespēju: pa tiem ir asimetriski izkaisÄ«ti divi, trÄ«s kanāli. Å eit arÄ« varam uzzināt, ka ir iespējams mainÄ«t signāla polaritāti, t.i. principā bija iespējams izmantot PWM režīmu 1. Mēs rakstām:

#define TIM2_CCER1 *(volatile uint8_t *)0x00530A
#define TIM2_CCER2 *(volatile uint8_t *)0x00530B

#define CC1E  (1<<0) // CCER1
#define CC2E  (1<<4) // CCER1
#define CC3E  (1<<0) // CCER2

TIM2_CCER1 = (CC1E | CC2E);
TIM2_CCER2 = CC3E;

Visbeidzot, mēs iedarbinām taimeri TIMx_CR1 reģistrā:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

UzrakstÄ«sim vienkārÅ”u AnalogWrite() analogu, kas salÄ«dzināŔanai pārsÅ«tÄ«s faktiskās vērtÄ«bas uz taimeri. ReÄ£istri nosaukti paredzami Uzņemt/salÄ«dzināt reÄ£istrus, katram kanālam ir divi no tiem: zemas kārtas 8 biti TIM2_CCRxL un augstākās kārtas TIM2_CCRxH. Tā kā mēs esam izveidojuÅ”i 8 bitu PWM, pietiek ar to, ka uzrakstiet tikai vismazāk nozÄ«mÄ«gus bitus:

#define TIM2_CCR1L *(volatile uint8_t *)0x005312
#define TIM2_CCR2L *(volatile uint8_t *)0x005314
#define TIM2_CCR3L *(volatile uint8_t *)0x005316

void setRGBled(uint8_t r, uint8_t g, uint8_t b)
{
    TIM2_CCR1L = r;
    TIM2_CCR2L = g;
    TIM2_CCR3L = b;
}

UzmanÄ«gs lasÄ«tājs pamanÄ«s, ka mums ir nedaudz bojāts PWM, kas nespēj nodroÅ”ināt 100% piepildÄ«jumu (maksimālajā vērtÄ«bā 255, signāls tiek apgriezts vienam taimera ciklam). Gaismas diodēm tas nav svarÄ«gi, un uzmanÄ«gs lasÄ«tājs jau var uzminēt, kā to salabot.

PWM uz otrā taimera darbojas, pāriesim pie pirmā.

Pirmajā taimerÄ« ir tieÅ”i tādi paÅ”i biti tajos paÅ”os reÄ£istros (tikai tie biti, kas palika ā€œrezervētiā€ otrajā taimeri, pirmajā tiek aktÄ«vi izmantoti visādām uzlabotām lietām). Tāpēc pietiek datu lapā atrast to paÅ”u reÄ£istru adreses un nokopēt kodu. Nu, mainiet frekvences dalÄ«tāja vērtÄ«bu, jo... pirmais taimeris vēlas saņemt nevis divu jaudu, bet precÄ«zu 16 bitu vērtÄ«bu divos reÄ£istros Prescaler High Šø Zems. Daram visu un... pirmais taimeris nestrādā. Kas noticis?

Problēmu var atrisināt tikai caurskatot visu sadaļu par taimera 1 vadÄ«bas reÄ£istriem, kur meklējam to, kura otrajam taimeram nav. Tur bÅ«s 17.7.30 Pārrāvuma reÄ£istrs (TIM1_BKR), kur ir Å”is bits:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Iespējot galveno izvadi

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

Tagad tas ir viss, kods tur.

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

STM8 multiplekss

MultipleksēŔana uz STM8

TreÅ”ais mini projekts ir savienot astoņas RGB gaismas diodes ar otro taimeri PWM režīmā un likt tiem parādÄ«t dažādas krāsas. Tas ir balstÄ«ts uz LED multipleksÄ“Å”anas koncepciju, proti, ja ļoti, ļoti ātri ieslēdzat un izslēdzat gaismas diodes, mums ŔķitÄ«s, ka tās pastāvÄ«gi deg (redzes noturÄ«ba, vizuālās uztveres inerce). Es reiz darÄ«ju kaut kas lÄ«dzÄ«gs Å”im vietnē Arduino.

Darba algoritms izskatās Ŕādi:

  • pieslēdza pirmās RGB gaismas diodes anodu;
  • iedegas to, nosÅ«tot nepiecieÅ”amos signālus uz katodiem;
  • gaidÄ«ja lÄ«dz PWM cikla beigām;
  • pievienoja otrās RGB gaismas diodes anodu;
  • aizdedzies to...

Nu utt. Protams, skaistai darbÄ«bai ir nepiecieÅ”ams pieslēgt anodu un vienlaikus ā€œaizdegtiesā€ LED. Nu vai gandrÄ«z. Jebkurā gadÄ«jumā mums ir jāraksta kods, kas izvadÄ«s vērtÄ«bas trÄ«s otrā taimera kanālos, mainÄ«s tās, kad tiek sasniegts UEV, un tajā paŔā laikā jāmaina paÅ”laik aktÄ«vais RGB LED.

Tā kā LED pārslēgÅ”ana ir automātiska, mums ir jāizveido "video atmiņa", no kuras pārtraukumu apstrādātājs saņems datus. Å is ir vienkārÅ”s masÄ«vs:

uint8_t colors[8][3];

Lai mainÄ«tu konkrētas gaismas diodes krāsu, pietiks ar vajadzÄ«gās vērtÄ«bas ierakstÄ«Å”anu Å”ajā masÄ«vā. Un mainÄ«gais bÅ«s atbildÄ«gs par aktÄ«vās gaismas diodes numuru

uint8_t cnt;

Demux

Pareizai multipleksÄ“Å”anai mums, dÄ«vainā kārtā, ir nepiecieÅ”ams CD74HC238 demultiplekseris. Demultiplekseris - mikroshēma, kas ievieÅ” operatoru aparatÅ«rā <<. Caur trim ievades tapām (biti 0, 1 un 2) mēs tam ievadām trÄ«s bitu skaitli X, un atbildot tas aktivizē izvades numuru (1<<X). AtlikuŔās mikroshēmas ievades tiek izmantotas, lai mērogotu visu dizainu. Å Ä« mikroshēma mums ir nepiecieÅ”ama ne tikai, lai samazinātu mikrokontrollera aizņemto tapu skaitu, bet arÄ« droŔībai - lai nejauÅ”i neiedegtu vairāk gaismas diodes nekā iespējams un nesadedzinātu MK. Mikroshēma maksā santÄ«mu, un tā vienmēr jāglabā mājas aptieciņā.

MÅ«su CD74HC238 bÅ«s atbildÄ«gs par sprieguma padevi vēlamās gaismas diodes anodam. PilnvērtÄ«gā multipleksā tas pievadÄ«tu spriegumu kolonnai caur P-MOSFET, bet Å”ajā demonstrācijā tas ir iespējams tieÅ”i, jo tas patērē 20 mA, saskaņā ar absolÅ«ti maksimālie vērtējumi datu lapā. No Datu lapa CD74HC238 mums ir nepiecieÅ”ami pinouts un Ŕī krāpÅ”anās lapa:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
H = augsts sprieguma lÄ«menis, L = zems sprieguma lÄ«menis, X ā€“ vienalga

Mēs savienojam E2 un E1 ar zemi, E3, A0, A1 un A3 ar STM5 tapām PD3, PC4, PC5 un PC8. Tā kā augstāk esoÅ”ajā tabulā ir gan zems, gan augsts lÄ«menis, mēs konfigurējam Ŕīs tapas kā stumÅ”anas tapas.

PWM

PWM otrajā taimerÄ« ir konfigurēts tāpat kā iepriekŔējā stāstā, ar divām atŔķirÄ«bām:

Pirmkārt, mums ir jāiespējo pārtraukums Atjaunināt notikumu (UEV), kas izsauks funkciju, kas pārslēdz aktÄ«vo LED. Tas tiek darÄ«ts, mainot bitu AtjaunināŔanas pārtraukuma iespējoÅ”ana reÄ£istrā ar izteiksmÄ«gu nosaukumu

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
Pārtraukt iespējot reģistru

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

Otrā atŔķirÄ«ba ir saistÄ«ta ar multipleksÄ“Å”anas fenomenu, piemēram, rēgoÅ”anās ā€“ diožu parazitārais spÄ«dums. MÅ«su gadÄ«jumā tas var parādÄ«ties tāpēc, ka taimeris, izraisÄ«jis UEV pārtraukumu, turpina atzÄ«mēties, un pārtraukumu apstrādātājam nav laika pārslēgt LED, pirms taimeris sāk kaut ko rakstÄ«t uz tapām. Lai to novērstu, jums bÅ«s jāapgriež loÄ£ika (0 = maksimālais spilgtums, 255 = nekas nedeg) un jāizvairās no ārkārtējām darba cikla vērtÄ«bām. Tie. nodroÅ”ināt, lai pēc UEV gaismas diodes pilnÄ«bā nodziest uz vienu PWM ciklu.

Polaritātes maiņa:

//set polarity 
    TIM2_CCER1 |= (CC1P | CC2P);
    TIM2_CCER2 |= CC3P;

Izvairieties no r, g un b iestatīŔanas uz 255 un atcerieties tos apgriezt, kad tos lietojat.

Pārtrauc

Pārtraukuma bÅ«tÄ«ba ir tāda, ka noteiktos apstākļos mikroshēma pārtrauc galvenās programmas izpildi un izsauc kādu ārēju funkciju. Pārtraukumi rodas ārējas vai iekŔējas ietekmes, tostarp taimera, dēļ.

Kad mēs pirmo reizi izveidojām projektu ST Visual Develop, papildus main.c mēs saņēmām logu ar noslēpumainu failu stm8_interrupt_vector.c, automātiski iekļauts projektā. Å ajā failā katram pārtraukumam tiek pieŔķirta funkcija NonHandledInterrupt. Mums ir jāsaista mÅ«su funkcija ar vēlamo pārtraukumu.

Datu lapā ir pārtraukumu vektoru tabula, kurā atrodam vajadzīgos vektorus:

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8
13 TIM2 atjaunināŔana/pārpilde
14 TIM2 uztverŔana/salīdzināŔana

Mums ir jāmaina LED UEV, tāpēc mums ir nepiecieÅ”ams pārtraukums Nr. 13.

Attiecīgi, pirmkārt, lietā stm8_interrupt_vector.c mainiet par pārtraukumu Nr. 13 (IRQ13) atbildīgās funkcijas noklusējuma nosaukumu uz savu:

{0x82, TIM2_Overflow}, /* irq13 */

Otrkārt, mums būs jāizveido fails main.h ar Ŕādu saturu:

#ifndef __MAIN_H
#define __MAIN_H

@far @interrupt void TIM2_Overflow (void);
#endif

Un visbeidzot ierakstiet Ŕo funkciju savā main.c:

@far @interrupt void TIM2_Overflow (void)
{
    PD_ODR &= ~(1<<5); // Š²Ń‹Ń€ŃƒŠ±Š°ŠµŠ¼ Š“ŠµŠ¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ¾Ń€
    PC_ODR = (cnt<<3); // Š·Š°ŠæŠøсыŠ²Š°ŠµŠ¼ Š² Š“ŠµŠ¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ¾Ń€ Š½Š¾Š²Š¾Šµ Š·Š½Š°Ń‡ŠµŠ½ŠøŠµ
    PD_ODR |= (1<<5); // Š²ŠŗŠ»ŃŽŃ‡Š°ŠµŠ¼ Š“ŠµŠ¼ŃƒŠ»ŃŒŃ‚ŠøŠæŠ»ŠµŠŗсŠ¾Ń€

    TIM2_SR1 = 0; // сŠ±Ń€Š°ŃŃ‹Š²Š°ŠµŠ¼ фŠ»Š°Š³ Update Interrupt Pending

    cnt++; 
    cnt &= 7; // Š“Š²ŠøŠ³Š°ŠµŠ¼ счŠµŃ‚чŠøŠŗ LED

    TIM2_CCR1L = ~colors[cnt][0]; // ŠæŠµŃ€ŠµŠ“Š°ŠµŠ¼ Š² Š±ŃƒŃ„ŠµŃ€ ŠøŠ½Š²ŠµŃ€Ń‚ŠøрŠ¾Š²Š°Š½Š½Ń‹Šµ Š·Š½Š°Ń‡ŠµŠ½Šøя
    TIM2_CCR2L = ~colors[cnt][1]; // Š“Š»Ń сŠ»ŠµŠ“ующŠµŠ³Š¾ цŠøŠŗŠ»Š° ŠØŠ˜Šœ
    TIM2_CCR3L = ~colors[cnt][2]; // 

    return;
}

Atliek tikai iespējot pārtraukumus. Tas tiek darÄ«ts, izmantojot komandu assembler rim - jums tas bÅ«s jāmeklē ProgrammÄ“Å”anas rokasgrāmata:

//enable interrupts
_asm("rim");

Vēl viena montētāja komanda ir sim ā€“ izslēdz pārtraukumus. Tie ir jāizslēdz, kamēr ā€œvideo atmiņāā€ tiek ierakstÄ«tas jaunas vērtÄ«bas, lai nepareizā brÄ«dÄ« radÄ«ts pārtraukums nesabojātu masÄ«vu.

Viss kods - vietnē GitHub.

2. datu lapu lasīŔana: SPI uz STM32; PWM, taimeri un pārtraukumi STM8

Ja vismaz kādam Å”is raksts Ŕķiet noderÄ«gs, tad es to nerakstÄ«ju velti. PriecāŔos saņemt komentārus un piezÄ«mes, centÄ«Å”os uz visu atbildēt.

Avots: www.habr.com

Pievieno komentāru