Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

В fyrsti hluti Ég reyndi að segja rafeindaverkfræðingum á áhugamálinu sem ólust upp úr Arduino buxum hvernig og hvers vegna þeir ættu að lesa gagnablöð og önnur skjöl fyrir örstýringar. Textinn reyndist stór, svo ég lofaði að sýna hagnýt dæmi í sérstakri grein. Hann kallaði sig mjólkursvepp...

Í dag mun ég sýna þér hvernig á að nota gagnablöð til að leysa frekar einfalt, en nauðsynlegt fyrir mörg verkefni, verkefni á STM32 (Blue Pill) og STM8 stýringar. Öll kynningarverkefni eru tileinkuð uppáhalds LED ljósunum mínum, við kveikjum á þeim í miklu magni, til þess þurfum við að nota alls kyns áhugaverð jaðartæki.

Textinn reyndist aftur stór, svo til hægðarauka geri ég efnið:

STM32 Blue Pill: 16 LED með DM634 reklum
STM8: Setja upp sex PWM pinna
STM8: 8 RGB LED á þremur pinnum, truflar

Fyrirvari: Ég er ekki verkfræðingur, ég þykist ekki hafa djúpa þekkingu á rafeindatækni, greinin er ætluð áhugamönnum eins og mér. Reyndar taldi ég mig fyrir tveimur árum vera markhópinn. Ef einhver hefði sagt mér þá að gagnablöð á ókunnugum flís væru ekki skelfileg aflestrar hefði ég ekki eytt miklum tíma í að leita að einhverjum kóða á netinu og finna upp hækjur með skærum og límbandi.

Áherslan í þessari grein er á gagnablöð, ekki verkefni, svo kóðinn er kannski ekki mjög snyrtilegur og oft þröngur. Verkefnin sjálf eru mjög einföld, þótt henta vel fyrir fyrstu kynni af nýju flögunni.

Ég vona að greinin mín muni hjálpa einhverjum sem er á svipuðu stigi í áhugamálinu.

STM32

16 LED með DM634 og SPI

Lítið verkefni sem notar Blue Pill (STM32F103C8T6) og DM634 LED rekil. Með því að nota gagnablöð munum við reikna út ökumanninn, STM IO tengi og stilla SPI.

DM634

Tævanskur flís með 16 16 bita PWM útgangi, hægt að tengja í keðjur. Lágmarks 12-bita líkanið er þekkt frá innlendu verkefni Ljósapakki. Á sínum tíma, þegar ég valdi á milli DM63x og hins vel þekkta TLC5940, valdi ég DM af nokkrum ástæðum: 1) TLC á Aliexpress er örugglega falsað, en þessi er það ekki; 2) DM hefur sjálfstætt PWM með eigin tíðni rafall; 3) það væri hægt að kaupa það ódýrt í Moskvu, frekar en að bíða eftir pakka frá Ali. Og auðvitað var áhugavert að læra hvernig á að stjórna flísinni sjálfur, frekar en að nota tilbúið bókasafn. Flísar eru nú aðallega í SSOP24 pakkanum; auðvelt er að lóða þá við millistykki.

Þar sem framleiðandinn er taívanskur, gagnablað kubburinn er skrifaður á kínversku ensku, sem þýðir að það verður gaman. Fyrst lítum við á pinout (Pinnatenging) til að skilja hvaða fót á að tengja hvað við, og lýsing á pinnunum (Pinnalýsing). 16 pinnar:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
DC Sink Sources (Open Drain)

Vaskur / Útgangur með opnu holræsi - holræsi; uppspretta innstreymisstraums; úttakið er tengt við jörðu í virku ástandi - LED eru tengd við ökumanninn með bakskautum. Rafmagnslega séð er þetta auðvitað ekki „opið holræsi“ (opið niðurfall), en í gagnablöðum er þessi tilnefning fyrir pinna í frárennslisstillingu oft að finna.

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Ytri viðnám á milli REXT og GND til að stilla útgangsstraumgildi

Viðmiðunarviðnám er komið fyrir á milli REXT pinna og jarðar, sem stjórnar innra viðnámi úttakanna, sjá línurit á blaðsíðu 9 í gagnablaðinu. Í DM634 er einnig hægt að stjórna þessari viðnám með hugbúnaði, stilla heildar birtustig (alþjóðlegt birtustig); Ég mun ekki fara í smáatriði í þessari grein, ég mun bara setja 2.2 - 3 kOhm viðnám hér.

Til að skilja hvernig á að stjórna flísinni skulum við skoða lýsinguna á viðmóti tækisins:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Já, hér er hún, kínversk enska í allri sinni dýrð. Það er erfitt að þýða þetta, þú getur skilið það ef þú vilt, en það er önnur leið - skoðaðu hvernig tengingu við virkni svipað TLC5940 er lýst í gagnablaðinu:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
... Aðeins þarf þrjá pinna til að slá inn gögn í tækið. Hækkandi brún SCLK merksins færir gögnin frá SIN pinnanum yfir í innri skrána. Eftir að öll gögn hafa verið hlaðin, læsir stutt hátt XLAT merki gögnin sem flutt eru í röð inn í innri skrárnar. Innri skrár eru hlið sem koma af stað af XLAT merkjastigi. Öll gögn eru send mikilvægustu bita fyrst.

Latch – lás/lás/lás.
Hækkandi brún - fremstu brún púls
MSB fyrst – markverðasti (lengst til vinstri) bit fram á við.
til að klukka gögn - senda gögn í röð (bit fyrir bit).

Orð latch er oft að finna í skjölum fyrir flís og er þýtt á ýmsa vegu, svo til skilnings leyfis ég mér

