ProHoster > Blog > nutizie internet > Leghjite datasheets 2: SPI nantu à STM32; PWM, timers è interruzioni nantu à STM8
Leghjite datasheets 2: SPI nantu à STM32; PWM, timers è interruzioni nantu à STM8
В a prima parte Aghju pruvatu à dì à l'ingegneri di l'elettronica di hobby chì sò cresciuti da i pantaloni Arduino cumu è perchè duveranu leghje datasheets è altra documentazione per i microcontrollers. U testu hè diventatu grande, cusì aghju prumessu di mustrà esempi pratichi in un articulu separatu. Ebbè, si chjamava caricatore ...
Oghje vi mustrarà cumu utilizà datasheets per risolve i travaglii abbastanza simplici, ma necessarii per parechji prughjetti nantu à i controller STM32 (Blue Pill) è STM8. Tutti i prughjetti demo sò dedicati à i mo LED preferiti, l'illuminemu in grande quantità, per quale avemu da aduprà ogni tipu di periferiche interessanti.
U testu hè tornatu à esse enormu, cusì per comodità aghju fattu u cuntenutu:
Disclaimer: Ùn sò micca un ingegnere, ùn aghju micca fintu di avè una cunniscenza prufonda in l'elettronica, l'articulu hè destinatu à dilettanti cum'è mè. In fatti, aghju cunsideratu dui anni fà cum'è u publicu di destinazione. Sì qualchissia m'hà dettu allora chì ùn hè micca scantu di leghje datasheets per un chip scunnisciutu, ùn avissi micca passatu assai tempu à circà qualchi pezzi di codice in Internet è inventà crutches cù forbici è gessatura adesiva.
U focu di questu articulu hè datasheets, micca drafts, perchè u codice pò esse micca troppu pulitu è spessu una crutch. I prughjetti stessi sò assai simplici, ancu s'elli sò adattati per a prima cunniscenza cù un novu chip.
Spergu chì u mo articulu aiuterà qualcunu in un stadiu simili di immersione in un hobby.
STM 32
16 LED cù DM634 è SPI
Picculu prughjettu cù Blue Pill (STM32F103C8T6) è driver LED DM634. Cù l'aiutu di datasheets, avemu da trattà cù u driver, i porti STM IO è cunfigurà SPI.
DM634
Chip taiwanese cù uscite PWM 16 x 16-bit, pò esse incatenatu. U mudellu più ghjovanu 12-bit hè cunnisciutu da un prughjettu domesticu pacchettu di luce. À un tempu, scegliendu trà DM63x è u famusu TLC5940, aghju stabilitu nantu à DM per parechje ragioni: 1) TLC in Aliexpress hè definitu falsu, ma questu ùn hè micca; 2) DM hà un PWM autonomu cù u so propiu generatore di frequenza; 3) Puderia esse acquistatu à pocu pressu in Mosca, è ùn aspittà micca un pacchettu da Ali. E, sicuru, era interessante per amparà cumu cuntrullà u chip stessu, è micca aduprà una biblioteca pronta. I patatine fritte sò avà presentati principarmenti in u pacchettu SSOP24, sò faciuli di saldarà nantu à l'adattatore.
Siccomu u fabricatore hè taiwanese, datasheet à u chip hè scrittu in Chinese English, chì significa chì serà divertente. Prima fighjate à u pinoutCunnessione Pin) per capisce quale gamba cunnetta ciò chì, è una descrizzione di i pin (Descrizione Pin). 16 pins:
Sink surghjenti DC (focu apertu)
Pica / Uscita di drenu apertu - stock; fonte di corrente entrante; un output cunnessu à a terra in un statu attivu - i LED sò cunnessi à u driver per catodi. Elettricu, questu hè, sicuru, micca "drain apertu" (drenu apertu), ma in datasheets tali designazione per outputs in modu di drenu si trova spessu.
Resistori esterni trà REXT è GND per stabilisce u valore di corrente di output
Un resistore di riferimentu hè stallatu trà u pin REXT è a terra, chì cuntrolla a resistenza interna di l'outputs, vede u graficu in a pagina 9 di a datasheet. In u DM634, sta resistenza pò ancu esse cuntrullata da u software stabilendu a luminosità generale (luminosità globale); Ùn andaraghju micca in dettagli in questu articulu, solu mette una resistenza 2.2 - 3 kOhm quì.
Per capisce cumu cuntrullà u chip, fighjemu a descrizzione di l'interfaccia di u dispusitivu:
Iè, quì hè, Chinese English in tutta a so gloria. Hè problematicu di traduce questu, pudete capisce se vulete, ma ci hè un altru modu - per vede cumu a cunnessione in a datasheet à u funziunale TLC5940 hè descritta:
... Solu trè pin sò richiesti per inserisce dati in u dispusitivu. U filu rising di u signale SCLK cambia a dati da u pin SIN à u registru internu. Dopu chì tutte e dati sò stati caricati, un brevi signali XLAT elevatu chjappà i dati trasferiti in serie in i registri interni. I registri interni sò porte attivate da u livellu di signale XLAT. Tutti i dati sò trasmessi prima MSB.
Latch - scroccata / scroccata / scroccata. Bordu ascendante hè a punta di u pulsu MSB prima - u bit più significativu (più a manca) in avanti. per clock data - trasmette dati in sequenza (bit per bit).
A parolla latch spessu trovu in a documentazione per i chips è hè traduttu in una varietà di manere, cusì per capiscenu mi permetteraghju.
un picculu prugramma educativuU driver LED hè essenzialmente un registru di shift. "Shift" (passata) in u nome - movimentu bit-by-bit di dati in u dispusitivu: ogni novu bit shoved inside pushs the whole chain forward in front of it. Siccomu nimu ùn vole osservà u lampeggiamentu caòticu di i LED durante u turnu, u prucessu si svolge in registri buffer separati da i travagliadori da un otturatore (latch) hè una spezia di vestitori induve i pezzi si allineanu in a sequenza desiderata. Quandu tuttu hè prontu, l'otturatore si apre è i pezzi vanu à travaglià, rimpiazzà u batch precedente. Parola latch in a documentazione per i microcircuiti quasi sempre implica un tali damper, in qualunque cumminazzioni hè utilizatu.
Allora, u trasferimentu di dati à DM634 hè realizatu cusì: stabilisce l'ingaghjamentu DAI à u valore di l'altu bit di u LED luntanu, tirà DCK su è falà; stabilisce l'input DAI à u valore di u prossimu bit, tira DCK; è cusì finu à chì tutti i bit sò stati trasmessi (chjosu in), dopu chì tiramu LAT. Questu pò esse fattu manualmenteun pocu bang), ma hè megliu aduprà l'interfaccia SPI spicialmente affilata per questu, postu chì hè presentata nantu à u nostru STM32 in duie copie.
Tablet blu STM32F103
Introduzione: i cuntrolli STM32 sò assai più complicati cà Atmega328 di ciò chì ponu esse spaventosi. À u listessu tempu, per ragioni di risparmiu energeticu, quasi tutti i periferichi sò disattivati à u principiu, è a freccia di u clock hè 8 MHz da una fonte interna. Fortunatamente, i programatori STM anu scrittu un codice chì porta u chip à u "calculatu" 72 MHz, è l'autori di tutti l'IDE chì cunnoscu includeu in a prucedura d'inizializazione, perchè ùn avemu micca bisognu di clock (ma pudete sè vo vulete veramente). Ma avete da accende i periferichi.
Documentazione: U popular chip STM32F103C8T6 hè stallatu nantu à Blue Pill, ci sò dui documenti utili per questu:
Datu Di Ficura per i microcontrollers STM32F103x8 è STM32F103xB;
Pinouts - chip pinouts - in casu chì decidemu di fà tavule noi stessi;
Memory Map - una mappa di memoria per un chip specificu. U Manuale di Referenza hà una mappa per tutta a linea, ammenta i registri chì ùn sò micca nantu à a nostra.
Pin Definitions table - elencu e funzioni pin principali è alternative; per a "pillola blu" in Internet, pudete truvà ritratti più convenienti cù una lista di pins è e so funzioni. Dunque, avemu subitu Google Blue Pill pinout è mantene sta stampa à manu:
NB: ci hè statu un errore in a stampa da Internet, nutatu in i cumenti, per quale ringraziu. A stampa hè stata rimpiazzata, ma questu hè una lezione - hè megliu per verificà l'infurmazioni micca da datasheets.
Eliminate a datasheet, apre u Manuale di Riferimentu, da avà l'utilicemu solu.
Prucedura: trattà cù input / output standard, cunfigurà SPI, accende i periferici necessarii.
Input Output
Nantu à l'Atmega328, l'I / O hè estremamente simplice, per quessa chì l'abbundanza di l'opzioni STM32 pò esse cunfusa. Avà avemu solu bisognu di cunclusioni, ma ancu ci sò quattru opzioni:
uscita di scarico aperto, uscita push-pull, alternativa push-pull, alternativa di scarico aperto
"Pull-push" (push-pull) - l'output abituale da l'Arduino, u pin pò esse HIGH o LOW. Ma cù u "focu apertu" nascenu difficultà, anche se in fatti tuttu hè simplice quì:
Configurazione di output / quandu un portu hè assignatu à un output: / output buffer enabled: / - open drain mode: "0" in u registru di output attiva N-MOS, "1" in u registru di output lascia u portu in modalità Hi-Z (P-MOS ùn hè micca attivatu) / - Modu push-pull: "0" in u registru di output attiva N-MOS, "1" in u registru output attiva P-MOS.
Tutta a differenza di scarico aperta (drenu apertu) da "push-pull" (push-pull) hè chì in u primu pin ùn pò micca piglià u statu ALTA: quandu una unità hè scritta à u registru di output, entra in modu d'alta resistenza (alta impedenza, Salute-Z). Quandu scrivite zero, u pin in i dui modi si cumporta u stessu, sia lògicu sia elettricamente.
In u modu di output normale, u pin si traduce solu u cuntenutu di u registru di output. In "alternativa" hè cuntrullata da u perifericu currispundente (vede 9.1.4):
Se u bit di u portu hè cunfiguratu cum'è una funzione alternativa di output, u registru di output hè disattivatu è u pin hè cunnessu à u signale di output di u perifericu.
A funziunalità alternativa di ogni pin hè descritta in Definizioni Pin A datasheet hè nantu à a stampa scaricata. Quandu ci hè dumandatu ciò chì deve fà se u pin hà parechje funzioni alternative, a risposta hè datu da una nota di pede in a datasheet:
Sì parechje periferiche utilizanu u stessu pin, per evità u cunflittu trà e funzioni alternative, solu un perifericu deve esse utilizatu à u mumentu, cambiendu utilizendu u bit Peripheral Clock Enable (in u registru RCC currispundente).
Infine, i pin in modu di output anu ancu una velocità di clock. Questa hè una altra funzione di risparmiu d'energia, in u nostru casu, avemu solu stabilitu à u massimu è scurdate.
Allora: usemu SPI, chì significa chì dui pin (cù dati è cun un signalu di clock) deve esse "funzione push-pull alternativa", è un altru (LAT) deve esse "push-pull normale". Ma prima di assignà elli, trattamu di SPI.
SPI
Un altru pocu pirate
SPI o Serial Peripheral Interface (interfaccia periferica seriale) hè una interfaccia simplice è assai efficace per cumunicà MK cù altri MK è u mondu esternu in generale. U principiu di u so funziunamentu hè digià statu discrittu sopra, induve circa lu driver Chinese LED (vede rùbbrica 25 in u manual di riferimentu). SPI pò operà in modi master ("maestru") è slave ("slave"). SPI hà quattru canali basi, chì ùn sò micca tutti implicati:
MOSI, Master Output / Slave Input: stu pin manda dati in modu maestru, è riceve dati in modu slave;
MISO, Master Input / Slave Output: à u cuntrariu, in u maestru riceve, in u slave dà;
SCK, Serial Clock: stabilisce a frequenza di trasmissione di dati in u maestru o riceve un signalu di clock in u slave. Essenzialmente, beats the beats;
SS, Slave Select: cù questu canale, u schiavu sapi chì volenu qualcosa da ellu. In STM32 hè chjamatu NSS, induve N = negativu, i.e. u controller diventa schiavu se stu canale hà una terra. Si combina bè cù u modu Open Drain Output, ma hè una altra storia.
Cum'è tuttu u restu, SPI in STM32 hè riccu di funziunalità, chì rende un pocu difficiule di capiscenu. Per esempiu, pò travaglià micca solu cù SPI, ma ancu cù una interfaccia I2S, è in a documentazione i so descrizzioni sò mischiati, hè necessariu taglià l'eccessu in una manera puntuale. U nostru compitu hè estremamente simplice: basta à dà dati cù solu MOSI è SCK. Andemu à a sezione 25.3.4 (comunicazione half-duplex, cumunicazione half-duplex), induve truvamu 1 clock è 1 filu di dati unidirezionale (1 clock è 1 flussu di dati unidirezionale):
In questu modu, l'applicazione usa SPI in modu di trasmissione solu o di riceve solu. / U modu di trasmissione solu hè simile à u modu duplex: i dati sò trasmessi nantu à u pin di trasmissione (MOSI in modu maestru o MISO in modu slave), mentre chì u pin di ricezione (MISO o MOSI rispettivamente) pò esse usatu cum'è pin I / O normale. In questu casu, hè abbastanza per l'applicazione per ignurà u buffer Rx (se hè lettu, ùn ci sarà micca dati trasmessi).
Grande, u pin MISO hè liberu, cunnettamu u signalu LAT. Trattemu di Slave Select, chì pò esse cuntrullatu programaticamente in STM32, chì hè estremamente convenientu. Avemu lettu u paràgrafu di u listessu nome in a sezione 25.3.1 SPI General Description:
U cuntrollu di u software NSS (SSM = 1) / L'infurmazione di selezzione di Slave hè cuntenuta in u bit SSI di u registru SPI_CR1. U pin NSS esternu hè lasciatu liberu per altri bisogni di l'applicazione.
Hè u tempu di scrive à i registri. Aghju decisu d'utilizà SPI2, cerchemu u so indirizzu di basa in a datasheet - in a sezione 3.3 Memory Map (Memory Map):
Apermu a sezione 25.3.3 cù u titulu di cunfigurazione "Configurazione di SPI in modu maestru":
1. Stabilite u clock di l'interfaccia seriale cù i bit BR[2:0] in u registru SPI_CR1.
I registri sò cullati in a sezione manuale di riferimentu di u listessu nome. Cambia l'indirizzu (offset di indirizzu) CR1 hà 0x00, per difettu tutti i bit sò sbulicati (Resettate u valore 0x0000):
I bits BR stabiliscenu u divisore di l'orologio di u controller, determinendu cusì a frequenza à quale u SPI operarà. A freccia STM32 serà 72 MHz, u driver LED, secondu a so datasheet, opera à una freccia di sin'à 25 MHz, cusì avemu bisognu di dividisce per quattru (BR[2: 0] = 001).
2. Impostate i bits CPOL è CPHA per definisce a relazione trà u trasferimentu di dati è u clock di l'interfaccia seriale (vede u schema à a pagina 240)
Siccomu leghjemu una scheda di dati quì, è ùn fighjemu micca schemi, fighjemu un ochju più vicinu à a descrizzione testuale di i bit CPOL è CPHA in a pagina 704 (SPI General Description):
Fase di u clock è polarità
Utilizendu i bits CPOL è CPHA di u registru SPI_CR1, pudete selezziunà programaticamente quattru opzioni per i rapporti di timing. U bit CPOL (Clock Polarity) cuntrolla u statu di u signale di u clock quandu ùn ci hè micca datu trasmessi. Stu bit cuntrolla i modi maestru è slave. Se CPOL hè resettatu, u pin SCK hè bassu à riposu. Se u bit CPOL hè impostatu, u pin SCK hè altu quandu inattivu.
Se u bit CPHA (Clock Phase) hè impostatu, u strobe trap MSB hè a seconda punta di u signale SCK (caduta si CPOL hè sbulicatu, o rising edge se CPOL hè impostatu). I dati sò latched in u sicondu cambiamentu di u clock. Se u bit CPHA hè sguassatu, u stroboscopiu di trappula di bit high hè u frontu ascendente di u signale SCK (caduta se CPOL hè impostatu, o frontu ascendante si CPOL hè chjaru). I dati sò latched in u primu cambiamentu di u clock.
Dopu avè tastatu sta cunniscenza, ghjunghjemu à a cunclusione chì i dui bits devenu esse zero, perchè vulemu chì u signale SCK fermu bassu quandu ùn hè micca in usu, è e dati per esse trasmessi nantu à a riva di u pulsu (vede fig. bordu ascendante in a scheda di dati DM634).
Per via, quì avemu prima scontru una caratteristica di u vocabulariu in i datasheets ST: in elli a frasa "reset the bit to zero" hè scritta. per resettare un pòè micca per sguassà un pocu, cum'è, per esempiu, Atmega.
3. Stabilisci u bit DFF per determinà u furmatu di bloccu di dati 8-bit o 16-bit
Aghju specificamente pigliatu u DM16 634-bit per ùn avè micca fastidiu cù u trasferimentu di dati PWM 12-bit, cum'è u DM633. DFF hà sensu di mette in unità:
4. Configurate u bit LSBFIRST in u registru SPI_CR1 per definisce u formatu di bloccu
LSBFIRST, cum'è u so nome implica, stabilisce a trasmissione cù u più pocu significativu prima. Ma u DM634 vole riceve prima dati MSB. Dunque, lascemu u resettore.
5. In u modu di hardware, se l'input da u pin NSS hè necessariu, cunduce u pin NSS altu durante tutta a sequenza di trasferimentu di byte. In u modu di prugramma NSS, stabilisce i bit SSM è SSI in u registru SPI_CR1. Se u pin NSS deve esse output, solu u bit SSOE deve esse stabilitu.
Installa SSM è SSI per scurdà di u modu di hardware NSS:
#define SSI 0x0100
#define SSM 0x0200
_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high
6. I bits MSTR è SPE deve esse stabilitu (si fermanu solu se u NSS hè altu)
In realtà, cù questi bit assignemu u nostru SPI cum'è maestru è l'accendemu:
SPI hè cunfiguratu, scrivemu immediatamente funzioni chì mandanu byte à u driver. Cuntinuà lettura 25.3.3 "Configurazione SPI in Modu Maestru":
Prucedura di trasferimentu di dati
U trasferimentu principia quandu un byte hè scrittu à u buffer Tx.
U byte di dati hè caricatu in u registru di shift at parallella modu (da u bus internu) durante a trasmissioni di u primu bit, dopu chì hè trasmessu in coherente Modu pin MOSI, u primu o l'ultimu bit in avanti secondu l'impostazione di u bit LSBFIRST in u registru CPI_CR1. A bandiera TXE hè stabilita dopu a trasmissione di dati da Tx buffer à shift register, è una interruzzione hè generata se u bit TXEIE in u registru CPI_CR1 hè stabilitu.
Aghju evidenziatu uni pochi di parolle in a traduzzione per attirà l'attenzione à una funzione di l'implementazione di SPI in i cuntrolli STM. Nant'à l'Atmega, a bandiera TXE (Tx Viotu, Tx hè viotu è pronta per riceve dati) hè stabilitu solu dopu chì u byte tutale hè statu mandatu fora. E quì sta bandiera hè stallata dopu chì u byte hè statu imbuttatu in u registru di shift internu. Siccomu hè sbuchjatu quì cù tutti i bits à u stessu tempu (in parallelu), è poi i dati sò trasmessi sequentially, TXE hè stabilitu prima chì u byte hè mandatu cumpletamente. Questu hè impurtante perchè in u casu di u nostru driver LED, avemu bisognu à tirà u pin LAT dopu à mandà всех dati, i.e. solu a bandiera TXE ùn serà micca abbastanza per noi.
Chì significa chì avemu bisognu di una altra bandiera. Fighjemu à 25.3.7 - "Status Flags":
<...>
Bandiera BUSY
A bandiera BSY hè stallata è sguassata da u hardware (scrivu à ellu ùn hà micca effettu). A bandiera BSY indica u statu di a capa di cumunicazione SPI.
Resetta:
quandu u trasferimentu hè cumpletu (eccettu in u modu maestru se u trasferimentu hè cuntinuu)
quandu SPI hè disattivatu
quandu si verifica un errore di modu maestru (MODF = 1)
Se a trasmissione ùn hè micca cuntinuu, a bandiera BSY hè sguassata trà ogni trasmissione di dati.
Va bè, serà utile. Scuprite induve si trova u buffer Tx. Per fà questu, leghjite u "SPI Data Register":
Bits 15: 0 DR[15: 0] Data Register
Dati ricevuti o dati da trasmette.
U registru di dati hè divisu in dui buffer, unu di scrittura (buffer di trasmissione) è unu di lettura (buffer di ricezione). Una scrittura à u registru di dati scrive in u buffer Tx, è una lettura da u registru di dati restituverà u valore cuntenutu in u buffer Rx.
Ebbè, u registru di statutu, induve ci sò bandiere TXE è BSY:
Ebbè, postu chì avemu bisognu di trasfiriri 16 volte dui bytes, secondu u numeru di outputs di u driver LED, qualcosa cum'è questu:
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();
}
Ma ùn sapemu micca ancu cumu tirà u pin LAT, allora vultemu à I / O.
Assegna pins
In STM32F1, i registri rispunsevuli di u statu di i pins sò piuttostu inusual. Hè chjaru chì ci sò più di elli chì Atmega, ma sò ancu diffirenti di l'altri chips STM. Sezione 9.1 GPIO Descrizione generale:
Ciascunu di i porti I/O di u scopu generale (GPIO) hà dui registri di cunfigurazione di 32 bit (GPIOx_CRL è GPIOx_CRH), dui registri di dati di 32 bit (GPIOx_IDR è GPIOx_ODR), un registru di reset / reset di 32 bit (GPIOx_BSRR), un registru di reset di 16 bit (GPIOx_BRR) è un registru di bloccu 32-bit LCKR.
Inusual, è ancu piuttostu inconveniente, sò i primi dui registri quì, perchè i pins 16 di u portu sò spargugliati nantu à elli in un furmatu "quattru bit per fratellu". Quelli. I pin da XNUMX à XNUMX sò in CRL, è u restu sò in CRH. À u listessu tempu, i registri rimanenti si adattanu bè à i pezzi di tutti i pins di u portu - spessu restanu a mità "riservatu".
Per simplicità, cuminciamu à a fine di a lista.
Ùn avemu micca bisognu di un registru di bloccu.
I registri di set è resettate sò abbastanza divertenti in quantu si duplicanu parzialmente: pudete scrive tuttu solu in BSRR, induve i 16 bits superiori resettanu u pin à cero, è i più bassi seranu messi à 1, o pudete ancu aduprà BRR, i 16 bits inferiori di quale solu resettate u pin. Mi piace a seconda opzione. Questi registri sò impurtanti perchè furnisce l'accessu atomicu à i pin:
Installazione atomica o resettate
Ùn avete bisognu di disattivà l'interruzioni quandu u prugramma GPIOx_ODR à u livellu di bit: pudete cambià unu o più bit cù una sola operazione di scrittura atomica APB2. Questu hè ottenutu scrivendu un "1" à u registru set/reset (GPIOx_BSRR o, per reset solu, GPIOx_BRR) di u bit da cambià. L'altri pezzi resteranu invariati.
I registri di dati anu nomi abbastanza parlanti - IDR = entrée Registru di direzzione, registru di input; ODR= radicali avrìanu pututu Registru di direzzione, registru di output. In u prughjettu attuale, ùn avemu micca bisognu.
È infine, i registri di cuntrollu. Siccomu ci interessa à i pins di u sicondu SPI, vale à dì PB13, PB14 è PB15, fighjemu immediatamente CRH:
È vedemu chì serà necessariu di scrive qualcosa in pezzi da u 20 à u 31.
Avemu digià capitu ciò chì vulemu da i pins sopra, cusì quì aghju da fà senza una screenshot, diceraghju solu chì MODE stabilisce a direzzione (input se i dui bits sò impostati à 0) è a vitezza di u pin (avemu bisognu di 50MHz, vale à dì chì i dui pins sò impostati à "1"), è CNF stabilisce u modu: normale "push-pull" hè 00, "10" per predefinitu, per predefinitu, "0" hè sopra. ov u terzu bit da u fondu (CNFXNUMX) hè registratu, li mette in u modu input flottante.
Siccomu pensa à fà qualcosa d'altru cù stu chip, per simplicità, aghju generalmente definitu tutti i valori MODE è CNF pussibuli per i registri di cuntrollu inferjuri è superiore.
(LAT_low solu per inerzia, in qualchì modu era sempre, lasciate stà per voi)
Avà tuttu hè grande, solu ùn funziona. Perchè questu hè STM32, salvanu l'electricità quì, chì significa chì avete bisognu di accende u clock di i periferici necessarii.
Accende l'orologio
U clock hè rispunsevule per u clock, sò ancu Clock. È pudemu digià nutà l'abbreviazione RCC. Cerchemu in a ducumentazione: questu hè Reset and Clock Control (Gestione di reset è clock).
Cum'è l'esitatu sopra, per furtuna, a ghjente di STM hà fattu a parte più difficiuli di u tema di u clock per noi, per quale assai grazie à elli (di novu vi daraghju un ligame per U situ web di Di Haltper fà chjaru quantu hè cunfusu). Avemu bisognu solu di registri rispunsevuli di attivà u clock perifericu (Registri di attivazione di l'orologio perifericu). Prima, truvamu l'indirizzu di basa di u RCC, hè à u principiu di a "Carta di Memoria":
È dopu cliccate nant'à u ligame induve pruvà à truvà qualcosa in a tavula, o, assai megliu, andate nantu à e descrizzioni di i registri inclusi da e rùbbriche circa. attivà i registri. Induve truvamu RCC_APB1ENR è RCC_APB2ENR:
È in elli, rispettivamente, bits chì includenu u clock di SPI2, IOPB (I / O Port B) è funzioni alternative (AFIO).
Se ci hè l'uppurtunità è u desideriu di pruvà, allora cunnettamu DM634 cusì: DAI à PB15, DCK à PB13, LAT à PB14. Alimentamu u cunduttore da 5 volti, ùn vi scurdate di cumminà i terreni.
STM8 PWM
PWM nantu à STM8
Quandu era ghjustu à pianificà stu articulu, decisu, per esempiu, di pruvà à ammaistrà una certa funziunalità di un chip scunnisciutu cù l'aiutu di solu una datasheet, perchè un calzaturinu ùn esce micca senza stivali. STM8 era perfettu per questu rolu: prima, aghju avutu un paru di schede chinesi cù STM8S103, è in segundu, ùn hè micca assai populari, è per quessa a tentazione di leghje è truvà una suluzione in Internet si basa nantu à l'absenza di sti stessi suluzioni.
Per automaticamente, STM8 opera à una frequenza di 2 MHz, questu deve esse correttu immediatamente.
HSI Clock (High Internal)
U clock HSI hè derivatu da un oscillatore RC internu di 16 MHz cù un divisore programabile (1 à 8). Hè stabilitu in u registru divisore di u clock (CLK_CKDIVR).
Nota: L'oscillatore HSI RC cù un divisore di 8 hè sceltu cum'è fonte di clock master à l'iniziu.
Truvemu l'indirizzu di u registru in a datasheet, a descrizzione in refman è vede chì u registru deve esse sbulicatu:
Siccomu andemu à eseguisce PWM è cunnette LED, fighjemu u pinout:
U chip hè chjucu, assai funzioni sò suspesi nantu à i stessi pin. Ciò chì hè in parentesi quadrate hè "funzionalità alternativa", hè cambiatu da "opzioni byte" (byte d'opzione) - qualcosa cum'è Atmega fuses. Pudete cambià i so valori programmaticamenti, ma ùn hè micca necessariu, perchè. A nova funziunalità hè attivata solu dopu un reboot. Hè più faciule d'utilizà ST Visual Programmer (scaricatu cù Visual Develop), chì pò cambià questi byte. U pinout mostra chì l'outputs CH1 è CH2 di u primu timer sò oculati in parentesi quadrate; hè necessariu di stabilisce i bits AFR1 è AFR0 in STVP, è u sicondu trasferisce ancu l'output CH1 di u second timer da PD4 à PC5.
Cusì, 6 pins cuntrullà i LED: PC6, PC7 è PC3 per u primu timer, PC5, PD3 è PA3 per u sicondu.
L'installazione di i pin I/O stessi nantu à u STM8 hè più simplice è più logicu chè in u STM32:
Registru di direzzione di dati Atmega familiarizatu DDR (Registru di direzzione di dati): 1 = output;
u primu registru di cuntrollu CR1, quandu u risultatu, stabilisce u modu push-pull (1) o apre u drain (0); postu ch'e aghju culligatu i LED à u chip cù catodi, lascià cero quì;
u sicondu registru di cuntrollu CR2 stabilisce a velocità di u clock quandu u outputting: 1 = 10 MHz
Capture / Comparare u valore - valore per catturà / paragunà, cuntendu finu à quale u timer farà qualcosa (in u casu di PWM, inverte u signale di output);
valore di preload - valore precaricatu. paragunà u valore ùn pò micca cambià mentre u timer hè in tic-tac, altrimenti u ciculu PWM si rompe. Per quessa, i novi valori trasmessi sò posti in u buffer è tirati fora quandu u timer righjunghji a fine di u countdown è hè resettatu;
Allineatu à bordu и Modi allineati à u centru - allinamentu nantu à u cunfini è in u centru, u listessu cum'è atmelovskie PWM veloce и PWM correttu in fase.
OCiREF, Output Compare Signal Reference - u signale di output di riferimentu, in fattu, ciò chì appare nantu à u pin currispundente in modu PWM.
Cumu hè digià chjaru da u pinout, dui cronometri anu capacità PWM - u primu è u sicondu. Tramindui sò 16-bit, u primu hà assai funzioni supplementari (in particulare, pò cuntà sia up sia down). Avemu bisognu di tramindui per travaglià a listessa manera, cusì aghju decisu di principià cù u sicondu, ovviamente più poviru, per ùn aduprà accidentalmente qualcosa chì ùn hè micca in questu. Qualchidunu prublema hè chì a descrizzione di a funziunalità PWM di tutti i timers in u manuale di riferimentu hè in u capitulu nantu à u primu cronometru (17.5.7 PWM Mode), perchè avete da saltà avanti è avanti per u documentu tuttu u tempu.
PWM in STM8 hà un vantaghju impurtante annantu à Atmega PWM:
PWM cù allineamentu di u bordu
Cunfigurazione di u contu da u fondu à a cima
L'up counting hè attivu se u bit DIR in u registru TIM_CR1 hè chjaru
Esempiu:
L'esempiu usa u primu modu PWM. U signale di riferenza PWM OCiREF hè tenutu altu finu à chì TIM1_CNT < TIM1_CCRi. Altrimenti, ci vole un livellu bassu. Se u valore da paragunà in u registru TIM1_CCRi hè più grande di u valore di carica automatica (registru TIM1_ARR), u signale OCiREF hè tenutu à 1. Se u valore di paragone hè 0, OCiREF hè tenutu à zero....
Timer STM8 durante avvenimentu di aghjurnà cuntrolli prima paragunà u valore, è solu allora pruduce un signalu di riferimentu. In Atmega, u timer prima tremula, è poi paragunate, per via di quale, quandu compare value == 0 l'output hè una agulla chì deve esse trattata di qualchì manera (per esempiu, invertendu programaticamente a logica).
Allora ciò chì vulemu fà: 8-bit PWM (AR == 255), cuntendu da u fondu à u cima, allinamentu longu u cunfini. Siccomu i lampadini sò cunnessi à u chip da catodi, u PWM deve esse 0 (LED on) finu à paragunà u valore è 1 dopu.
Avemu digià lettu circa qualchi Modu PWM, cusì truvamu u registru desideratu di u second timer cerchendu in u manuale di riferimentu per sta frasa (18.6.8 - TIMx_CCMR1):
110: Primu modu PWM - quandu si cunta da u fondu à a cima, u primu canale hè attivu sempre chì TIMx_CNT < TIMx_CCR1. Altrimenti, u primu canale hè inattivu. [più in u documentu, erroneous copy-paste from timer 1] 111: Second mode PWM - quandu cunta da u fondu à u cima, u primu canale hè inattivu finu à TIMx_CNT < TIMx_CCR1. Altrimenti, u primu canale hè attivu.
Siccomu i LED sò cunnessi à u MK cù catodi, u sicondu modu ci cunvene (u primu ancu, ma ùn sapemu micca ancu questu).
Bit 3 OC1PE: Abilita Preloading Output 1
0: Preload register in TIMx_CCR1 disattivatu. Pudete scrive à TIMx_CCR1 in ogni mumentu. U novu valore travaglia subitu.
1: Preload register in TIMx_CCR1 attivatu. L'operazioni di lettura / scrittura accede à u registru di precarica. U valore precaricatu di TIMx_CCR1 hè caricatu in u registru d'ombra durante ogni avvenimentu di aghjurnamentu.
* Nota: I registri di precaricamentu devenu esse attivati per u modu PWM per travaglià bè. Questu hè opzionale in u modu di signale unicu (u bit OPM hè stabilitu in u registru TIMx_CR1).
Va bè, attivate tuttu ciò chì avete bisognu per i trè canali di u second timer:
U second timer pò cuntà solu da u fondu à u cima, l'allinjamentu nantu à u cunfini, nunda ùn deve esse cambiatu. Pone u divisore di freccia, per esempiu, à 256. Per u second timer, u divisore hè stallatu in u registru TIM2_PSCR è hè una putenza di dui:
Resta à accende e cunclusioni è u sicondu timer stessu. U primu compitu hè risolta da i registri Capture / Comparare Enable: ci sò dui, trè canali sò spargugliati asimmetricamente nantu à elli. Quì pudemu ancu amparà chì hè pussibule cambià a polarità di u signale, i.e. in principiu, puderia ancu esse usatu PWM Mode 1. Scrivemu:
Scrivemu un analogu simplice di AnalogWrite (), chì passerà i valori attuali à u timer per paragunà. I registri sò prevedibilmente chjamati Capture / Comparare i registri, ci sò dui per ogni canali: i 8 bits bassi in TIM2_CCRxL è i bits alti in TIM2_CCRxH. Siccomu avemu principiatu PWM 8-bit, hè abbastanza per scrive solu i bits bassu:
U lettore attentu hà da vede chì avemu un PWM ligeramente difettu, incapaci di dà 100% di riempimentu (à un valore massimu di 255, u signale hè invertitu da un ciclu di timer). Per i LED, questu ùn ghjoca micca un rolu, è u lettore attentu hà digià indovinatu cumu per riparà.
PWM nantu à u secondu timer travaglia, andate à u primu.
U primu timer hà esattamente i stessi bits in i stessi registri (hè solu chì quelli bits chì sò stati "riservati" in u second timer sò attivamente usati per ogni tipu di cose avanzate in u primu). Dunque, hè abbastanza per truvà l'indirizzi di i stessi registri in a datasheet è copià u codice. Ebbè, cambia u valore di u divisore di freccia, perchè. u primu timer ùn vole micca ottene una putenza di dui, ma un valore esatta di 16 bit in dui registri Prescaler High и Low. Facemu tuttu è ... u primu timer ùn funziona micca. Chì ci hè?
L'unicu modu per risolve u prublema hè fighjendu tutta a sezione nantu à i registri di cuntrollu di u timer 1, induve circhemu unu chì u second timer ùn hà micca. ci sarà 17.7.30 Break register (TIM1_BKR), induve ci hè un pocu cusì:
U terzu mini-prughjettu hè di cunnette ottu LED RGB à u sicondu timer in u modu PWM è fà chì mostranu diversi culori. Hè basatu annantu à u cuncettu di multiplexing LED, chì cunsiste in u fattu chì si accende è spegne i LED assai, assai rapidamente, ci pare chì sò sempre accesi (persistenza di a visione, inerzia di a percepzione visuale). Aghju fattu una volta qualcosa di simile nantu à arduino.
L'algoritmu di u travagliu pare cusì:
cunnessu l'anodu di u primu LED RGB;
accende, dendu i signali necessarii à i catodi;
aspittatu per a fine di u ciculu PWM;
cunnessu l'anodu di u sicondu LED RGB;
l'accendi...
Ebbè, ecc. Di sicuru, per u travagliu bellu, hè necessariu chì a cunnessione di l'anodu è l'"ignizione" di u LED sò simultaneamente. Bè, quasi. In ogni casu, avemu bisognu di scrive un codice chì pruduverà i valori in trè canali di u secondu timer, cambiassi quandu UEV hè ghjuntu è simultaneamente cambia u LED RGB attualmente attivu.
Siccomu u cambiamentu LED hè automaticu, avemu bisognu di creà "memoria video" da induve u gestore di l'interruzzione riceverà dati. Questu hè un array simplice:
uint8_t colors[8][3];
Per cambià u culore di un LED particulari, sarà abbastanza à scrive i valori necessarii in questa matrice. È a variàbile serà rispunsevuli di u numeru di u LED attivu
uint8_t cnt;
Demux
Per un multiplexing propiu, avemu bisognu, stranamente, u demultiplexer CD74HC238. Demultiplexer - un chip chì implementa l'operatore in hardware <<. Attraversu trè pin di input (bits 0, 1 è 2) l'alimentemu un numeru di trè bit X, è in risposta attiva u numeru di output (1<<X). L'inputs restanti di u chip sò usati per scala u disignu tutale. Avemu bisognu di stu chip micca solu per riduce u nùmeru di pins occupati di u microcontroller, ma ancu per a sicurità - per ùn accende accidentalmente più LED di ciò chì hè pussibule è micca brusgià u MK. U chip costa un centesimu, deve esse sempre guardatu in u kit di primu aiutu in casa.
CD74HC238 serà rispunsevule per furnisce a tensione à l'anodu di u LED desideratu. In un multiplex full-fledged, furnisce a tensione à a colonna attraversu u P-MOSFET, ma in questa demo, pudete fà direttamente, perchè. tira 20mA, secondu valutazione massima assoluta in a datasheet. Da Scheda dati CD74HC238 avemu bisognu di un pinout è di sta cheat sheet:
H = livellu d'alta tensione, L = livellu di tensione bassa, X - ùn importa micca
Cunnetteremu E2 è E1 à a terra, E3, A0, A1 è A3 à i pins PD5, PC3, PC4 è PC5 di STM8. Siccomu a tavula sopra cuntene i livelli bassi è alti, avemu stallatu questi pins cum'è pins push-pull.
PWM
PWM nantu à u second timer hè cunfiguratu in u listessu modu cum'è in a storia precedente, cù duie differenzi:
Prima, avemu bisognu di attivà l'interruzzione Actualizazione di l'avvenimentu (UEV) chì chjamarà una funzione per cambià u LED attivu. Questu hè fattu da cambià u bit Update Interrupt Enable in un registru cù un nome parlante
A seconda diferenza hè cunnessu cù un tali fenomenu di multiplexing cum'è ghosting - luce parassita di diodi. In u nostru casu, pò apparisce per u fattu chì u cronometru, chì hà causatu una interruzzione in u UEV, cuntinueghja à tick, è u gestore di l'interruzzione ùn hà micca tempu di cambià u LED prima chì u timer cumencia à scrive qualcosa à i outputs. Per cumbattà questu, avete da invertisce a logica (0 = luminosità massima, 255 = nunda ùn hè micca attivu) è ùn permettenu micca valori estremi di u ciclu di duty. Quelli. assicuratevi chì dopu à UEV i LED sò completamente spenti per un ciclu PWM.
Evitate di mette r, g è b à 255 è ricordate di invertisce quandu si usa.
Interrupts
L'essenza di l'interruzzione hè chì, in certi circustanzi, u chip cessà di eseguisce u prugramma principale è chjama una funzione esterna. L'interruzioni sò per via di influenze esterne o internu, ancu da u timer.
Quandu avemu creatu prima un prughjettu in ST Visual Develop, fora di main.c avemu una finestra cù un schedariu misteriosu stm8_interrupt_vector.cautomaticamente inclusu in u prugettu. In questu schedariu, una funzione hè attaccata à ogni interruzzione NonHandledInterrupt. Avemu bisognu di ligà a nostra funzione à l'interruzzione desiderata.
A datasheet hà una tabella di vettori di interruzzione, induve truvamu quelli chì avemu bisognu:
Avemu bisognu di cambià u LED à UEV, cusì l'interruzzione #13 hè necessaria.
Per quessa, prima, in u schedariu stm8_interrupt_vector.c cambia u nome di a funzione rispunsevuli di l'interruzzione numeru 13 (IRQ13) per difettu à a nostra propria:
{0x82, TIM2_Overflow}, /* irq13 */
Siconda, avemu da creà un schedariu main.h cuntenutu cum'è questu:
È infine, scrivite sta funzione in u vostru 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;
}
Resta per attivà l'interruzioni. Questu hè fattu cù un cumandamentu assembler. rim - vi tuccherà à circà lu in Manuale di prugrammazione:
//enable interrupts
_asm("rim");
Un'altra struzzione di assembler - sim - Disattiva l'interruzzioni. Deve esse disattivati mentre i novi valori sò scritti in a "memoria video" in modu chì una interruzzione causata in un momentu sfurtunatu ùn sguassate micca l'array.
Se almenu qualchissia questu articulu hè utile, allora ùn l'aghju micca scrittu in vain. Seraghju cuntentu di cumenti è rimarche, pruvaraghju à risponde à tutti.