Lugege andmelehti 2: SPI STM32-l; PWM, taimerid ja katkestused STM8-s
В Esimene osa Püüdsin Arduino pükstest välja kasvanud hobielektroonikainseneridele rääkida, kuidas ja miks nad peaksid lugema mikrokontrollerite andmelehti ja muud dokumentatsiooni. Tekst osutus suureks, nii et lubasin praktilisi näiteid näidata eraldi artiklis. Noh, ta nimetas end laaduriks ...
Täna näitan teile, kuidas andmelehtede abil lahendada STM32 (Blue Pill) ja STM8 kontrolleritel paljude projektide jaoks üsna lihtsaid, kuid vajalikke ülesandeid. Kõik demoprojektid on pühendatud minu lemmikutele LED-idele, valgustame neid suures koguses, selleks tuleb kasutada igasuguseid huvitavaid välisseadmeid.
Tekst osutus taas tohutuks, nii et mugavuse huvides koostan sisu:
Vastutusest loobumine: ma ei ole insener, ma ei pretendeeri oma sügavate teadmistega elektroonikasse, artikkel on mõeldud minusugustele amatööridele. Tegelikult pidasin end sihtrühmaks kaks aastat tagasi. Kui keegi oleks mulle tookord öelnud, et tundmatu kiibi andmelehti pole hirmus lugeda, poleks ma palju aega kulutanud internetist koodijuppide otsimisele ning kääride ja kleepkrohviga karkude leiutamisele.
Selle artikli keskmes on andmelehed, mitte projektid, nii et kood ei pruugi olla liiga lihvitud ja sageli kark. Projektid ise on väga lihtsad, kuigi sobivad esmatutvuseks uue kiibiga.
Loodan, et minu artikkel aitab kedagi, kes on hobisse sukeldumise sarnases etapis.
STM32
16 LED-i DM634 ja SPI-ga
Väike projekt Blue Pilli (STM32F103C8T6) ja DM634 LED-draiverit kasutades. Andmelehtede abil tegeleme draiveri, STM IO portide ja SPI konfigureerimisega.
DM634
Taiwani kiip 16 x 16-bitise PWM väljundiga, saab aheldada. Noorem 12-bitine mudel on tuntud kodumaisest projektist kerge pakk. Kunagi, valides DM63x ja tuntud TLC5940 vahel, leppisin DM-iga mitmel põhjusel: 1) Aliexpressi TLC on kindlasti võlts, kuid see pole seda; 2) DM-l on autonoomne PWM oma sagedusgeneraatoriga; 3) seda saab Moskvas odavalt osta ja mitte oodata Ali pakki. Ja muidugi oli huvitav õppida, kuidas kiipi ise juhtida, mitte kasutada valmis teeki. Kiibid on nüüd peamiselt SSOP24 pakendis, neid on lihtne adapteril jootma.
Kuna tootja on Taiwani päritolu, andmeleht to chip on kirjutatud hiina inglise keeles, mis tähendab, et see saab olema lõbus. Kõigepealt vaadake pinoutiPin ühendus), et mõista, milline jalg mida ühendada, ja tihvtide kirjeldus (PIN-koodi kirjeldus). 16 tihvti:
Valamu alalisvoolu allikad (avatud äravool)
valamu / Avatud äravooluga väljund - laos; sissetuleva voolu allikas; maandusega ühendatud väljund aktiivses olekus - LED-id ühendatakse draiveriga katoodide abil. Elektriliselt pole see muidugi "avatud äravool" (avatud äravool), kuid andmelehtedel leidub sageli sellist tähistust tühjendusrežiimis olevate väljundite jaoks.
Välised takistid REXT ja GND vahel väljundvoolu väärtuse määramiseks
REXT tihvti ja maanduse vahele on paigaldatud võrdlustakisti, mis juhib väljundite sisetakistust, vt graafikut andmelehe lk 9. DM634 puhul saab seda takistust juhtida ka tarkvara abil, seadistades üldise heleduse (globaalne heledus); Ma ei lasku selles artiklis üksikasjadesse, panen siia lihtsalt 2.2–3 kOhm takisti.
Kiibi juhtimise mõistmiseks vaatame seadme liidese kirjeldust:
Jah, siin see on, hiina inglise keel kogu oma hiilguses. Selle tõlkimine on problemaatiline, saate sellest aru saada, kui soovite, kuid on ka teine võimalus - vaadata, kuidas kirjeldatakse andmelehel ühendust funktsionaalselt lähedase TLC5940-ga:
… Andmete seadmesse sisestamiseks on vaja ainult kolme tihvti. SCLK signaali tõusev serv nihutab andmed SIN-viigust siseregistrisse. Pärast kõigi andmete laadimist lukustab lühike kõrge XLAT-signaal seeriaviisiliselt edastatud andmed sisemistes registrites. Sisemised registrid on väravad, mille käivitab XLAT signaali tase. Kõik andmed edastatakse kõigepealt MSB kaudu.
Riiv - riiv / riiv / riiv. Tõusev serv on impulsi esiserv MSB kõigepealt – kõige olulisem (vasakpoolseim) bitt ettepoole. kella andmeid – edastada andmeid järjestikku (bitihaaval).
Sõna riiv sageli leitakse kiipide dokumentatsioonist ja seda tõlgitakse mitmel viisil, nii et mõistmiseks luban endale
väike haridusprogrammLED-draiver on sisuliselt nihkeregister. "Shift" (suunata) nimes - andmete bitthaaval liikumine seadme sees: iga uus sisse lükatud bitt lükkab kogu keti enda ees ette. Kuna keegi ei taha jälgida LED-ide kaootilist vilkumist vahetuse ajal, siis toimub protsess puhverregistrites, mis on töötajatest katikuga eraldatud (riiv) on omamoodi riietusruum, kus bitid reastuvad soovitud järjekorras. Kui kõik on valmis, avaneb katik ja bitid lähevad tööle, asendades eelmise partii. Sõna riiv mikroskeemide dokumentatsioonis tähendab peaaegu alati sellist summutit, olenemata sellest, millistes kombinatsioonides seda kasutatakse.
Niisiis, andmete edastamine DM634-le toimub järgmiselt: seadke DAI sisend kaugema LED-i kõrge biti väärtusele, tõmmake DCK üles ja alla; seadke DAI sisendiks järgmise biti väärtus, tõmmake DCK; ja nii edasi, kuni kõik bitid on edastatud (sisse kellatanud), mille järel tõmbame LAT. Seda saab teha käsitsinatuke pauk), kuid selleks on parem kasutada spetsiaalselt teritatud SPI-liidest, kuna see on meie STM32-s kahes eksemplaris.
Sinine tahvelarvuti STM32F103
Sissejuhatus: STM32 kontrollerid on palju keerulisemad kui Atmega328, kui nad võivad olla hirmutavad. Samal ajal lülitatakse energiasäästu huvides alguses peaaegu kõik välisseadmed välja ja taktsagedus on 8 MHz sisemisest allikast. Õnneks kirjutasid STM-i programmeerijad koodi, mis toob kiibi "arvutatud" 72 MHz-le ja kõigi mulle teadaolevate IDE-de autorid lülitasid selle initsialiseerimisprotseduuri, nii et meil pole vaja kella (aga sa saad, kui sa tõesti tahad). Kuid peate välisseadmed sisse lülitama.
Dokumentatsioon: Blue Pillile on installitud populaarne STM32F103C8T6 kiip, selle jaoks on kaks kasulikku dokumenti:
Andmeleht mikrokontrolleritele STM32F103x8 ja STM32F103xB;
Pinouts - chip pinouts - juhuks, kui otsustame ise lauad teha;
Mälukaart – konkreetse kiibi mälukaart. Teatmejuhendis on kaart kogu rea kohta, seal on mainitud registreid, mida meie omas ei ole.
Pin Definitions tabel – peamiste ja alternatiivsete tihvtide funktsioonide loetelu; Internetist “sinise pilli” jaoks leiab mugavamaid pilte koos tihvtide ja nende funktsioonidega. Seetõttu guugeldame kohe Blue Pill pinouti ja hoiame seda pilti käepärast:
NB: pildil oli internetist tulnud viga, märgati kommentaarides, mille eest aitäh. Pilt on asendatud, kuid see on õppetund - parem on kontrollida teavet mitte andmelehtedelt.
Eemaldame andmelehe, avame Reference Manuali, edaspidi kasutame ainult seda.
Protseduur: tegelege standardse sisendi/väljundiga, konfigureerige SPI, lülitage sisse vajalikud välisseadmed.
Sisend väljund
Atmega328-l on I/O äärmiselt lihtne, mistõttu võib STM32 valikute rohkus segadusse ajada. Nüüd vajame ainult järeldusi, kuid isegi on neli võimalust:
Avatud äravoolu väljund, push-pull väljund, push-pull alternatiivne, avatud äravoolu alternatiivne
"Tõmba lükka" (tõukejõud) - Arduino tavaline väljund, tihvti väärtus võib olla kas HIGH või LOW. Kuid "avatud äravooluga" tekivad raskusi, kuigi tegelikult on siin kõik lihtne:
Väljundi konfiguratsioon / kui port on väljundile määratud: / väljundpuhver lubatud: / – avatud tühjendusrežiim: "0" väljundregistris lubab N-MOS-i, "1" väljundregistris jätab pordi Hi-Z režiimi (P -MOS ei ole aktiveeritud ) / - push-pull mode: "0" väljundregistris aktiveerib N-MOS, "1" väljundregistris aktiveerib P-MOS.
Kõik avatud äravoolu erinevus (avatud äravool) sõnast "push-pull" (tõukejõud) seisneb selles, et esimeses viigus ei saa see võtta HIGH olekut: kui üksus kirjutatakse väljundregistrisse, läheb see suure takistuse režiimi (kõrge takistus, Tere-Z). Nulli kirjutades käitub tihvt mõlemas režiimis ühtmoodi, nii loogiliselt kui ka elektriliselt.
Tavalises väljundrežiimis tõlgib pin lihtsalt väljundregistri sisu. "Alternatiivis" juhib seda vastav välisseade (vt 9.1.4):
Kui pordibitt on konfigureeritud alternatiivse funktsiooni väljundina, on väljundregister keelatud ja kontakt on ühendatud välisseadme väljundsignaaliga.
Iga tihvti alternatiivset funktsionaalsust kirjeldatakse artiklis PIN-ide definitsioonid Andmeleht on allalaaditud pildil. Küsimusele, mida teha, kui tihvtil on mitu alternatiivset funktsiooni, annab vastuse andmelehel joonealune märkus:
Kui mitu välisseadet kasutavad sama tihvti, tuleks alternatiivsete funktsioonide vahelise konflikti vältimiseks kasutada korraga ainult ühte välisseadet, mille ümberlülitamiseks kasutatakse bitti Peripheral Clock Enable (vastavas RCC registris).
Lõpuks on väljundrežiimis kontaktidel ka taktsagedus. See on veel üks energiasäästu funktsioon, meie puhul paneme selle lihtsalt maksimumile ja unustame ära.
Niisiis: me kasutame SPI-d, mis tähendab, et kaks kontakti (andmete ja kellasignaaliga) peaksid olema "alternatiivne push-pull funktsioon" ja veel üks (LAT) peaks olema "tavaline push-pull". Kuid enne nende määramist tegeleme SPI-ga.
SPI
Veel üks väike häkkimine
SPI ehk Serial Peripheral Interface (serial peripheral interface) on lihtne ja väga tõhus liides MK-ga suhtlemiseks teiste MK-dega ja välismaailmaga üldiselt. Selle tööpõhimõtet on juba eespool kirjeldatud, kus räägitakse Hiina LED-draiverist (vt juhendi jaotist 25). SPI võib töötada ülem- ("master") ja alam ("alluv") režiimides. SPI-l on neli põhikanalit, millest kõik ei pruugi olla seotud:
MOSI, põhiväljund / alluv sisend: see kontakt saadab andmeid ülemrežiimis ja võtab andmeid vastu alamrežiimis;
MISO, Master Input / Slave Output: vastupidi, ülemseadmes see võtab vastu, alamseadmes annab;
SCK, Serial Clock: määrab andmeedastuse sageduse ülemseadmes või võtab vastu alamseadmes kellasignaali. Sisuliselt lööb lööki;
SS, Slave Select: selle kanali puhul teab ori, et nad tahavad temalt midagi. STM32 peal nimetatakse seda NSS-iks, kus N = negatiivne, st. kontroller muutub alluvaks, kui sellel kanalil on maandus. See sobib hästi Open Drain Output režiimiga, kuid see on teine lugu.
Nagu kõik muu, on STM32 SPI-l palju funktsioone, mis muudab selle mõistmise mõnevõrra keeruliseks. Näiteks võib see töötada mitte ainult SPI-ga, vaid ka I2S-liidesega ja nende kirjeldused on dokumentatsioonis segatud, peate ülejäägid õigeaegselt ära lõikama. Meie ülesanne on äärmiselt lihtne: peate lihtsalt andma andmed ainult MOSI ja SCK abil. Läheme jaotisse 25.3.4 (pooldupleksside, pooldupleksside), kust leiame 1 kell ja 1 ühesuunaline andmejuhe (1 kell ja 1 ühesuunaline andmevoog):
Selles režiimis kasutab rakendus SPI-d kas ainult edastus- või ainult vastuvõturežiimis. / Ainult edastusrežiim sarnaneb dupleksrežiimiga: andmed edastatakse edastusviiul (MOSI ülemrežiimis või MISO alamrežiimis), samas kui vastuvõtuviiku (vastavalt MISO või MOSI) saab kasutada tavalise I/O-na. pin. Sel juhul piisab, kui rakendus ignoreerib Rx puhvrit (kui see loetakse, siis andmeid ei edastata).
Suurepärane, MISO pin on vaba, ühendame sellega LAT signaali. Tegeleme Slave Selectiga, mida saab STM32 pealt programmiliselt juhtida, mis on ülimugav. Samanimelist lõiku loeme jaotises 25.3.1 SPI üldkirjeldus:
NSS-i tarkvara juhtimine (SSM = 1) / Slave valiku teave sisaldub SPI_CR1 registri SSI-bitis. Väline NSS-i tihvt jäetakse vabaks muude rakenduste vajaduste jaoks.
On aeg registritesse kirjutada. Otsustasin kasutada SPI2, otsime selle baasaadressi andmelehelt - jaotisest 3.3 Mälukaart (mälukaart):
Avame jaotise 25.3.3 kõneka pealkirjaga "SPI konfigureerimine põhirežiimis":
1. Seadke jadaliidese kell SPI_CR2 registri BR[0:1] bittidega.
Registrid on kogutud samanimelisse teatmejuhendi jaotisesse. Aadressi nihe (aadressi nihe) CR1-l on 0x00, vaikimisi kustutatakse kõik bitid (Lähtesta väärtus 0x0000):
BR-bitid määravad kontrolleri kellajaguri, määrates nii sageduse, millega SPI töötab. STM32 sagedus on 72 MHz, LED-draiver töötab selle andmelehe järgi sagedusel kuni 25 MHz, seega peame jagama neljaga (BR[2:0] = 001).
2. Seadistage CPOL- ja CPHA-bitid, et määrata seos andmeedastuse ja jadaliidese kella vahel (vt diagrammi lk 240).
Kuna me loeme siin andmelehte, mitte ei vaata skeeme, siis vaatame lähemalt CPOL- ja CPHA-bittide tekstilist kirjeldust leheküljel 704 (SPI üldkirjeldus):
Kella faas ja polaarsus
Kasutades SPI_CR1 registri CPOL- ja CPHA-bitte, saate programmiliselt valida neli ajastussuhte valikut. CPOL (Clock Polarity) bitt juhib kella signaali olekut, kui andmeid ei edastata. See bitt juhib ülem- ja alamrežiime. Kui CPOL lähtestatakse, on SCK viik puhkeolekus madal. Kui CPOL-bitt on seatud, on SCK-viik jõudeoleku ajal kõrgel.
Kui CPHA (Clock Phase) bitt on seatud, on MSB trap strobo SCK signaali teine serv (langeb, kui CPOL on kustutatud, või tõusev serv, kui CPOL on seatud). Andmed lukustatakse teisel kellavahetusel. Kui CPHA-bitt on kustutatud, toimib SCK-signaali tõusev serv (langev serv, kui CPOL on seatud, või tõusev serv, kui CPOL on tühi) kõrge bitilõksu strobina. Andmed lukustatakse esimesel kellavahetusel.
Olles seda teadmist maitsnud, jõuame järeldusele, et mõlemad bitid peavad jääma nulliks, sest tahame, et SCK-signaal jääks madalaks, kui seda ei kasutata, ja andmeid edastataks impulsi tõusval serval (vt joonis XNUMX). Tõusev serv andmelehel DM634).
Muide, siin kohtasime esmakordselt ST-andmete lehtede sõnavara omadust: neis on kirjutatud fraas "reset the bit to zero". natukene lähtestadaJa mitte natuke puhastada, nagu näiteks Atmega.
3. 8-bitise või 16-bitise andmeploki vormingu määramiseks määrake DFF-bitt
Võtsin konkreetselt 16-bitise DM634, et mitte vaeva näha 12-bitiste PWM-andmete edastamisega, nagu DM633. DFF-i on mõttekas ühendada:
4. Konfigureerige LSBFIRST bitt SPI_CR1 registris, et määrata ploki vorming
LSBFIRST, nagu nimigi viitab, seadistab edastuse esmalt kõige vähem olulise bitiga. Kuid DM634 soovib esmalt saada andmeid MSB-st. Seetõttu jätame selle lähtestama.
5. Riistvararežiimis, kui on vaja sisendit NSS-i viigust, juhtige NSS-i viik kõrgele kogu baidiedastusjada jooksul. NSS-programmirežiimis määrake SSM- ja SSI-bitid SPI_CR1-registris. Kui NSS-i viik tuleb väljastada, tuleb määrata ainult SSOE-bitt.
Installige SSM ja SSI, et unustada NSS-i riistvararežiim:
#define SSI 0x0100
#define SSM 0x0200
_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high
6. MSTR ja SPE bitid tuleb seadistada (need jäävad seadistatuks ainult siis, kui NSS on kõrge)
Tegelikult määrame nende bittide abil oma SPI-d ülemseadmeks ja lülitame selle sisse:
SPI on seadistatud, kirjutame kohe funktsioonid, mis saadavad draiverile baite. Loe edasi 25.3.3 "SPI konfigureerimine põhirežiimis":
Andmeedastusprotseduur
Edastamine algab siis, kui bait kirjutatakse Tx-puhvrisse.
Andmebait laaditakse nihkeregistrisse kell paralleelselt režiimis (sisemisest siinist) esimese biti edastamise ajal, misjärel see edastatakse järjekindel MOSI viigu režiim, esimene või viimane bitt edasi, sõltuvalt LSBFIRST biti seadistusest registris CPI_CR1. TXE lipp määratakse pärast andmeedastust Tx puhvrist nihkeregistrisse, ja katkestus genereeritakse, kui TXEIE bitt CPI_CR1 registris on seatud.
Tõlkes tõstsin esile paar sõna, et juhtida tähelepanu ühele SPI-i juurutamise tunnusele STM-kontrollerites. Atmegal on TXE lipp (Tx tühi, Tx on tühi ja valmis andmete vastuvõtmiseks) määratakse alles pärast kogu baidi saatmist väljapoole. Ja siin pannakse see lipp pärast seda, kui bait on sisestatud sisemisse nihkeregistrisse. Kuna see lükatakse sinna kõigi bittidega korraga (paralleelselt) ja seejärel edastatakse andmed järjestikku, siis seadistatakse TXE enne, kui bait on täielikult saadetud. See on oluline, sest meie LED-draiveri puhul peame pärast saatmist tõmbama LAT-tihvti Kõik andmed, s.t. ainult TXE lipust meile ei piisa.
Mis tähendab, et vajame teist lippu. Vaatame 25.3.7 - "Oleklipud":
<…>
HÄIVATUD lipp
BSY lipu määrab ja kustutab riistvara (sellele kirjutamine ei mõjuta). BSY lipp näitab SPI sidekihi olekut.
See lähtestab:
kui ülekanne on lõppenud (välja arvatud põhirežiimis, kui ülekanne on pidev)
kui SPI on keelatud
kui ilmneb põhirežiimi tõrge (MODF=1)
Kui edastamine ei ole pidev, kustutatakse BSY lipp iga andmeedastuse vahel.
Olgu, see tuleb kasuks. Uurige, kus asub Tx-puhver. Selleks lugege "SPI andmeregistrit":
Bitid 15:0 DR[15:0] Andmeregister
Vastuvõetud või edastatavad andmed.
Andmeregister on jagatud kaheks puhvriks, millest üks on kirjutamiseks (edastuspuhver) ja teine lugemiseks (vastuvõtupuhver). Andmeregistrisse kirjutamine kirjutab Tx puhvrisse ja andmeregistrist lugemine tagastab Rx puhvris sisalduva väärtuse.
Noh, kuna peame vastavalt LED-draiveri väljundite arvule üle kandma 16 korda kaks baiti, siis midagi sellist:
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();
}
Kuid me ei tea veel, kuidas LAT-i tihvti tõmmata, nii et läheme tagasi I/O juurde.
Määrake tihvtid
STM32F1-s on kontaktide oleku eest vastutavad registrid üsna ebatavalised. Selge on see, et neid on rohkem kui Atmega, kuid need erinevad ka teistest STM kiipidest. Jaotis 9.1 GPIO Üldkirjeldus:
Kõik üldotstarbelised I/O-pordid (GPIO) sellel on kaks 32-bitist konfiguratsiooniregistrit (GPIOx_CRL ja GPIOx_CRH), kaks 32-bitist andmeregistrit (GPIOx_IDR ja GPIOx_ODR), 32-bitine seadistus-/lähtestusregister (GPIOx_BSRR), 16-bitine lähtestusregister (GPIOx_BRR) ja 32-bitine seadistusregister (GPIOx_BSRR). bitiblokeerimisregister (GPIOx_LCKR).
Ebatavalised ja ka üsna ebamugavad on siin kaks esimest registrit, sest pordi 16 viiku on nende vahel laiali “neli bitti venna kohta” formaadis. Need. tihvtid XNUMX kuni XNUMX on CRL-is ja ülejäänud on CRH-s. Samal ajal sobivad ülejäänud registrid edukalt kõigi pordi viigude bittidega - sageli jäävad need pooleks "reserveeritud".
Lihtsuse huvides alustame loendi lõpust.
Me ei vaja blokeerimisregistrit.
Seadistamise ja lähtestamise registrid on üsna naljakad selle poolest, et nad dubleerivad üksteist osaliselt: kõike saab kirjutada ainult BSRR-is, kus ülemised 16 bitti lähtestavad viigu nulli ja alumised seatakse 1-le või saate ka kasutage BRR-i, mille alumised 16 bitti lähtestavad ainult viigu . Mulle meeldib teine variant. Need registrid on olulised, kuna need pakuvad tihvtidele aatomi juurdepääsu:
Aatomi installimine või lähtestamine
GPIOx_ODR-i bititasemel programmeerimisel ei pea te katkestusi keelama: saate muuta üht või mitut bitti ühe APB2 aatomikirjutusoperatsiooniga. See saavutatakse, kirjutades "1" muudetava biti seadistus-/lähtestamisregistrisse (GPIOx_BSRR või ainult lähtestamise korral GPIOx_BRR). Muud bitid jäävad muutumatuks.
Andmeregistritel on üsna kõnekad nimed – IDR = Sisend Suunaregister, sisestusregister; ODR= Väljund Suunaregister, väljundregister. Praeguses projektis me neid ei vaja.
Ja lõpuks, kontrollregistrid. Kuna meid huvitavad teise SPI kontaktid, nimelt PB13, PB14 ja PB15, vaatame kohe CRH-i:
Ja me näeme, et 20.-31. kuupäevast tuleb midagi bitti kirjutada.
Saime juba ülaltoodud kontaktidest aru, mida tahame, nii et siin teen ilma ekraanipildita, ütlen lihtsalt, et MODE määrab suuna (sisend, kui mõlemad bitid on seatud 0-le) ja viigu kiiruse (me vajame 50MHz, st. mõlemad tihvtid väärtusele "1") ja CNF seab režiimi: tavaline "push-push" - 00, "alternative" - 10. Vaikimisi, nagu näeme ülalt, on kõigil kontaktidel kolmas bitt altpoolt ( CNF0), see seab need režiimi ujuv sisend.
Kuna plaanin selle kiibiga midagi muud teha, siis lihtsuse mõttes defineerisin üldiselt kõik võimalikud MODE ja CNF väärtused nii alumise kui ka ülemise juhtregistri jaoks.
(LAT_madal lihtsalt inertsist, kuidagi alati oli, las see jääb endale)
Nüüd on kõik suurepärane, kuid see ei tööta. Kuna see on STM32, säästavad nad siin elektrit, mis tähendab, et peate sisse lülitama vajalike välisseadmete kella.
Lülitage kellaaeg sisse
Kell vastutab kellaajamise eest, nemad on ka Kell. Ja juba võisime märgata lühendit RCC. Otsime seda dokumentatsioonist: see on Reset ja Clock Control (lähtestamise ja kellaaja haldamine).
Nagu eelpool mainitud, siis õnneks tegid STM-i inimesed meie jaoks kõige raskema osa kellatamise teemast, mille eest suur tänu neile (panen taaskord lingi Di Halti veebisaitet oleks selge, kui segane see on). Vajame ainult registreid, mis vastutavad välisseadmete kellastamise lubamise eest (Peripheral Clock Enable Registers). Esiteks leiame RCC baasaadressi, see asub "Mälukaardi" alguses:
Ja seejärel klõpsake lingil, kust tabelist midagi otsida, või, palju parem, vaadake üle hõlmavate registrite kirjeldused jaotistest lubada registrid. Kust leiame RCC_APB1ENR ja RCC_APB2ENR:
Ja nendes vastavalt bitid, mis sisaldavad SPI2, IOPB (I / O-port B) ja alternatiivsete funktsioonide (AFIO) takti.
Kui on võimalus ja soov testida, siis ühendame DM634 nii: DAI PB15 külge, DCK PB13 külge, LAT PB14 külge. Toidame juhti 5 voltist, ärge unustage maandusi kombineerida.
STM8 PWM
PWM STM8-l
Kui ma just seda artiklit kavandasin, otsustasin näiteks proovida mõne harjumatu kiibi funktsionaalsust meisterdada vaid andmelehe abil, et kingsepp ilma saabasteta välja ei tuleks. STM8 sobis sellesse rolli suurepäraselt: esiteks oli mul paar hiina tahvlit STM8S103-ga, teiseks pole see eriti populaarne ning seetõttu toetub kiusatus internetist lugeda ja lahendus leida just nende samade lahenduste puudumisel.
Vaikimisi töötab STM8 sagedusel 2 MHz, see tuleb kohe parandada.
HSI kell (kõrge sisemine)
HSI kell on tuletatud sisemisest 16 MHz RC-ostsillaatorist, millel on programmeeritav jagur (1 kuni 8). See on määratud kellajaguri registris (CLK_CKDIVR).
Märkus: HSI RC ostsillaator jaguriga 8 valitakse käivitamisel peamise kella allikaks.
Leiame andmelehelt registri aadressi, refmanis kirjelduse ja näeme, et register vajab tühjendamist:
Kuna kavatseme käivitada PWM-i ja ühendada LED-id, vaatame pinouti:
Kiip on väike, paljud funktsioonid on riputatud samadele tihvtidele. See, mis on nurksulgudes, on "alternatiivne funktsionaalsus", seda vahetavad "valikubaitid" (valikubaidid) – midagi Atmega kaitsmete sarnast. Saate nende väärtusi programmiliselt muuta, kuid see pole vajalik, sest. Uus funktsioon aktiveeritakse alles pärast taaskäivitamist. Lihtsam on kasutada ST Visual Programmerit (allalaaditud koos Visual Developiga), mis saab neid baite muuta. Pinout näitab, et esimese taimeri väljundid CH1 ja CH2 on peidetud nurksulgudesse; STVP-s on vaja seadistada AFR1 ja AFR0 bitid ning teine kannab ka teise taimeri väljundi CH1 PD4-lt PC5-le.
Seega juhivad LED-e 6 kontakti: PC6, PC7 ja PC3 esimese taimeri jaoks, PC5, PD3 ja PA3 teise jaoks.
STM8 sisend- ja väljundviikude endi seadistamine on lihtsam ja loogilisem kui STM32 puhul:
Atmega tuttav andmete suunaregister DDR (Andmete suuna register): 1 = väljund;
esimene juhtregister CR1 seab väljastamisel push-pull režiimi (1) või avatud äravoolu (0); kuna ühendan LED-id kiibiga katoodidega, siis jätan siia nullid;
teine juhtregister CR2 määrab väljastamisel taktsageduse: 1 = 10 MHz
Automaatne uuesti laadimine, AR – automaatselt laaditud väärtus, milleni taimer loeb (impulsiperiood);
Värskenda sündmust, UEV – sündmus, mis leiab aset siis, kui taimer on AR-le lugenud;
PWM töötsükkel - PWM-i töötsükkel, mida sageli nimetatakse "töötsükliks";
Jäädvusta/võrdle väärtust – jäädvustamise/võrdlemise väärtus, milleni loendatakse taimer teeb midagi (PWM-i puhul inverteerib väljundsignaali);
eellaadimise väärtus – eelsalvestatud väärtus. väärtust võrrelda ei saa muuta, kui taimer tiksub, vastasel juhul katkeb PWM-tsükkel. Seetõttu asetatakse uued edastatud väärtused puhvrisse ja tõmmatakse välja, kui taimer jõuab loenduse lõpuni ja lähtestatakse;
Servad joondatud и Keskjoondatud režiimid – joondus piiril ja keskel, sama mis atmelovskie Kiire PWM и Faasikorrektne PWM.
OCiREF, väljundi võrdlussignaal - võrdlusväljundsignaal, tegelikult see, mis kuvatakse PWM-režiimis vastaval viigul.
Nagu pinoutist juba selgub, on kahel taimeril PWM-võimalused - esimesel ja teisel. Mõlemad on 16-bitised, esimesel on palju lisafunktsioone (eelkõige võib see lugeda nii üles kui ka alla). Meil on vaja mõlemat ühtemoodi töötada, seega otsustasin alustada ilmselgelt kehvemast teisest, et mitte kogemata kasutada midagi, mida selles pole. Mõningane probleem on selles, et kõigi taimerite PWM-i funktsionaalsuse kirjeldus viitejuhendis on esimest taimerit käsitlevas peatükis (17.5.7 PWM-režiim), seega peate kogu aeg dokumendis edasi-tagasi hüppama.
STM8 PWM-il on Atmega PWM-i ees oluline eelis:
PWM servade joondamisega
Konto seadistamine alt üles
Ülesloendamine on aktiivne, kui DIR-bitt TIM_CR1 registris on selge
Näide
Näites kasutatakse esimest PWM-režiimi. PWM-i tugisignaali OCiREF hoitakse kõrgel seni, kuni TIM1_CNT < TIM1_CCRI. Vastasel juhul võtab see madala taseme. Kui võrreldav väärtus TIM1_CCRI registris on suurem kui automaatse laadimise väärtus (TIM1_ARR register), hoitakse OCiREF signaali väärtusel 1. Kui võrdlusväärtus on 0, hoitakse OCiREF nullis....
STM8 taimer ajal värskenda sündmust kontrollib kõigepealt väärtust võrreldaja alles siis toodab võrdlussignaali. Atmegas ajab taimer esmalt värisema ja seejärel võrdleb, mille tulemusena millal compare value == 0 väljundiks on nõel, millega peab kuidagi hakkama saama (näiteks programmiliselt loogikat ümber pöörates).
Mida me teha tahame: 8-bitine PWM (AR == 255), lugedes alt üles, joondus piki piiri. Kuna pirnid on kiibiga ühendatud katoodidega, peaks PWM väljastama 0 (LED põleb), kuni väärtust võrrelda ja 1 pärast.
Mõne kohta oleme juba lugenud PWM-režiim, nii et leiame teise taimeri soovitud registri, otsides teatmejuhendist seda fraasi (18.6.8 - TIMx_CCMR1):
110: Esimene PWM-režiim – alt üles loendamisel on esimene kanal aktiivne seni, kuni TIMx_CNT < TIMx_CCR1. Vastasel juhul on esimene kanal passiivne. [dokumendis edasi, ekslik kopeeri-kleebi taimer 1] 111: Teine PWM-režiim – alt üles loendamisel on esimene kanal passiivne kuni TIMx_CNT < TIMx_CCR1. Vastasel juhul on esimene kanal aktiivne.
Kuna LED-id on MK-ga ühendatud katoodidega, siis teine režiim sobib meile (esimene ka, aga seda me veel ei tea).
Bitt 3 OC1PE: lubage 1. väljundi eellaadimine
0: TIMx_CCR1 eellaadimisregister on keelatud. Saate igal ajal kirjutada aadressile TIMx_CCR1. Uus väärtus töötab kohe.
1: TIMx_CCR1 eellaadimisregister on lubatud. Lugemis-/kirjutustoimingud pääsevad juurde eellaadimisregistrisse. TIMx_CCR1 eellaaditud väärtus laaditakse iga värskendussündmuse ajal variregistrisse.
*Märkus. PWM-režiimi nõuetekohaseks toimimiseks peavad eellaadimisregistrid olema lubatud. See on ühe signaali režiimis valikuline (OPM-bitt on seatud registris TIMx_CR1).
Olgu, lülitage sisse kõik, mida vajate teise taimeri kolme kanali jaoks:
Teine taimer saab lugeda ainult alt üles, joondus piiril, midagi muuta ei pea. Seadke sagedusjagur näiteks 256-le. Teise taimeri jaoks määratakse jagur registris TIM2_PSCR ja see on kahe astmega:
Jääb järeldused ja teine taimer ise sisse lülitada. Esimene ülesanne on lahendatud registrite abil Jäädvusta/võrdle Võimaldama: neid on kaks, nende peale on asümmeetriliselt hajutatud kolm kanalit. Siit saame ka teada, et on võimalik muuta signaali polaarsust, s.t. põhimõtteliselt võiks kasutada ka PWM režiimi 1. Kirjutame:
Kirjutame AnalogWrite'i () lihtsa analoogi, mis edastab tegelikud väärtused võrdluseks taimerile. Registrid on ettearvatavalt nimelised Registrite hõivamine/võrdlemine, on neid iga kanali jaoks kaks: madalad 8 bitti TIM2_CCRxL-s ja kõrged bitid TIM2_CCRxH-s. Kuna alustasime 8-bitise PWM-iga, piisab ainult madalate bittide kirjutamisest:
Tähelepanelik lugeja märkab, et meil on pisut defektne PWM, mis ei suuda 100% täitmist välja anda (maksimaalse väärtuse 255 korral pööratakse signaal ühe taimeritsükli võrra ümber). LED-ide puhul see rolli ei mängi ja tähelepanelik lugeja aimab juba ära, kuidas seda parandada.
Teise taimeriga PWM töötab, minge esimese juurde.
Esimesel taimeris on täpselt samad bitid samades registrites (lihtsalt neid bitte, mis teises taimeris "reserveeritud" jäid, kasutatakse esimeses aktiivselt igasuguste edasijõudnute jaoks). Seetõttu piisab, kui leida andmelehel samade registrite aadressid ja kopeerida kood. Noh, muuda sagedusjaguri väärtust, sest. esimene taimer tahab saada kahes registris mitte kahe astme, vaid täpse 16-bitise väärtuse Eelskaala kõrge и Madal. Teeme kõike ja ... esimene taimer ei tööta. Mis viga?
Ainus viis probleemi lahendamiseks on vaadata kogu jaotist taimeri 1 juhtimisregistrite kohta, kus otsime sellist, mida teisel taimeril pole. tuleb 17.7.30 Rikete register (TIM1_BKR), kus on natuke selline:
Kolmas miniprojekt on ühendada kaheksa RGB LED-i teise taimeriga PWM-režiimis ja panna need näitama erinevaid värve. See põhineb LED-multipleksimise kontseptsioonil, mis seisneb selles, et kui lülitate LED-id väga-väga kiiresti sisse ja välja, tundub meile, et need põlevad pidevalt (nägemise püsivus, visuaalse taju inerts). Kunagi tegin midagi sellist arduino peal.
Töö algoritm näeb välja selline:
ühendas esimese RGB LED-i anood;
valgustage see, andes katoodidele vajalikke signaale;
ootas PWM-tsükli lõppu;
ühendatud teise RGB LED-i anood;
süütas selle...
No jne. Muidugi on ilusa töö jaoks vajalik, et anoodiühendus ja LED-i "süütamine" toimuksid samaaegselt. Noh, peaaegu. Igal juhul peame kirjutama koodi, mis väljastab väärtused teise taimeri kolmes kanalis, muutma neid, kui UEV on saavutatud, ja samal ajal muutma hetkel aktiivset RGB LED-i.
Kuna LED-i lülitus on automaatne, peate looma "videomälu", kust katkestuse töötleja andmeid saab. See on lihtne massiiv:
uint8_t colors[8][3];
Konkreetse LED-i värvi muutmiseks piisab, kui kirjutada sellesse massiivi vajalikud väärtused. Ja muutuja vastutab aktiivse LED-i arvu eest
uint8_t cnt;
Demux
Korralikuks multipleksimiseks vajame kummalisel kombel CD74HC238 demultiplekserit. Demultiplekser - kiip, mis rakendab operaatori riistvaras <<. Kolme sisendviigu (bitid 0, 1 ja 2) kaudu anname talle ette kolmebitise numbri X ja vastuseks aktiveerib ta väljundnumbri (1<<X). Ülejäänud kiibi sisendeid kasutatakse kogu disaini skaleerimiseks. Seda kiipi vajame mitte ainult mikrokontrolleri hõivatud tihvtide arvu vähendamiseks, vaid ka ohutuse tagamiseks - et mitte kogemata sisse lülitada rohkem LED-e kui võimalik ja mitte põletada MK-d. Kiip maksab senti, seda tuleks alati kodus esmaabikomplektis hoida.
CD74HC238 vastutab soovitud LED-i anoodi pinge andmise eest. Täisväärtuslikus multipleksis annaks see P-MOSFET-i kaudu kolonni pinget, kuid selles demos saate seda teha otse, sest. see tõmbab vastavalt 20mA absoluutsed maksimumhinnangud andmelehel. Alates andmeleht CD74HC238 vajame pinouti ja seda petulehte:
H = kõrge pinge tase, L = madalpinge tase, X - ei huvita
Ühendame E2 ja E1 maandusega, E3, A0, A1 ja A3 STM5 kontaktidega PD3, PC4, PC5 ja PC8. Kuna ülaltoodud tabel sisaldab nii madalaid kui ka kõrgeid tasemeid, seadistasime need tihvtid push-pull tihvtidena.
PWM
Teise taimeriga PWM on konfigureeritud samamoodi nagu eelmises loos, kahe erinevusega:
Esiteks peame lubama katkestuse Värskenda sündmust (UEV), mis kutsub välja funktsiooni aktiivse LED-i ümberlülitamiseks. Seda tehakse biti muutmisega Värskenda katkestuse lubamine kõneleva nimega registris
Teine erinevus on seotud sellise multipleksimise nähtusega nagu ghosting - dioodide parasiitne sära. Meie puhul võib see ilmneda sellest, et UEV-s katkestuse tekitanud taimer tiksub edasi ja katkestuste töötlejal pole aega LED-i enne vahetada, kui taimer hakkab midagi väljunditesse kirjutama. Selle vastu võitlemiseks peate loogika ümber pöörama (0 = maksimaalne heledus, 255 = midagi pole sisse lülitatud) ja mitte lubama äärmuslikke töötsükli väärtusi. Need. tagage, et pärast UEV-d on LED-id täielikult kustunud üheks PWM-tsükliks.
Vältige väärtuste r, g ja b seadmist väärtusele 255 ning ärge unustage neid kasutamise ajal ümber pöörata.
Katkestab
Katkestuse olemus seisneb selles, et teatud asjaoludel lõpetab kiip põhiprogrammi täitmise ja kutsub välja mõne välise funktsiooni. Katkestused tekivad väliste või sisemiste mõjude, sealhulgas taimeri mõju tõttu.
Kui me esimest korda ST Visual Developi projekti lõime, välja arvatud main.c saime akna salapärase failiga stm8_interrupt_vector.cautomaatselt projekti kaasatud. Selles failis on igale katkestusele lisatud funktsioon NonHandledInterrupt. Peame oma funktsiooni siduma soovitud katkestusega.
Andmelehel on katkestusvektorite tabel, kust leiame need, mida vajame:
Ja lõpuks kirjutage see funktsioon oma sisse 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;
}
Järele jääb katkestuste lubamine. Seda tehakse käsuga assembler. rim - peate selle sealt otsima Programmeerimisjuhend:
//enable interrupts
_asm("rim");
Veel üks monteerija juhend - sim - Lülitab katkestused välja. Uute väärtuste "videomällu" kirjutamise ajal tuleb need keelata, et kahetsusväärsel hetkel tekkinud katkestus massiivi ei rikuks.
Kui vähemalt kellelegi on see artikkel kasulik, siis ma ei kirjutanud seda asjata. Mul on hea meel kommentaaride ja märkuste vastu, proovin vastata kõigile.