lítið fræðsluefniLED bílstjórinn er í meginatriðum vaktaskrá. "Skift" (breyting) í nafninu - gagnaflutningur inni í tækinu í bita: hver nýr biti sem ýtt er inn ýtir allri keðjunni fram fyrir það. Þar sem enginn vill fylgjast með óskipulegum blikkandi ljósdíóðum á vaktinni, fer ferlið fram í biðminni skrám sem eru aðskilin frá vinnuskrám með dempara (latch) er eins konar biðstofa þar sem bitunum er raðað í þá röð sem óskað er eftir. Þegar allt er tilbúið opnast lokarinn og bitarnir fara að vinna og koma í stað fyrri lotunnar. Orð latch í skjölunum fyrir örrásir felur nánast alltaf í sér slíkan dempara, sama í hvaða samsetningum hann er notaður.

Svo, gagnaflutningur til DM634 fer fram á þennan hátt: stilltu DAI-inntakið á gildi mikilvægasta bita fjær LED, dragðu DCK upp og niður; stilltu DAI inntakið á gildi næsta bita, dragðu DCK; og svo framvegis þar til allir bitar hafa verið sendir (klukkað inn), eftir það drögum við LAT. Þetta er hægt að gera handvirkt (bita-högg), en það er betra að nota SPI viðmót sérstaklega sniðið fyrir þetta, þar sem það er sýnt á STM32 okkar í tveimur eintökum.

Blá pilla STM32F103

Inngangur: STM32 stýringar eru miklu flóknari en Atmega328 en þeir gætu virst skelfilegir. Þar að auki, vegna orkusparnaðar, er slökkt á næstum öllum jaðartækjum í byrjun og klukkutíðnin er 8 MHz frá innri uppsprettu. Sem betur fer skrifuðu STM forritarar kóða sem færir flísina upp í "reiknaða" 72 MHz og höfundar allra IDE sem ég þekki tóku hann með í frumstillingarferlinu, svo við þurfum ekki að klukka (en þú getur ef þú virkilega vilt). En þú verður að kveikja á jaðartækjum.

Skjöl: Blue Pill er búinn vinsælum STM32F103C8T6 flís, það eru tvö gagnleg skjöl fyrir það:

Í gagnablaðinu gætum við haft áhuga á:

  • Pinouts – chip pinouts – ef við ákveðum að búa til borðin sjálf;
  • Minniskort – minniskort fyrir tiltekna flís. Í tilvísunarhandbókinni er kort fyrir alla línuna og þar er minnst á skrár sem okkar eru ekki með.
  • Tafla með skilgreiningum pinna - listi yfir helstu og aðrar aðgerðir pinna; fyrir „bláu pilluna“ geturðu fundið þægilegri myndir á netinu með lista yfir nælur og virkni þeirra. Þess vegna googlum við strax Blue Pill pinout og höfum þessa mynd við höndina:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
ATH: það var villa í myndinni af netinu sem kom fram í athugasemdum, takk fyrir það. Myndinni hefur verið skipt út, en þetta er lexía - það er betra að athuga upplýsingar ekki úr gagnablöðum.

Við fjarlægjum gagnablaðið, opnum tilvísunarhandbókina og héðan í frá notum við aðeins það.
Málsmeðferð: við tökumst á við staðlað inntak/úttak, stillum SPI, kveikjum á nauðsynlegum jaðartækjum.

Inntak úttak

Á Atmega328 er I/O útfært á mjög einfaldan hátt, þess vegna getur gnægð STM32 valkosta verið ruglingslegt. Nú þurfum við aðeins ályktanir, en jafnvel þessir hafa fjóra valkosti:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
opið frárennsli, ýta-draga, val ýta-draga, val opið niðurfall

"Pull-ýta" (ýta toga) er venjuleg framleiðsla frá Arduino, pinninn getur tekið gildið annað hvort HÁTT eða LÁGT. En með "opnu holræsi" eru það erfiðleikar, þó í raun sé allt einfalt hér:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Úttaksstilling / þegar tengi er úthlutað til úttaks: / úttaksbuffi virkt: / – opinn frárennslishamur: "0" í úttaksskránni virkjar N-MOS, "1" í úttaksskránni fer úr portinu í Hi-Z ham ( P-MOS er ekki virkjað) / – push-pull ham: „0“ í úttaksskránni virkjar N-MOS, „1“ í úttaksskránni virkjar P-MOS.

Allur munurinn á opnu holræsi (opið niðurfall) frá „push-pull“ (ýta toga) er að í fyrsta pinna getur ekki samþykkt HIGH ástandið: þegar þú skrifar einn í úttaksskrána fer hann í hátt viðnámsham (hár viðnám, Hæ-Z). Þegar núll er skrifað, hegðar pinninn sér eins í báðum stillingum, bæði rökfræðilega og rafrænt.

Í venjulegum úttaksham sendir pinninn einfaldlega út innihald úttaksskrárinnar. Í „valinu“ er því stjórnað af samsvarandi jaðartækjum (sjá 9.1.4):

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Ef tengibiti er stilltur sem annar virknipinna er pinnaskráin óvirk og pinninn tengdur við jaðarpinna.

Önnur virkni hvers pinna er lýst í Pin skilgreiningar Gagnablaðið er á myndinni sem hlaðið var niður. Við spurningunni um hvað eigi að gera ef pinna hefur nokkrar aðrar aðgerðir, er svarið gefið með neðanmálsgrein í gagnablaðinu:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Ef mörg jaðartæki nota sama pinna, til að koma í veg fyrir árekstra milli annarra aðgerða, ætti aðeins að nota eitt jaðartæki í einu, skipta um það með því að nota jaðarklukkuvirkjunarbitann (í viðeigandi RCC skrá).

Að lokum hafa pinnar í úttaksstillingu einnig klukkuhraða. Þetta er annar orkusparandi eiginleiki; í okkar tilviki stillum við það bara á hámark og gleymum því.

Svo: við erum að nota SPI, sem þýðir að tveir pinnar (með gögnum og með klukkumerki) ættu að vera „val push-pull aðgerð“ og annar (LAT) ætti að vera „venjulegur push-pull“. En áður en þeim er úthlutað skulum við takast á við SPI.

