Přečtěte si datové listy 2: SPI na STM32; PWM, časovače a přerušení na STM8
В první část Snažil jsem se říci hobby inženýrům elektroniky, kteří vyrostli z kalhot Arduino, jak a proč by měli číst datové listy a další dokumentaci k mikrokontrolérům. Text se ukázal být velký, a tak jsem slíbil praktické ukázky ukázat v samostatném článku. No, říkal si mléčná houba...
Dnes vám ukážu, jak pomocí datasheetů řešit celkem jednoduché, ale pro mnoho projektů nezbytné úlohy na ovladačích STM32 (Blue Pill) a STM8. Všechny demo projekty jsou věnovány mým oblíbeným LEDkám, budeme je svítit ve velkém, k čemuž budeme muset použít nejrůznější zajímavé periferie.
Text se opět ukázal jako obrovský, takže pro pohodlí tvořím obsah:
Upozornění: Nejsem inženýr, nepředstírám hluboké znalosti v elektronice, článek je určen pro amatéry, jako jsem já. Ve skutečnosti jsem se před dvěma lety považoval za cílovou skupinu. Kdyby mi tehdy někdo řekl, že datasheety na neznámém čipu nejsou děsivé na čtení, nestrávil bych spoustu času hledáním nějakých kousků kódu na internetu a vymýšlením berlí s nůžkami a lepicí páskou.
Tento článek se zaměřuje na datové listy, nikoli na projekty, takže kód nemusí být příliš úhledný a často stísněný. Samotné projekty jsou velmi jednoduché, i když vhodné pro první seznámení s novým čipem.
Doufám, že můj článek někomu pomůže v podobné fázi ponoření se do koníčka.
STM32
16 LED s DM634 a SPI
Malý projekt využívající Blue Pill (STM32F103C8T6) a ovladač DM634 LED. Pomocí datasheetů zjistíme ovladač, STM IO porty a nakonfigurujeme SPI.
DM634
Tchajwanský čip s 16 16bitovými PWM výstupy, lze zapojit do řetězců. Low-endový 12bitový model je znám z tuzemského projektu Lightpack. Kdysi, když jsem se rozhodoval mezi DM63x a známým TLC5940, jsem si vybral DM z několika důvodů: 1) TLC na Aliexpress je určitě falešné, ale toto není; 2) DM má autonomní PWM s vlastním frekvenčním generátorem; 3) dalo by se to koupit levně v Moskvě, než čekat na balíček od Ali. A samozřejmě bylo zajímavé naučit se ovládat čip sami, než používat hotovou knihovnu. Čipy jsou nyní prezentovány především v balení SSOP24, lze je snadno připájet k adaptéru.
Protože výrobce je Tchaj-wan, datový list čip je napsán v čínské angličtině, což znamená, že to bude zábava. Nejprve se podíváme na pinout (Pin připojení), abyste pochopili, ke které noze co připojit, a popis kolíků (Popis kolíku). 16 pinů:
Zdroje stejnosměrného umyvadla (otevřený odtok)
Dřez / Výstup s otevřeným odtokem – odtok; zdroj přitékajícího proudu; výstup je v aktivním stavu spojen se zemí - LED jsou k budiči připojeny katodami. Elektricky se samozřejmě nejedná o „otevřený odtok“ (otevřený odtok), ale v datasheetech se toto označení pro piny v režimu vypouštění často vyskytuje.
Externí odpory mezi REXT a GND pro nastavení hodnoty výstupního proudu
Mezi pin REXT a zem je instalován referenční rezistor, který řídí vnitřní odpor výstupů, viz graf na straně 9 datového listu. V DM634 lze tento odpor ovládat také softwarově, nastavením celkového jasu (globální jas); V tomto článku nebudu zacházet do podrobností, jen sem vložím odpor 2.2 - 3 kOhm.
Abychom pochopili, jak ovládat čip, podívejme se na popis rozhraní zařízení:
Jo, tady to je, čínská angličtina v celé své kráse. Přeložit to je problematické, můžete to pochopit, pokud chcete, ale existuje i jiný způsob - podívejte se, jak je připojení k funkčně podobnému TLC5940 popsáno v datovém listu:
... Pro zadávání dat do zařízení jsou potřeba pouze tři piny. Náběžná hrana signálu SCLK posouvá data z pinu SIN do vnitřního registru. Po načtení všech dat krátký vysoký signál XLAT zachytí postupně přenášená data do interních registrů. Vnitřní registry jsou brány spouštěné úrovní signálu XLAT. Všechna data jsou přenášena nejvýznamnější bit jako první.
Blokovat – západka/zámek/zámek. Stoupající hrana – náběžná hrana pulsu Nejprve MSB – nejvýznamnější (zcela vlevo) bit vpřed. na hodinová data – přenášet data postupně (bit po bitu).
Slovo závora se často nachází v dokumentaci k čipům a různě se překládá, takže si pro pochopení dovolím
malý vzdělávací programOvladač LED je v podstatě posuvný registr. "Shift" (posun) v názvu - bitový pohyb dat uvnitř zařízení: každý nový bit vsunutý dovnitř tlačí celý řetězec dopředu před sebe. Protože nikdo nechce pozorovat chaotické blikání LED během směny, proces probíhá ve vyrovnávacích registrech oddělených od pracovních registrů tlumičem (závora) je druh čekárny, kde jsou bity uspořádány v požadovaném pořadí. Když je vše připraveno, závěrka se otevře a bity se dají do práce a nahradí předchozí dávku. Slovo závora v dokumentaci pro mikroobvody téměř vždy předpokládá takový tlumič, bez ohledu na to, v jakých kombinacích se používá.
Přenos dat do DM634 se tedy provádí takto: nastavte vstup DAI na hodnotu nejvýznamnějšího bitu vzdálené LED, vytáhněte DCK nahoru a dolů; nastavte vstup DAI na hodnotu dalšího bitu, vytáhněte DCK; a tak dále, dokud nebudou přeneseny všechny bity (zapsáno), načež vytáhneme LAT. To lze provést ručně (bit-bang), ale je lepší použít rozhraní SPI speciálně přizpůsobené tomuto účelu, protože je na našem STM32 prezentováno ve dvou kopiích.
Modrá pilulka STM32F103
Úvod: Kontroléry STM32 jsou mnohem složitější než Atmega328, než by se mohlo zdát děsivé. Navíc z důvodu úspory energie jsou při startu téměř všechny periferie vypnuty a taktovací frekvence je 8 MHz z interního zdroje. Naštěstí programátoři STM napsali kód, který čip přivede na „vypočítaných“ 72 MHz a autoři všech IDE, které znám, jej zahrnuli do inicializační procedury, takže nemusíme taktovat (ale můžete, pokud opravdu chcete). Budete ale muset zapnout periferie.
Dokumentace: Blue Pill je vybavena oblíbeným čipem STM32F103C8T6, existují k němu dva užitečné dokumenty:
List pro mikrokontroléry STM32F103x8 a STM32F103xB;
Pinouts – chip pinouts – v případě, že se rozhodneme desky vyrobit sami;
Memory Map – mapa paměti pro konkrétní čip. Referenční příručka má mapu celé linky a zmiňuje registry, které ten náš nemá.
Tabulka definic pinů – seznam hlavních a alternativních funkcí pinů; pro „modrou pilulku“ najdete na internetu pohodlnější obrázky se seznamem pinů a jejich funkcí. Proto si okamžitě vygooglujeme Blue Pill pinout a máme tento obrázek po ruce:
Pozn.: na obrázku z internetu byla chyba, která byla uvedena v komentářích, děkuji za to. Obrázek byl nahrazen, ale toto je poučení - je lepší zkontrolovat informace, které nejsou z datasheetů.
Odebereme datový list, otevřeme referenční příručku a od této chvíle používáme pouze ji.
Postup: vyřídíme standardní vstup/výstup, nakonfigurujeme SPI, zapneme potřebné periferie.
Vstup výstup
Na Atmega328 je I/O implementován extrémně jednoduše, a proto může být množství možností STM32 matoucí. Nyní potřebujeme pouze závěry, ale i ty mají čtyři možnosti:
"Táhni-tlač" (tlačit táhnout) je obvyklý výstup z Arduina, pin může mít hodnotu buď HIGH nebo LOW. Ale s „otevřeným odtokem“ existují potíže, i když ve skutečnosti je zde vše jednoduché:
Konfigurace výstupu / když je port přiřazen k výstupu: / výstupní vyrovnávací paměť povolena: / – režim otevřeného odčerpávání: „0“ ve výstupním registru povolí N-MOS, „1“ ve výstupním registru ponechá port v režimu Hi-Z ( P-MOS není aktivován ) / – režim push-pull: „0“ ve výstupním registru aktivuje N-MOS, „1“ ve výstupním registru aktivuje P-MOS.
Celý rozdíl mezi otevřeným odtokem (otevřený odtok) z „push-pull“ (tlačit táhnout) je, že na prvním kolíku nemůže přijmout stav HIGH: při zápisu jedničky do výstupního registru přejde do režimu vysokého odporu (vysoká impedance, Ahoj-Z). Při zápisu nuly se pin chová v obou režimech stejně, jak logicky, tak i elektricky.
V normálním výstupním režimu pin jednoduše vysílá obsah výstupního registru. V "alternativě" je řízena odpovídajícími periferiemi (viz 9.1.4):
Pokud je bit portu nakonfigurován jako kolík alternativní funkce, registr kolíků je deaktivován a kolík je připojen k kolíku periferie.
Alternativní funkčnost každého pinu je popsána v Definice pinů Datasheet je na staženém obrázku. Na otázku, co dělat, když má pin několik alternativních funkcí, je odpověď uvedena poznámkou pod čarou v datovém listu:
Pokud více periferních zařízení používá stejný pin, aby se předešlo konfliktu mezi alternativními funkcemi, měla by být současně používána pouze jedna periferie, přepínaná pomocí bitu povolení periferních hodin (v příslušném registru RCC).
A konečně, piny ve výstupním režimu mají také takt. Toto je další funkce pro úsporu energie; v našem případě ji nastavíme na maximum a zapomeneme na to.
Takže: používáme SPI, což znamená, že dva piny (s daty a hodinovým signálem) by měly být „alternativní funkce push-pull“ a další (LAT) by měl být „regular push-pull“. Než je ale přiřadíme, pojďme se zabývat SPI.
SPI
Další malý vzdělávací program
SPI neboli Serial Peripheral Interface (sériové periferní rozhraní) je jednoduché a velmi efektivní rozhraní pro propojení MK s jinými MK a vnějším světem obecně. Princip jeho činnosti již byl popsán výše, kde o čínském ovladači LED (v referenční příručce, viz část 25). SPI může pracovat v režimu master („master“) a slave („slave“). SPI má čtyři základní kanály, z nichž ne všechny lze použít:
MOSI, Master Output / Slave Input: tento pin přenáší data v master režimu a přijímá data v slave režimu;
MISO, Master Input / Slave Output: naopak přijímá v masteru a vysílá v slave;
SCK, Serial Clock: nastavuje frekvenci přenosu dat v masteru nebo přijímá hodinový signál v slave. V podstatě údery do rytmů;
SS, Slave Select: s pomocí tohoto kanálu slave ví, že se po něm něco chce. Na STM32 se nazývá NSS, kde N = negativní, tzn. regulátor se stane slave, pokud je v tomto kanálu uzemnění. Dobře se kombinuje s režimem Open Drain Output, ale to je jiný příběh.
Stejně jako všechno ostatní je SPI na STM32 bohaté na funkčnost, což ztěžuje jeho pochopení. Například může pracovat nejen s SPI, ale také s rozhraním I2S a v dokumentaci jsou jejich popisy smíšené, je třeba včas odříznout přebytek. Náš úkol je extrémně jednoduchý: stačí posílat data pouze pomocí MOSI a SCK. Jdeme do sekce 25.3.4 (poloviční duplexní komunikace, poloduplexní komunikace), kde najdeme 1 hodinový a 1 jednosměrný datový vodič (1 hodinový signál a 1 jednosměrný datový tok):
V tomto režimu aplikace používá SPI v režimu pouze pro vysílání nebo pouze pro příjem. / Režim pouze vysílání je podobný duplexnímu režimu: data jsou přenášena na vysílacím kolíku (MOSI v režimu master nebo MISO v režimu slave) a přijímací kolík (MISO nebo MOSI v tomto pořadí) lze použít jako běžný I/O kolík . V tomto případě stačí aplikaci ignorovat Rx buffer (pokud je načten, nebudou tam žádná přenesená data).
Výborně, pin MISO je volný, připojíme na něj signál LAT. Podívejme se na Slave Select, který lze na STM32 ovládat programově, což je mimořádně pohodlné. Přečetli jsme si stejnojmenný odstavec v sekci 25.3.1 Obecný popis SPI:
Softwarové řízení NSS (SSM = 1) / Informace o výběru Slave jsou obsaženy v bitu SSI registru SPI_CR1. Externí pin NSS zůstává volný pro potřeby jiných aplikací.
Je čas zapsat se do registrů. Rozhodl jsem se použít SPI2, hledejte jeho základní adresu v datovém listu - v sekci 3.3 Mapa paměti:
Otevřete sekci 25.3.3 se samovysvětlujícím názvem „Konfigurace SPI v režimu Master“:
1. Nastavte frekvenci sériového hodin pomocí bitů BR[2:0] v registru SPI_CR1.
Registry jsou shromážděny ve stejnojmenné části referenční příručky. Posun adresy (Offset adresy) pro CR1 – 0x00 jsou ve výchozím nastavení všechny bity vymazány (Resetovat hodnotu 0x0000):
Bity BR nastavují dělič hodin regulátoru a tím určují frekvenci, na které bude SPI pracovat. Naše frekvence STM32 bude 72 MHz, ovladač LED podle jeho datasheetu pracuje s frekvencí až 25 MHz, takže musíme vydělit čtyřmi (BR[2:0] = 001).
2. Nastavte bity CPOL a CPHA, abyste definovali vztah mezi přenosem dat a časováním sériových hodin (viz diagram na straně 240)
Protože zde čteme datový list a nedíváme se na schémata, podívejme se blíže na textový popis bitů CPOL a CPHA na straně 704 (SPI General Description):
Fáze a polarita hodin
Pomocí bitů CPOL a CPHA registru SPI_CR1 můžete programově vybrat čtyři vztahy časování. Bit CPOL (polarita hodin) řídí stav hodinového signálu, když nejsou přenášena žádná data. Tento bit řídí režimy master a slave. Pokud je CPOL resetován, je pin SCK v klidovém režimu nízký. Pokud je nastaven bit CPOL, je pin SCK v klidovém režimu vysoký.
Když je bit CPHA (fáze hodin) nastaven, záblesk horní bitové pasti je druhou hranou signálu SCK (klesá, pokud je CPOL volný, stoupá, pokud je nastaveno CPOL). Data jsou zachycena druhou změnou hodinového signálu. Pokud je bit CPHA prázdný, záblesk horní bitové pasti je náběžná hrana signálu SCK (sestupná hrana, pokud je nastavena CPOL, vzestupná hrana, pokud je CPOL vymazána). Data jsou zachycena při první změně hodinového signálu.
Po vstřebání těchto znalostí dojdeme k závěru, že oba bity musí zůstat nulové, protože Chceme, aby signál SCK zůstal nízký, když se nepoužívá, a aby se data přenášela na náběžné hraně pulsu (viz obr. Rising Edge v datovém listu DM634).
Mimochodem, zde jsme se poprvé setkali s rysem slovní zásoby v datasheetech ST: v nich je napsána fráze „reset bit to zero“ trochu resetovatA ne trochu vyčistit, jako je například Atmega.
3. Nastavte bit DFF, abyste určili, zda je datový blok 8bitový nebo 16bitový formát
Konkrétně jsem vzal 16bitový DM634, abych se neobtěžoval s přenosem 12bitových PWM dat, jako je DM633. Má smysl nastavit DFF na jednu:
4. Pro určení formátu bloku nakonfigurujte bit LSBFIRST v registru SPI_CR1
LSBFIRST, jak jeho název napovídá, konfiguruje přenos s nejméně významným bitem jako první. Ale DM634 chce přijímat data od nejvýznamnějšího bitu. Proto jej necháme resetovat.
5. Pokud je v hardwarovém režimu vyžadován vstup z kolíku NSS, přiveďte na kolík NSS během celé sekvence přenosu bajtů vysoký signál. V softwarovém režimu NSS nastavte bity SSM a SSI v registru SPI_CR1. Pokud má být pin NSS použit jako výstup, je potřeba nastavit pouze bit SSOE.
Nainstalujte SSM a SSI, abyste zapomněli na hardwarový režim NSS:
#define SSI 0x0100
#define SSM 0x0200
_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high
6. Musí být nastaveny bity MSTR a SPE (zůstanou nastaveny pouze v případě, že je signál NSS vysoký)
Ve skutečnosti pomocí těchto bitů označíme naše SPI jako hlavní a zapneme jej:
SPI je nakonfigurováno, pojďme rovnou napsat funkce, které posílají bajty ovladači. Pokračovat ve čtení 25.3.3 „Konfigurace SPI v hlavním režimu“:
Objednávka přenosu dat
Přenos začíná, když je bajt zapsán do vyrovnávací paměti Tx.
Datový bajt se načte do posuvného registru at paralelní režimu (z vnitřní sběrnice) při přenosu prvního bitu, po kterém je přenesen na sekvenční Režim MOSI pin, první nebo poslední bit vpřed v závislosti na nastavení bitu LSBFIRST v registru CPI_CR1. Příznak TXE je nastaven po přenosu dat z Tx bufferu do posuvného registrua také generuje přerušení, pokud je nastaven bit TXEIE v registru CPI_CR1.
Zvýraznil jsem pár slov v překladu, abych upozornil na jednu vlastnost implementace SPI v STM kontrolérech. Na Atmega příznak TXE (Tx je prázdný, Tx je prázdný a připraven k příjmu dat) se nastavuje až po odeslání celého bajtu ven. A zde se tento příznak nastavuje po vložení bajtu do interního posuvného registru. Vzhledem k tomu, že se tam strčí se všemi bity současně (paralelně), a pak se data přenášejí sekvenčně, nastaví se TXE před úplným odesláním bytu. To je důležité, protože v případě našeho LED ovladače musíme po odeslání vytáhnout LAT pin vše údaje, tzn. Samotný příznak TXE nám stačit nebude.
To znamená, že potřebujeme další vlajku. Podívejme se na 25.3.7 - „Příznaky stavu“:
<…>
Vlajka BUSY
Příznak BSY je nastaven a vymazán hardwarem (zápis do něj nemá žádný vliv). Příznak BSY označuje stav komunikační vrstvy SPI.
Resetuje se:
po dokončení přenosu (kromě hlavního režimu, pokud je přenos nepřetržitý)
když je SPI deaktivováno
když dojde k chybě hlavního režimu (MODF=1)
Pokud přenos není kontinuální, příznak BSY se mezi každým přenosem dat vymaže
Dobře, tohle se bude hodit. Pojďme zjistit, kde se nachází Tx buffer. Chcete-li to provést, přečtěte si „Registr dat SPI“:
Bity 15:0 DR[15:0] Registr dat
Přijatá data nebo data k přenosu.
Datový registr je rozdělen na dva buffery - jeden pro zápis (vyrovnávací paměť pro přenos) a jeden pro čtení (vyrovnávací paměť pro příjem). Zápis do datového registru zapisuje do Tx bufferu a čtení z datového registru vrátí hodnotu obsaženou v Rx bufferu.
No a stavový registr, kde se nacházejí příznaky TXE a BSY:
Protože potřebujeme přenést 16 krát dva bajty, podle počtu výstupů ovladače LED, něco takového:
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();
}
Ale zatím nevíme, jak vytáhnout pin LAT, takže se vrátíme k I/O.
Přiřazení pinů
V STM32F1 jsou registry zodpovědné za stav pinů poměrně neobvyklé. Je jasné, že jich je více než Atmega, ale také se liší od ostatních STM čipů. Část 9.1 Obecný popis GPIO:
Každý z obecných I/O portů (GPIO) má dva 32bitové konfigurační registry (GPIOx_CRL a GPIOx_CRH), dva 32bitové datové registry (GPIOx_IDR a GPIOx_ODR), 32bitový registr set/reset (GPIOx_BSRR), 16bitový registr reset (GPIOx_BRR) a 32-bitový registr registr blokování bitů (GPIOx_LCKR).
První dva registry jsou neobvyklé a také docela nepohodlné, protože 16 pinů portu je na nich roztroušeno ve formátu „čtyři bity na bratra“. Tito. piny nula až sedm jsou v CRL a zbytek je v CRH. Zároveň zbývající registry úspěšně obsahují bity všech pinů portu – často zůstávají napůl „rezervované“.
Pro zjednodušení začneme od konce seznamu.
Nepotřebujeme blokovací registr.
Nastavovací a resetovací registry jsou docela vtipné v tom, že se částečně duplikují: vše můžete zapisovat pouze v BSRR, kde vyšších 16 bitů vynuluje pin a nižších na 1, nebo také můžete použijte BRR, z nichž spodních 16 bitů pouze resetuje pin . Líbí se mi druhá možnost. Tyto registry jsou důležité, protože poskytují atomový přístup k pinům:
Atomic Set nebo Reset
Při programování GPIOx_ODR na bitové úrovni není potřeba deaktivovat přerušení: jeden nebo více bitů lze změnit jedinou operací atomického zápisu APB2. Toho je dosaženo zapsáním "1" do registru set/reset (GPIOx_BSRR nebo pouze pro reset GPIOx_BRR) bitu, který je třeba změnit. Ostatní bity zůstanou nezměněny.
Datové registry mají zcela srozumitelné názvy - IDR = Vstup Směrový registr, vstupní registr; ODR = Výstup Směrový registr, výstupní registr. V současném projektu je nebudeme potřebovat.
A nakonec kontrolní registry. Protože nás zajímají druhé piny SPI, konkrétně PB13, PB14 a PB15, okamžitě se podíváme na CRH:
A vidíme, že budeme muset něco napsat v bitech od 20 do 31.
Co chceme od pinů jsme si už vymysleli výše, takže se zde obejdu bez screenshotu, jen řeknu, že MODE udává směr (vstup, pokud jsou oba bity nastaveny na 0) a rychlost pinu (potřebujeme 50MHz, tzn. oba piny na „1“) a CNF nastaví režim: běžný „push-pull“ – 00, „alternativní“ – 10. Ve výchozím nastavení, jak vidíme výše, mají všechny piny třetí bit odspodu (CNF0), nastaví je do režimu plovoucí vstup.
Jelikož plánuji s tímto čipem udělat něco jiného, pro jednoduchost jsem nadefinoval všechny možné hodnoty MODE a CNF pro dolní i horní řídicí registr.
(LAT_low jen setrvačností, vždycky to tak bylo, nech to zůstat)
Nyní je vše skvělé, ale nefunguje to. Protože se jedná o STM32, šetří elektrickou energii, což znamená, že musíte povolit taktování požadovaných periferií.
Zapněte taktování
Hodinky, známé také jako Clock, mají na starosti taktování. A už jsme si mohli všimnout zkratky RCC. Hledáme to v dokumentaci: toto je Reset and Clock Control.
Jak bylo řečeno výše, naštěstí nejtěžší část taktovacího tématu za nás udělali lidé ze STM, za což jim moc děkujeme (ještě jednou dám odkaz na Web Di Halt, aby bylo jasné, jak je to matoucí). Potřebujeme pouze registry zodpovědné za povolení periferního taktování (Peripheral Clock Enable Registers). Nejprve najdeme základní adresu RCC, je na samém začátku „mapy paměti“:
A pak buď klikněte na odkaz, kde se pokusíte něco najít v desce, nebo mnohem lépe projděte popisy aktivačních registrů ze sekcí o povolit registry. Kde najdeme RCC_APB1ENR a RCC_APB2ENR:
A podle toho obsahují bity, které zahrnují taktování SPI2, IOPB (I/O Port B) a alternativní funkce (AFIO).
Pokud máte možnost a chuť testovat, pak připojte DM634 takto: DAI k PB15, DCK k PB13, LAT k PB14. Ovladač napájíme z 5 voltů, nezapomeňte připojit uzemnění.
STM8 PWM
PWM na STM8
Když jsem tento článek teprve plánoval, rozhodl jsem se jako příklad zkusit zvládnout nějakou funkcionalitu neznámého čipu pouze pomocí datasheetu, abych neskončil u ševce bez bot. STM8 byl pro tuto roli ideální: za prvé jsem měl pár čínských desek s STM8S103 a za druhé není příliš populární, a proto pokušení číst a najít řešení na internetu spočívá na nedostatku těchto řešení.
Standardně STM8 pracuje na frekvenci 2 MHz, to je nutné okamžitě opravit.
HSI (vysokorychlostní vnitřní) hodiny
Hodinový signál HSI je odvozen z interního 16 MHz RC oscilátoru s programovatelným děličem (1 až 8). Nastavuje se v registru děliče hodin (CLK_CKDIVR).
Poznámka: na začátku je jako hlavní zdroj hodinového signálu zvolen HSI RC oscilátor s děličem 8.
Adresu registru najdeme v datovém listu, popis v refman a uvidíme, že je třeba registr vymazat:
Protože se chystáme spustit PWM a připojit LED diody, podívejme se na pinout:
Čip je malý, mnoho funkcí je zavěšeno na stejných pinech. To, co je v hranatých závorkách, je „alternativní funkčnost“, přepíná se pomocí „bytů možností“ (možnost bajtů) – něco jako pojistky Atmega. Jejich hodnoty můžete měnit programově, ale není to nutné, protože Nová funkce se aktivuje až po restartu. Jednodušší je použít ST Visual Programmer (stažený pomocí Visual Develop), který může tyto bajty změnit. Pinout ukazuje, že piny CH1 a CH2 prvního časovače jsou skryté v hranatých závorkách; v STVP je nutné nastavit bity AFR1 a AFR0 a druhý přenese i výstup CH1 druhého časovače z PD4 do PC5.
Takže 6 pinů bude ovládat LED: PC6, PC7 a PC3 pro první časovač, PC5, PD3 a PA3 pro druhý.
Nastavení samotných I/O pinů na STM8 je jednodušší a logičtější než na STM32:
známý z datového registru Atmega DDR (Registr směrování dat): 1 = výstup;
první řídicí registr CR1, když je na výstupu, nastavuje režim push-pull (1) nebo otevřený odtok (0); jelikož LED připojuji k čipu katodami, nechávám zde nuly;
druhý řídicí registr CR2, když je na výstupu, nastavuje takt: 1 = 10 MHz
Automatické opětovné načtení, AR – automaticky načítatelná hodnota, do které bude časovač počítat (perioda pulsu);
Aktualizovat událost, UEV – událost, která nastane, když časovač napočítá do AR;
Pracovní cyklus PWM – pracovní cyklus PWM, často nazývaný „pracovní faktor“;
Zachycení/porovnání hodnoty – hodnota pro zachycení/porovnání, do které časovač počítal něco udělá (v případě PWM invertuje výstupní signál);
Hodnota předpětí – přednastavená hodnota. Porovnejte hodnotu nelze změnit, dokud časovač tiká, jinak se cyklus PWM přeruší. Proto jsou nové přenášené hodnoty umístěny do vyrovnávací paměti a vytaženy, když časovač dosáhne konce svého odpočítávání a je resetován;
Zarovnáno na okraj и Režimy zarovnané na střed – zarovnání podél okraje a na střed, stejné jako u Atmelu Rychlé PWM и Fázově správná PWM.
OCiREF, výstupní porovnávací referenční signál – referenční výstupní signál, ve skutečnosti to, co se objeví na odpovídajícím pinu v režimu PWM.
Jak je již zřejmé z pinoutu, dva časovače mají schopnosti PWM – první a druhý. Oba jsou 16bitové, první má spoustu dalších funkcí (zejména umí počítat jak nahoru, tak dolů). Potřebujeme, aby obojí fungovalo stejně, a tak jsem se rozhodl začít tím evidentně chudším druhým, abych náhodou nepoužil něco, co tam není. Určitým problémem je, že popis funkce PWM všech časovačů v referenční příručce je v kapitole o prvním časovači (17.5.7 Režim PWM), takže musíte v dokumentu neustále přeskakovat tam a zpět.
PWM na STM8 má důležitou výhodu oproti PWM na Atmega:
Boundary Aligned PWM
Konfigurace účtu zdola nahoru
Počítání zdola nahoru je aktivní, pokud je vymazán bit DIR v registru TIM_CR1
příklad
V příkladu je použit první režim PWM. Referenční signál PWM OCiREF je udržován na vysoké úrovni, dokud TIM1_CNT < TIM1_CCRi. Jinak to má nízkou úroveň. Pokud je srovnávací hodnota v registru TIM1_CCRi větší než hodnota autoload (registr TIM1_ARR), signál OCiREF je udržován na 1. Pokud je srovnávací hodnota 0, je OCiREF udržován na nule....
Časovač STM8 během aktualizovat událost nejprve kontroluje porovnat hodnotua teprve poté vytváří referenční signál. Časovač Atmega se nejprve zvrtne a poté porovná, což má za následek compare value == 0 výstupem je jehla, se kterou je třeba se nějak vypořádat (např. programovým převrácením logiky).
Co tedy chceme udělat: 8bitové PWM (AR == 255), počítání zdola nahoru, zarovnání podél hranice. Vzhledem k tomu, že žárovky jsou připojeny k čipu katodami, PWM by měl vydávat 0 (LED svítí), dokud porovnat hodnotu a 1 po.
O některých jsme již četli Režim PWM, takže požadovaný registr druhého časovače najdeme vyhledáním této fráze v referenční příručce (18.6.8 - TIMx_CCMR1):
110: První režim PWM – při počítání zdola nahoru je aktivní první kanál, zatímco TIMx_CNT < TIMx_CCR1. Jinak je první kanál neaktivní. [dále v dokumentu je chybné copy-paste z časovače 1] 111: Druhý režim PWM – při počítání odspodu nahoru je první kanál neaktivní, zatímco TIMx_CNT < TIMx_CCR1. Jinak je aktivní první kanál.
Vzhledem k tomu, že LED jsou k MK připojeny katodami, vyhovuje nám druhý režim (i ten první, ale to ještě nevíme).
Bit 3 OC1PE: Povolí předpětí kolíku 1
0: Preload registru na TIMx_CCR1 je zakázán. Do TIMx_CCR1 můžete napsat kdykoli. Nová hodnota funguje okamžitě.
1: Preload registru na TIMx_CCR1 je povolen. Operace čtení/zápisu přistupují k registru předběžného načtení. Předem načtená hodnota TIMx_CCR1 je načtena do stínového registru během každé události aktualizace.
*Poznámka: Aby režim PWM fungoval správně, musí být povoleny registry preload. To není nutné v režimu jednoho signálu (bit OPM se nastavuje v registru TIMx_CR1).
Dobře, pojďme zapnout vše, co potřebujeme pro tři kanály druhého časovače:
Druhý časovač může počítat pouze zdola nahoru, zarovnání podél hranice, není třeba nic měnit. Dělič kmitočtu nastavíme např. na 256. U druhého časovače se dělič nastavuje v registru TIM2_PSCR a je mocninou dvou:
Nezbývá než zapnout závěry a samotný druhý časovač. První problém řeší registry Zachytit/Porovnat umožnit: jsou na nich asymetricky rozmístěny dva, tři kanály. Zde se také můžeme dozvědět, že je možné změnit polaritu signálu, tzn. v zásadě bylo možné použít PWM Mode 1. Píšeme:
Pojďme napsat jednoduchou analogii AnalogWrite(), která přenese skutečné hodnoty do časovače pro porovnání. Registry jsou pojmenovány předvídatelně Zachytit/porovnat registry, existují dva z nich pro každý kanál: 8 bitů nižšího řádu v TIM2_CCRxL a vyšší v TIM2_CCRxH. Protože jsme vytvořili 8bitové PWM, stačí zapsat pouze nejméně významné bity:
Pozorný čtenář si všimne, že máme mírně vadnou PWM, neschopnou produkovat 100% plnění (při maximální hodnotě 255 je signál invertován na jeden cyklus časovače). U LED to nevadí a pozorný čtenář už tuší, jak to opravit.
PWM na druhém časovači funguje, přejděme k prvnímu.
První časovač má přesně stejné bity ve stejných registrech (jen ty bity, které zůstaly „rezervované“ ve druhém časovači, se v prvním aktivně používají pro nejrůznější pokročilé věci). Stačí tedy v datasheetu najít adresy stejných registrů a zkopírovat kód. Změňte hodnotu frekvenčního děliče, protože... první časovač chce přijímat nikoli mocninu dvou, ale přesnou 16bitovou hodnotu ve dvou registrech Předdělička vysoká и Nízké. Děláme všechno a... první časovač nefunguje. Co se děje?
Problém lze vyřešit pouze prohlédnutím celé sekce o řídicích registrech časovače 1, kde hledáme ten, který druhý časovač nemá. tam bude 17.7.30 Registrace přerušení (TIM1_BKR), kde je tento bit:
Třetím miniprojektem je připojení osmi RGB LED k druhému časovači v režimu PWM a jejich zobrazení v různých barvách. Vychází z konceptu LED multiplexování, který spočívá v tom, že pokud LED zapínáte a vypínáte velmi, velmi rychle, bude se nám zdát, že neustále svítí (vytrvalost vidění, setrvačnost zrakového vnímání). Jednou jsem to udělal něco takového na Arduinu.
Algoritmus práce vypadá takto:
připojena anoda první RGB LED;
zapálil jej a vyslal potřebné signály ke katodám;
čekal až do konce cyklu PWM;
připojena anoda druhé RGB LED;
zapálil to...
No atd. Pro krásný provoz je samozřejmě nutné, aby byla současně připojena anoda a „zapálena“ LED. No, nebo skoro. V každém případě musíme napsat kód, který bude vydávat hodnoty ve třech kanálech druhého časovače, měnit je při dosažení UEV a současně měnit aktuálně aktivní RGB LED.
Protože přepínání LED je automatické, musíme vytvořit „videopaměť“, ze které bude obsluha přerušení přijímat data. Toto je jednoduché pole:
uint8_t colors[8][3];
Aby bylo možné změnit barvu konkrétní LED, bude stačit zapsat požadované hodnoty do tohoto pole. A proměnná bude zodpovědná za číslo aktivní LED
uint8_t cnt;
Demux
Pro správné multiplexování potřebujeme, kupodivu, demultiplexer CD74HC238. Demultiplexer - čip, který implementuje operátor do hardwaru <<. Přes tři vstupní piny (bity 0, 1 a 2) mu přivedeme tříbitové číslo X a jako odpověď aktivuje výstupní číslo (1<<X). Zbývající vstupy čipu slouží k škálování celého návrhu. Tento čip potřebujeme nejen kvůli snížení počtu obsazených pinů mikrokontroléru, ale také kvůli bezpečnosti – abychom omylem nerozsvítili více LED, než je možné a nespálili MK. Čip stojí penny a měl by být vždy uložen ve vaší domácí lékárničce.
Náš CD74HC238 bude zodpovědný za napájení anody požadované LED. V plnohodnotném multiplexu by napájel sloupek přes P-MOSFET, ale v tomto demu je to možné přímo, protože odebírá 20 mA, podle absolutní maximální hodnocení v datovém listu. Z Datasheet CD74HC238 potřebujeme pinouty a tento cheat sheet:
H = úroveň vysokého napětí, L = úroveň nízkého napětí, X – to je jedno
E2 a E1 připojíme k zemi, E3, A0, A1 a A3 k pinům PD5, PC3, PC4 a PC5 STM8. Protože výše uvedená tabulka obsahuje nízké i vysoké úrovně, nakonfigurujeme tyto kolíky jako kolíky push-pull.
PWM
PWM na druhém časovači je nakonfigurován stejným způsobem jako v předchozím příběhu, se dvěma rozdíly:
Nejprve musíme zapnout přerušení Aktualizovat událost (UEV), která zavolá funkci, která přepíná aktivní LED. To se provádí změnou bitu Povolit přerušení aktualizace v rejstříku s vypovídajícím jménem
Druhý rozdíl souvisí s fenoménem multiplexování, jako je kupř ghosting – parazitní svit diod. V našem případě se to může objevit kvůli skutečnosti, že časovač, který způsobil přerušení na UEV, stále tiká a obsluha přerušení nemá čas přepnout LED, než časovač začne něco zapisovat na piny. Abyste tomu zabránili, budete muset převrátit logiku (0 = maximální jas, 255 = nic nesvítí) a vyhnout se extrémním hodnotám pracovního cyklu. Tito. zajistěte, aby po UEV LED zcela zhasly na jeden cyklus PWM.
Vyhněte se nastavení r, gab na 255 a nezapomeňte je při použití převrátit.
Přerušuje
Podstatou přerušení je, že za určitých okolností čip přestane vykonávat hlavní program a zavolá nějakou externí funkci. K přerušením dochází vlivem vnějších nebo vnitřních vlivů, včetně časovače.
Když jsme poprvé vytvořili projekt v ST Visual Develop, kromě main.c dostali jsme okno se záhadným souborem stm8_interrupt_vector.c, automaticky zařazený do projektu. V tomto souboru je každému přerušení přiřazena funkce NonHandledInterrupt. Potřebujeme svázat naši funkci s požadovaným přerušením.
Datový list obsahuje tabulku vektorů přerušení, kde najdeme ty, které potřebujeme:
@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;
}
Zbývá pouze povolit přerušení. To se provádí pomocí příkazu assembler rim - budete to muset hledat v Programovací manuál:
//enable interrupts
_asm("rim");
Dalším příkazem assembleru je sim – vypne přerušení. Během zápisu nových hodnot do „videopaměti“ musí být vypnuty, aby přerušení způsobené v nesprávnou chvíli nezkazilo pole.