SPI

Önnur lítil fræðsluáætlun

SPI eða Serial Peripheral Interface (serial peripheral interface) er einfalt og mjög áhrifaríkt viðmót til að tengja MK við aðra MK og umheiminn almennt. Meginreglan um rekstur þess hefur þegar verið lýst hér að ofan, þar sem um kínverska LED bílstjórinn er að ræða (í tilvísunarhandbókinni, sjá kafla 25). SPI getur starfað í master ("meistara") og þræl ("slave") ham. SPI hefur fjórar grunnrásir, þar af má ekki nota allar:

  • MOSI, Master Output / Slave Input: þessi pinna sendir gögn í masterham og tekur á móti gögnum í slaveham;
  • MISO, Master Input / Slave Output: þvert á móti, það tekur á móti í masternum og sendir í þrælnum;
  • SCK, Serial Clock: stillir tíðni gagnaflutnings í masternum eða tekur á móti klukkumerki í þrælnum. Í meginatriðum slá slög;
  • SS, Slave Select: með hjálp þessarar rásar veit þrællinn að eitthvað er óskað eftir honum. Á STM32 er það kallað NSS, þar sem N = neikvætt, þ.e. stjórnandinn verður þræll ef það er jörð í þessari rás. Það sameinast vel með Open Drain Output ham, en það er önnur saga.

Eins og allt annað er SPI á STM32 ríkur af virkni, sem gerir það nokkuð erfitt að skilja það. Til dæmis getur það virkað ekki aðeins með SPI, heldur einnig með I2S viðmóti, og í skjölunum eru lýsingar þeirra blandaðar, það er nauðsynlegt að skera af umfram tímanlega. Verkefni okkar er mjög einfalt: við þurfum bara að senda gögn með því að nota aðeins MOSI og SCK. Við förum í kafla 25.3.4 (hálf tvíhliða samskipti, hálf tvíhliða samskipti), þar sem við finnum 1 klukka og 1 einátta gagnavír (1 klukkumerki og 1 einátta gagnastraumur):

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Í þessari stillingu notar forritið SPI í annaðhvort eingöngu sendingarham eða móttökuham. / Eingöngu sendingarhamur er svipaður tvíhliða ham: gögn eru send á sendingarpinna (MOSI í masterham eða MISO í þrælham), og móttökupinna (MISO eða MOSI í sömu röð) er hægt að nota sem venjulegan I/O pinna . Í þessu tilviki þarf forritið aðeins að hunsa Rx biðminni (ef það er lesið verða engin flutt gögn þangað).

Frábært, MISO pinninn er ókeypis, við skulum tengja LAT merkið við hann. Skoðum Slave Select, sem á STM32 er hægt að stjórna forritunarlega, sem er einstaklega þægilegt. Við lesum málsgreinina með sama nafni í kafla 25.3.1 SPI Almenn lýsing:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Hugbúnaðarstýring NSS (SSM = 1) / Þrælavalsupplýsingar eru í SSI bita SPI_CR1 skrárinnar. Ytri NSS pinna er áfram ókeypis fyrir aðrar umsóknarþarfir.

Það er kominn tími til að skrifa í skrárnar. Ég ákvað að nota SPI2, leitaðu að grunnfangi þess í gagnablaðinu - í kafla 3.3 Minniskort:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Jæja, við skulum byrja:

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

Opnaðu hluta 25.3.3 með sjálfskýrandi titlinum „Stilling SPI í Master Mode“:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

1. Stilltu raðklukkutíðni með bitum BR[2:0] í SPI_CR1 skránni.

Skránum er safnað í samnefndum tilvísunarhandbókarhluta. Heimilisfangsbreyting (Heimilisfangsfráfærsla) fyrir CR1 – 0x00, sjálfgefið eru allir bitar hreinsaðir (Endurstilla gildi 0x0000):

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

BR bitarnir stilla klukkudeili stjórnandans og ákvarða þannig tíðnina sem SPI mun starfa á. STM32 tíðnin okkar verður 72 MHz, LED rekillinn, samkvæmt gagnablaði þess, starfar með allt að 25 MHz tíðni, þannig að við þurfum að deila með fjórum (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. Stilltu CPOL og CPHA bitana til að skilgreina sambandið milli gagnaflutnings og tímasetningar raðklukku (sjá skýringarmynd á blaðsíðu 240)

Þar sem við erum að lesa gagnablað hér og ekki að skoða skýringarmyndir, skulum við skoða nánar textalýsinguna á CPOL og CPHA bitunum á síðu 704 (SPI almenn lýsing):

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Klukkufasi og pólun
Með því að nota CPOL og CPHA bita SPI_CR1 skrárinnar geturðu valið fjögur tímasetningartengsl með forritunaraðferðum. CPOL (klukkupólun) bitinn stjórnar stöðu klukkumerkisins þegar engin gögn eru send. Þessi biti stjórnar master og þrælastillingum. Ef CPOL er endurstillt er SCK pinnan lág í hvíldarham. Ef CPOL bitinn er stilltur er SCK pinnan hátt í hvíldarham.
Þegar CPHA (klukkufasa) bitinn er stilltur, er hábitagildrustrobe önnur brún SCK merksins (lækkar ef CPOL er hreint, hækkar ef CPOL er stillt). Gögnin eru tekin með seinni breytingunni á klukkumerkinu. Ef CPHA bitinn er tær, er hábita gildru strobe hækkandi brún SCK merksins (lækkandi brún ef CPOL er stillt, hækkandi brún ef CPOL er hreinsuð). Gögn eru tekin við fyrstu breytingu á klukkumerkinu.

Eftir að hafa tileinkað okkur þessa þekkingu komumst við að þeirri niðurstöðu að báðir bitarnir verða að vera núll, vegna þess að Við viljum að SCK merkið haldist lágt þegar það er ekki í notkun og að gögn séu send á hækkandi brún púlsins (sjá mynd. Rising Edge í DM634 gagnablaðinu).

Við the vegur, hér hittum við fyrst eiginleika orðaforða í ST gagnablöðum: í þeim er setningin „endurstilla bitann á núll“ að núllstilla aðeinsOg ekki að hreinsa aðeins, eins og til dæmis Atmega.

3. Stilltu DFF bitann til að ákvarða hvort gagnablokkin sé 8-bita eða 16-bita snið

Ég tók sérstaklega 16 bita DM634 til að nenna ekki að senda 12 bita PWM gögn, eins og DM633. Það er skynsamlegt að stilla DFF á einn:

#define DFF         0x0800

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

4. Stilltu LSBFIRST bitann í SPI_CR1 skránni til að ákvarða blokkarsniðið

LSBFIRST, eins og nafnið gefur til kynna, stillir sendingu með minnstu bitanum fyrst. En DM634 vill fá gögn frá mikilvægasta bitanum. Þess vegna látum við það endurstilla.

5. Í vélbúnaðarstillingu, ef inntaks frá NSS pinna er krafist, skaltu beita háu merki á NSS pinna meðan á allri bætaflutningsröðinni stendur. Í NSS hugbúnaðarham skaltu stilla SSM og SSI bitana í SPI_CR1 skránni. Ef nota á NSS pinna sem úttak þarf aðeins að stilla SSOE bitann.

Settu upp SSM og SSI til að gleyma NSS vélbúnaðarstillingunni:

#define SSI         0x0100
#define SSM         0x0200

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

6. Stilla verður MSTR og SPE bitana (þeir haldast aðeins stilltir ef NSS merki er hátt)

Reyndar, með þessum bitum útnefnum við SPI okkar sem meistara og kveikjum á honum:

#define MSTR        0x0004
#define SPE         0x0040

_SPI2_ (_SPI_CR1) |= MSTR; //SPI master
//когда все готово, включаем SPI
_SPI2_ (_SPI_CR1) |= SPE;

SPI er stillt, við skulum strax skrifa aðgerðir sem senda bæti til ökumannsins. Halda áfram að lesa 25.3.3 „Stilling SPI í masterham“:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Gagnaflutningspöntun
Sending hefst þegar bæti er skrifað í Tx biðminni.
Gagnabætið er hlaðið inn í vaktaskrána kl samhliða ham (frá innri rútunni) meðan á sendingu fyrsta bitans stendur, eftir það er hann sendur til röð MOSI pinnahamur, fyrsti eða síðasti biti áfram eftir stillingu LSBFIRST bitans í CPI_CR1 skránni. TXE fáninn er stilltur eftir gagnaflutning frá Tx biðminni til vaktaskrár, og myndar einnig truflun ef TXEIE bitinn í CPI_CR1 skránni er stilltur.

Ég benti á nokkur orð í þýðingunni til að vekja athygli á einum eiginleika SPI innleiðingar í STM stýringar. Á Atmega TXE fánann (Tx tómt, Tx er tómt og tilbúið til að taka á móti gögnum) er aðeins stillt eftir að allt bæti hefur verið sent út á við. Og hér er þetta flagg sett eftir að bæti hefur verið sett inn í innri vaktaskrá. Þar sem því er ýtt þangað með öllum bitunum á sama tíma (samhliða), og síðan eru gögnin flutt í röð, er TXE stillt áður en bætið er alveg sent. Þetta er mikilvægt vegna þess þegar um er að ræða LED bílstjórann okkar, þurfum við að draga LAT pinnana eftir sendingu allt gögn, þ.e. TXE fáninn einn mun ekki duga okkur.

Þetta þýðir að við þurfum annan fána. Við skulum líta á 25.3.7 - „Stöðufánar“:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
<…>
Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
UPPTAKIÐ fáni
BSY fáninn er stilltur og hreinsaður af vélbúnaði (að skrifa á það hefur engin áhrif). BSY fáninn gefur til kynna stöðu SPI samskiptalagsins.
Það endurstillir:
þegar flutningi er lokið (nema í masterham ef flutningur er samfelldur)
þegar SPI er óvirkt
þegar masterham villa kemur upp (MODF=1)
Ef flutningurinn er ekki samfelldur er BSY fáninn hreinsaður á milli hvers gagnaflutnings

Jæja, þetta kemur sér vel. Við skulum finna út hvar Tx biðminni er staðsett. Til að gera þetta skaltu lesa „SPI Data Register“:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Bitar 15:0 DR[15:0] Gagnaskrá
Móttekin gögn eða gögn sem á að senda.
Gagnaskránni er skipt í tvo biðminni - einn fyrir ritun (senda biðminni) og einn fyrir lestur (móttaka biðminni). Að skrifa í gagnaskrána skrifar í Tx biðminni og lestur úr gagnaskránni mun skila gildinu sem er í Rx biðminni.

Jæja, og stöðuskráin, þar sem TXE og BSY fánarnir eru að finna:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Við skrifum:

#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
}

Jæja, þar sem við þurfum að senda 16 sinnum tvö bæti, í samræmi við fjölda LED ökumannsúttakanna, eitthvað á þessa leið:

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();
}

En við vitum ekki hvernig á að draga LAT pinna ennþá, svo við förum aftur í I/O.

Að úthluta pinnum

Í STM32F1 eru skrárnar sem bera ábyrgð á ástandi pinna nokkuð óvenjulegar. Það er ljóst að þeir eru fleiri en Atmega, en þeir eru líka ólíkir öðrum STM flögum. Kafli 9.1 Almenn lýsing á GPIO:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Hvert af almennu I/O höfnunum (GPIO) hefur tvær 32-bita stillingarskrár (GPIOx_CRL og GPIOx_CRH), tvær 32-bita gagnaskrár (GPIOx_IDR og GPIOx_ODR), 32-bita sett/endurstilla skrá (GPIOx_BSRR), 16-bita endurstillingarskrá (GPIOx_BRR) og 32- bitablokkunarskrá (GPIOx_LCKR).

Fyrstu tveir skrárnar eru óvenjulegar og líka frekar óþægilegar, vegna þess að 16 portpinnar eru dreifðir yfir þá í „fjórum bitum á bróður“ sniði. Þeir. pinnar núll til sjö eru í CRL og restin er í CRH. Á sama tíma innihalda skrárnar sem eftir eru bita allra pinna gáttarinnar - oft eftir hálft „frátekið“.

Til einföldunar skulum við byrja frá enda listans.

Við þurfum ekki læsingarskrá.

Stillingar- og endurstillingarskrárnar eru frekar fyndnar að því leyti að þeir afrita hvort annað að hluta: þú getur skrifað allt aðeins í BSRR, þar sem hærri 16 bitarnir endurstilla pinnann á núll, og þeir neðri verða stilltir á 1, eða þú getur líka notaðu BRR, neðri 16 bitarnir endurstilla aðeins pinnana. Mér líkar við seinni kostinn. Þessar skrár eru mikilvægar vegna þess að þær veita atómaðgang að pinnum:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Atómstilling eða endurstilling
Það er engin þörf á að slökkva á truflunum þegar forritað er GPIOx_ODR á bitastigi: einum eða fleiri bitum er hægt að breyta með einni atómskrifaaðgerð APB2. Þetta er náð með því að skrifa "1" í set/endurstilla skrána (GPIOx_BSRR eða, fyrir endurstillingu eingöngu, GPIOx_BRR) bitans sem þarf að breyta. Aðrir bitar verða óbreyttir.

Gagnaskrárnar bera nokkuð sjálfskýrandi nöfn - IDR = inntak Stefnaskrá, inntaksskrá; ODR = Output Stefnaskrá, úttaksskrá. Við þurfum ekki á þeim að halda í núverandi verkefni.

Og að lokum, eftirlitsskrár. Þar sem við höfum áhuga á seinni SPI pinnunum, nefnilega PB13, PB14 og PB15, skoðum við strax CRH:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Og við sjáum að við þurfum að skrifa eitthvað í bitum frá 20 til 31.

Við höfum þegar fundið út hér að ofan hvað við viljum af pinnum, svo hér mun ég gera án skjáskots, ég segi bara að MODE tilgreinir stefnuna (inntak ef báðir bitarnir eru stilltir á 0) og pinnahraða (við þurfum 50MHz, þ.e.a.s. bæði pinna á "1"), og CNF stillir stillinguna: venjulegur "push-pull" - 00, "val" - 10. Sjálfgefið, eins og við sjáum hér að ofan, hafa allir pinnar þriðja bitann frá botninum (CNF0), það setur þá í ham fljótandi inntak.

Þar sem ég ætla að gera eitthvað annað með þessum flís hef ég til einföldunar skilgreint öll möguleg MODE og CNF gildi fyrir bæði neðri og efri stjórnskrána.

Einhvern veginn svona

#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

Pinnarnir okkar eru staðsettir á port B (grunnfang - 0x40010C00), kóða:

#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;

Og í samræmi við það geturðu skrifað skilgreiningar fyrir LAT, sem verður kippt af BRR og BSRR skránum:

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

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

(LAT_low bara af tregðu, það hefur alltaf verið svona, láttu það vera)

Nú er allt frábært, en það virkar ekki. Vegna þess að þetta er STM32 spara þeir rafmagn, sem þýðir að þú þarft að virkja klukku á nauðsynlegum jaðartækjum.

Kveiktu á klukku

Úrið, einnig þekkt sem Clock, ber ábyrgð á klukku. Og við gætum þegar tekið eftir skammstöfuninni RCC. Við leitum að því í skjölunum: þetta er Reset and Clock Control.

Eins og sagt var hér að ofan, sem betur fer var erfiðasti hluti klukkuefnisins gerður fyrir okkur af fólki frá STM, sem við þökkum þeim kærlega fyrir (enn og aftur mun ég gefa tengil á Heimasíða Di Halt, til að gera það ljóst hversu ruglingslegt það er). Við þurfum aðeins skrár sem bera ábyrgð á að virkja jaðarklukku (Peripheral Clock Enable Registers). Í fyrsta lagi skulum við finna grunn heimilisfang RCC, það er í upphafi „Minniskortsins“:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

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

Og smelltu svo annaðhvort á hlekkinn þar sem þú reynir að finna eitthvað í plötunni, eða, miklu betra, farðu í gegnum lýsingarnar á virkjunarskránum úr köflum um virkja skrár. Hvar finnum við RCC_APB1ENR og RCC_APB2ENR:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Og í samræmi við það innihalda þeir bita sem innihalda klukku SPI2, IOPB (I/O Port B) og aðrar aðgerðir (AFIO).

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

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

//включаем тактирование порта B и альт. функций
_RCC_(_APB2ENR) |= IOPBEN | AFIOEN;

//включаем  тактирование SPI2
_RCC_(_APB1ENR) |= SPI2EN;

Lokakóðann er að finna hér.

Ef þú hefur tækifæri og löngun til að prófa, tengdu þá DM634 svona: DAI við PB15, DCK við PB13, LAT við PB14. Við knýjum ökumanninn frá 5 voltum, ekki gleyma að tengja jarðveginn.

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

STM8 PWM

PWM á STM8

Þegar ég var að skipuleggja þessa grein ákvað ég, sem dæmi, að reyna að ná tökum á einhverjum virkni ókunnugrar flísar með því að nota aðeins gagnablað, svo að ég myndi ekki enda með skósmið án stígvéla. STM8 var tilvalið fyrir þetta hlutverk: í fyrsta lagi átti ég nokkrar kínverskar töflur með STM8S103 og í öðru lagi er það ekki mjög vinsælt og þess vegna hvílir freistingin til að lesa og finna lausn á netinu á skortinum á þessum lausnum.

Kubburinn hefur líka gagnablað и tilvísunarhandbók RM0016, í fyrstu er pinout og skrá heimilisföng, í öðru - allt annað. STM8 er forritað í C í hræðilegu IDE ST sjónræn þróun.

Klukka og I/O

Sjálfgefið er að STM8 starfar á 2 MHz tíðninni, þetta verður að leiðrétta strax.

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
HSI (High Speed ​​​​Internal) klukka
HSI klukkumerkið er dregið af innri 16 MHz RC oscillator með forritanlegum deili (1 til 8). Það er stillt í klukkuskilaskránni (CLK_CKDIVR).
Athugið: í upphafi er HSI RC sveiflubúnaður með deili 8 valinn sem leiðandi uppspretta klukkumerkisins.

Við finnum skráarfangið í gagnablaðinu, lýsinguna í refman og sjáum að það þarf að hreinsa skrána:

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

Þar sem við ætlum að keyra PWM og tengja ljósdíóða, skulum við líta á pinout:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Kubburinn er lítill, margar aðgerðir eru hengdar á sömu pinna. Það sem er innan hornklofa er „val virkni“, það er skipt um „valkostabæti“ (valmöguleikabæti) – eitthvað eins og Atmega öryggi. Þú getur breytt gildum þeirra forritunarlega, en það er ekki nauðsynlegt vegna þess Nýja virknin er aðeins virkjuð eftir endurræsingu. Það er auðveldara að nota ST Visual Programmer (halað niður með Visual Develop), sem getur breytt þessum bætum. Pinout sýnir að CH1 og CH2 pinnar á fyrsta tímamælinum eru falin innan hornklofa; það er nauðsynlegt að stilla AFR1 og AFR0 bitana í STVP, og sá seinni mun einnig flytja CH1 úttak seinni tímamælisins frá PD4 til PC5.

Þannig munu 6 pinnar stjórna LED: PC6, PC7 og PC3 fyrir fyrsta tímamælirinn, PC5, PD3 og PA3 fyrir þann seinni.

Að setja upp I/O pinnana sjálfa á STM8 er einfaldara og rökréttara en á STM32:

  • þekki frá Atmega DDR gagnastefnuskrá (Gagnastefnuskrá): 1 = framleiðsla;
  • fyrsta stýriskráin CR1, þegar hún er útgefin, stillir ýta-draga stillingu (1) eða opið holræsi (0); þar sem ég tengi LED við flísina með bakskautum, skil ég núll eftir hér;
  • seinni stjórnskráin CR2 stillir klukkuhraðann þegar hún er útgefin: 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 stilling

Fyrst skulum við skilgreina hugtökin:

  • PWM tíðni – tíðni sem tímamælirinn tikkar með;
  • Sjálfvirk endurhleðsla, AR - sjálfvirkt gildi sem tímamælirinn mun telja upp í (púlstímabil);
  • Uppfærðu viðburður, UEV – atburður sem á sér stað þegar teljarinn hefur talið til AR;
  • PWM vinnuferill - PWM vinnuferill, oft kallaður "skylduþáttur";
  • Handtaka/bera saman gildi – gildi fyrir töku/samanburð, sem tímamælirinn hefur talið til mun gera eitthvað (þegar um PWM er að ræða, snýr það úttaksmerkinu);
  • Forhlaða gildi – forhlaðið gildi. Berðu saman gildi getur ekki breyst á meðan tímamælirinn tikkar, annars mun PWM hringrásin rofna. Þess vegna eru ný send gildi sett í biðminni og dregin út þegar teljarinn nær lok niðurtalningar og er endurstilltur;
  • Jaðarjafnað и Miðjastilltar stillingar – röðun meðfram landamærunum og í miðjunni, eins og Atmel Hratt PWM и Fasa-rétt PWM.
  • OCiREF, Output Compare Reference Signal – viðmiðunarúttaksmerkið, í raun, það sem birtist á samsvarandi pinna í PWM ham.

Eins og þegar er ljóst af pinout hafa tveir tímamælir PWM getu - sá fyrsti og sá annar. Báðir eru 16-bita, sá fyrsti hefur fullt af viðbótareiginleikum (sérstaklega getur hann talið bæði upp og niður). Við þurfum bæði að vinna jafnt, svo ég ákvað að byrja á þeim seinni sem er augljóslega lakari, til að nota ekki óvart eitthvað sem er ekki til staðar. Eitthvað vandamál er að lýsingin á PWM virkni allra tímamæla í tilvísunarhandbókinni er í kaflanum um fyrsta tímamælinn (17.5.7 PWM Mode), þannig að þú þarft að hoppa fram og til baka í gegnum skjalið allan tímann.

PWM á STM8 hefur mikilvægan kost á PWM á Atmega:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Boundary Aligned PWM
Reikningsstilling frá botni til topps
Botn-upp talning er virk ef DIR bitinn í TIM_CR1 skránni er hreinsaður
Dæmi
Dæmið notar fyrstu PWM haminn. PWM viðmiðunarmerkinu OCiREF er haldið hátt svo lengi sem TIM1_CNT < TIM1_CCRi. Annars tekur það lágt stig. Ef samanburðargildið í TIM1_CCRi skránni er hærra en sjálfvirkt hleðslugildi (TIM1_ARR skrár), er OCiREF merkinu haldið á 1. Ef samanburðargildið er 0 er OCiREF haldið á núlli....

STM8 teljari á meðan uppfæra atburð athugar fyrst bera saman gildi, og aðeins þá framleiðir viðmiðunarmerki. Atmega tímamælir skrúfar fyrst upp og ber síðan saman, sem leiðir til compare value == 0 úttakið er nál, sem verður að bregðast við á einhvern hátt (til dæmis með því að snúa rökfræðinni á dagskrá).

Svo það sem við viljum gera: 8-bita PWM (AR == 255), talið frá botni til topps, röðun meðfram landamærunum. Þar sem ljósaperurnar eru tengdar við flöguna með bakskautum ætti PWM að gefa út 0 (LED á) til kl. bera saman gildi og 1 á eftir.

Við höfum þegar lesið um suma PWM ham, þannig að við finnum nauðsynlega skrá fyrir seinni tímamælirinn með því að leita í tilvísunarhandbókinni að þessari setningu (18.6.8 - TIMx_CCMR1):

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
110: Fyrsta PWM ham – þegar talið er frá botni til topps er fyrsta rásin virk á meðan TIMx_CNT < TIMx_CCR1. Annars er fyrsta rásin óvirk. [nánar í skjalinu er rangt copy-paste frá tímamæli 1] 111: Önnur PWM ham – þegar talið er frá botni til topps er fyrsta rásin óvirk á meðan TIMx_CNT < TIMx_CCR1. Annars er fyrsta rásin virk.

Þar sem LED eru tengd við MK með bakskautum, hentar seinni stillingin okkur (sá fyrri líka, en við vitum það ekki ennþá).

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Bit 3 OC1PE: Virkja forhleðslu pinna 1
0: Forhlaðaskrá á TIMx_CCR1 er óvirk. Þú getur skrifað á TIMx_CCR1 hvenær sem er. Nýja gildið virkar strax.
1: Forhlaðaskrá á TIMx_CCR1 er virkjuð. Les-/skrifaðgerðir fá aðgang að forhleðsluskránni. Forhlaðna gildið TIMx_CCR1 er hlaðið inn í skuggaskrána við hverja uppfærsluatburð.
*Athugið: Til að PWM hamur virki rétt verður að virkja forhleðsluskrárnar. Þetta er ekki nauðsynlegt í stakmerkjaham (OPM bitinn er stilltur í TIMx_CR1 skránni).

Allt í lagi, kveikjum á öllu sem við þurfum fyrir þrjár rásir seinni tímamælisins:

#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 samanstendur af tveimur átta bita skrám, allt er einfalt:

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

TIM2_ARRH = 0;
TIM2_ARRL = 255;

Seinni tímamælirinn getur aðeins talið frá botni til topps, röðun meðfram landamærunum, engu þarf að breyta. Við skulum stilla tíðnideilinn, til dæmis, á 256. Fyrir seinni tímamælirinn er deilirinn stilltur í TIM2_PSCR skránni og er kraftur tveggja:

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

Það eina sem er eftir er að kveikja á niðurstöðunum og seinni tímamælinum sjálfum. Fyrsta vandamálið er leyst með skrám Handtaka/bera saman Virkja: það eru tvær, þrjár rásir dreifðar ósamhverfar yfir þær. Hér getum við líka lært að það er hægt að breyta pólun merksins, þ.e. í grundvallaratriðum var hægt að nota PWM Mode 1. Við skrifum:

#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;

Og að lokum byrjum við tímamælirinn í TIMx_CR1 skránni:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

Við skulum skrifa einfalda hliðstæðu af AnalogWrite(), sem mun flytja raungildin yfir á tímamælirinn til samanburðar. Skrárnar heita fyrirsjáanlega Handtaka/bera saman skrár, það eru tveir af þeim fyrir hverja rás: lágskipan 8 bita í TIM2_CCRxL og háskipan í TIM2_CCRxH. Þar sem við höfum búið til 8-bita PWM, er nóg að skrifa aðeins mikilvægustu bitana:

#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;
}

The gaum lesandi mun taka eftir því að við erum með örlítið gallaða PWM, sem getur ekki framleitt 100% fyllingu (við hámarksgildi 255, er merkinu snúið við í eina tímastillingarlotu). Fyrir LED skiptir þetta ekki máli og gaumgæfi lesandinn getur þegar giskað á hvernig á að laga það.

PWM á seinni tímamælinum virkar, við skulum halda áfram í þann fyrsta.

Fyrsti tímamælirinn hefur nákvæmlega sömu bita í sömu skrám (það er bara þannig að þeir bitar sem voru „fráteknir“ í seinni tímamælinum eru virkir notaðir í þeim fyrsta fyrir alls kyns háþróaða hluti). Þess vegna er nóg að finna heimilisföng sömu skráa í gagnablaðinu og afrita kóðann. Jæja, breyttu gildi tíðniskilans, vegna þess að... fyrsti tímamælirinn vill ekki fá kraft upp á tvo, heldur nákvæmlega 16 bita gildi í tveimur skrám Prescaler High и Low. Við gerum allt og... fyrsti tímamælirinn virkar ekki. Hvað er að?

Vandamálið er aðeins hægt að leysa með því að skoða allan kaflann um stjórnskrár tímamælis 1, þar sem við leitum að þeim sem seinni tímamælirinn hefur ekki. Það mun verða 17.7.30 Hléskrá (TIM1_BKR), þar sem er þessi hluti:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Virkjaðu aðalúttak

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

Það er allt á hreinu núna, kóðinn þar.

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

STM8 Multiplex

Margföldun á STM8

Þriðja smáverkefnið er að tengja átta RGB LED við annan tímamæli í PWM ham og láta þá sýna mismunandi liti. Það er byggt á hugmyndinni um LED multiplexing, sem er að ef þú kveikir og slekkur á LED mjög, mjög fljótt, þá virðist okkur vera stöðugt á þeim (þrautseigja í sjón, tregðu sjónskynjunar). Ég gerði það einu sinni eitthvað svona á Arduino.

Vinnualgrímið lítur svona út:

  • tengdur rafskaut fyrsta RGB LED;
  • kveikti á því og sendi nauðsynleg merki til bakskautanna;
  • beið til loka PWM hringrásarinnar;
  • tengdu rafskautið á annarri RGB LED;
  • kveikti í því...

Jæja, o.s.frv. Auðvitað, fyrir fallega notkun, er nauðsynlegt að rafskautið sé tengt og ljósdíóðan er „kveikt“ á sama tíma. Jæja, eða næstum því. Í öllum tilvikum þurfum við að skrifa kóða sem mun gefa út gildi í þremur rásum seinni tímamælisins, breyta þeim þegar UEV er náð og um leið breyta núverandi RGB LED.

Þar sem LED skipting er sjálfvirk þurfum við að búa til „myndaminni“ sem truflunarstjórinn mun taka við gögnum frá. Þetta er einfalt fylki:

uint8_t colors[8][3];

Til þess að breyta lit á tiltekinni LED, mun það vera nóg að skrifa nauðsynleg gildi inn í þessa fylki. Og breytan mun bera ábyrgð á fjölda virku LED

uint8_t cnt;

Demux

Fyrir rétta multiplexing þurfum við, einkennilega nóg, CD74HC238 demultiplexer. Demultiplexer - flís sem útfærir rekstraraðila í vélbúnaði <<. Í gegnum þrjá inntakspinna (bita 0, 1 og 2) gefum við því þriggja bita númer X, og sem svar virkjar það úttaksnúmer (1<<X). Eftirstöðvar flísarinnar eru notaðar til að skala alla hönnunina. Við þurfum þessa flís, ekki aðeins til að fækka uppteknum pinna örstýringarinnar, heldur einnig til öryggis - til að kveikja ekki óvart á fleiri LED en mögulegt er og ekki brenna MK. Kubburinn kostar eina eyri og ætti alltaf að geyma hann í lyfjaskápnum heima hjá þér.

CD74HC238 okkar mun sjá um að veita spennu á rafskaut viðkomandi LED. Í fullgildum multiplex myndi það veita spennu til súlunnar í gegnum P-MOSFET, en í þessari kynningu er það mögulegt beint, vegna þess að það dregur 20 mA, skv alger hámarkseinkunnir í gagnablaðinu. Frá Gagnablað CD74HC238 við þurfum pinouts og þetta svindlblað:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
H = háspennustig, L = lágspennustig, X – er alveg sama

Við tengjum E2 og E1 við jörðu, E3, A0, A1 og A3 við pinna PD5, PC3, PC4 og PC5 á STM8. Þar sem taflan hér að ofan inniheldur bæði lágt og hátt stig, stillum við þessa pinna sem push-pull pinna.

PWM

PWM á seinni tímamælinum er stillt á sama hátt og í fyrri sögunni, með tvennum mun:

Fyrst þurfum við að virkja truflunina Uppfæra viðburð (UEV) sem mun kalla á aðgerð sem breytir virku LED. Þetta er gert með því að breyta bitanum Virkja truflun á uppfærslu í skrá með tali nafni

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
Trufla virkja skrá

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

Annar munurinn tengist fyrirbærinu margföldun, svo sem draugur - sníkjudýraljómi díóða. Í okkar tilviki gæti það birst vegna þess að tímamælirinn, sem hefur valdið truflun á UEV, heldur áfram að merkja og truflanarmaðurinn hefur ekki tíma til að skipta um LED áður en tímamælirinn byrjar að skrifa eitthvað á pinnana. Til að berjast gegn þessu verður þú að snúa við rökfræðinni (0 = hámarks birta, 255 = ekkert logar) og forðast öfgakennd vinnulotugildi. Þeir. Gakktu úr skugga um að eftir UEV slökkni ljósdíóðir alveg í eina PWM lotu.

Breyting á pólun:

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

Forðastu að stilla r, g og b á 255 og mundu að snúa þeim við þegar þú notar þau.

Truflar

Kjarninn í truflun er sá að undir vissum kringumstæðum hættir kubburinn að keyra aðalforritið og kallar á einhverja ytri aðgerð. Truflanir verða vegna ytri eða innri áhrifa, þar á meðal tímamælis.

Þegar við bjuggum fyrst til verkefni í ST Visual Develop, auk main.c við fengum glugga með dularfullri skrá stm8_interrupt_vector.c, sjálfkrafa með í verkefninu. Í þessari skrá er aðgerð úthlutað fyrir hverja truflun NonHandledInterrupt. Við þurfum að binda hlutverk okkar við æskilega truflun.

Gagnablaðið hefur töflu yfir truflunarvektora, þar sem við finnum þá sem við þurfum:

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8
13 TIM2 uppfærsla/flæði
14 TIM2 handtaka/samanburður

Við þurfum að skipta um LED á UEV, svo við þurfum truflun #13.

Í samræmi við það, í fyrsta lagi í skránni stm8_interrupt_vector.c breyttu sjálfgefna heiti aðgerðarinnar sem ber ábyrgð á truflun nr. 13 (IRQ13) í þitt eigið:

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

Í öðru lagi verðum við að búa til skrá main.h með eftirfarandi innihaldi:

#ifndef __MAIN_H
#define __MAIN_H

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

Og að lokum, skrifaðu þessa aðgerð í þinn 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;
}

Allt sem er eftir er að gera truflanir kleift. Þetta er gert með því að nota assembler skipunina rim - þú verður að leita að því Forritunarhandbók:

//enable interrupts
_asm("rim");

Önnur assembler skipun er sim – slekkur á truflunum. Slökkt verður á þeim á meðan ný gildi eru skrifuð í „myndaminni“, svo að truflun sem orsakast á röngum augnabliki spilli ekki fylkinu.

Allur kóði - á GitHub.

Lestu gagnablöð 2: SPI á STM32; PWM, tímamælir og truflanir á STM8

Ef að minnsta kosti einhverjum finnst þessi grein gagnleg, þá skrifaði ég hana ekki til einskis. Ég mun glaður fá athugasemdir og athugasemdir, ég mun reyna að svara öllu.

Heimild: www.habr.com

Bæta við athugasemd