Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

В y rhan gyntaf Ceisiais ddweud wrth beirianwyr electroneg hobi a fagwyd o Arduino pants sut a pham y dylent ddarllen taflenni data a dogfennaeth arall ar gyfer microreolwyr. Trodd y testun allan yn fawr, felly addewais ddangos enghreifftiau ymarferol mewn erthygl ar wahân. Wel, galwodd ei hun yn fadarch llefrith...

Heddiw, byddaf yn dangos i chi sut i ddefnyddio taflenni data i ddatrys eithaf syml, ond yn angenrheidiol ar gyfer llawer o brosiectau, tasgau ar reolwyr STM32 (Blue Pill) a STM8. Mae pob prosiect demo yn ymroddedig i fy hoff LEDs, byddwn yn eu goleuo mewn symiau mawr, y bydd yn rhaid i ni ddefnyddio pob math o berifferolion diddorol ar eu cyfer.

Unwaith eto, roedd y testun yn enfawr, felly er hwylustod rwy'n gwneud y cynnwys:

Pill Glas STM32: 16 LED gyda gyrrwr DM634
STM8: Sefydlu chwe pin PWM
STM8: 8 RGB LED ar dri phin, yn torri ar draws

Ymwadiad: Nid wyf yn beiriannydd, nid wyf yn esgus bod gennyf wybodaeth ddofn mewn electroneg, mae'r erthygl wedi'i bwriadu ar gyfer amaturiaid fel fi. Yn wir, roeddwn yn ystyried fy hun ddwy flynedd yn ôl fel y gynulleidfa darged. Pe bai rhywun wedi dweud wrthyf bryd hynny nad oedd taflenni data ar sglodyn anghyfarwydd yn frawychus i'w darllen, ni fyddwn wedi treulio llawer o amser yn chwilio am rai darnau o god ar y Rhyngrwyd ac yn dyfeisio baglau gyda siswrn a thâp gludiog.

Mae ffocws yr erthygl hon ar daflenni data, nid prosiectau, felly efallai na fydd y cod yn daclus iawn ac yn aml yn gyfyng. Mae'r prosiectau eu hunain yn syml iawn, er eu bod yn addas ar gyfer adnabyddiaeth gyntaf â'r sglodyn newydd.

Rwy'n gobeithio y bydd fy erthygl yn helpu rhywun ar gam tebyg o drochi yn y hobi.

STM32

16 LED gyda DM634 a SPI

Prosiect bach gan ddefnyddio Blue Pill (STM32F103C8T6) a gyrrwr DM634 LED. Gan ddefnyddio taflenni data, byddwn yn cyfrifo'r gyrrwr, porthladdoedd STM IO ac yn ffurfweddu SPI.

DM634

Gellir cysylltu sglodion Taiwan gyda 16 o allbynnau PWM 16-did mewn cadwyni. Mae'r model 12-did pen isel yn hysbys o brosiect domestig Pecyn golau. Ar un adeg, gan ddewis rhwng y DM63x a'r TLC5940 adnabyddus, dewisais DM am sawl rheswm: 1) Mae TLC ar Aliexpress yn bendant yn ffug, ond nid yw'r un hwn; 2) Mae gan DM PWM ymreolaethol gyda'i generadur amledd ei hun; 3) gellid ei brynu'n rhad ym Moscow, yn hytrach nag aros am barsel gan Ali. Ac, wrth gwrs, roedd yn ddiddorol dysgu sut i reoli'r sglodyn eich hun, yn hytrach na defnyddio llyfrgell barod. Bellach cyflwynir sglodion yn bennaf yn y pecyn SSOP24; maent yn hawdd eu sodro i addasydd.

Gan mai Taiwan yw'r gwneuthurwr, Taflen data mae'r sglodyn wedi'i ysgrifennu yn Saesneg Tsieineaidd, sy'n golygu y bydd yn hwyl. Yn gyntaf edrychwn ar y pinout (Cysylltiad Pin) deall pa goes i gysylltu beth i, a disgrifiad o'r pinnau (Disgrifiad Pin). 16 pin:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Ffynonellau Sink DC (Draen Agored)

Sinc / Allbwn draen agored - draen; ffynhonnell cerrynt sy'n llifo; mae'r allbwn wedi'i gysylltu â daear yn y cyflwr gweithredol - mae'r LEDs wedi'u cysylltu â'r gyrrwr gan gathodau. Yn drydanol, nid “draen agored” yw hwn, wrth gwrs (draen agored), ond mewn taflenni data ceir y dynodiad hwn ar gyfer pinnau yn y modd draen yn aml.

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Gwrthyddion allanol rhwng REXT a GND i osod gwerth cerrynt yr allbwn

Mae gwrthydd cyfeirio wedi'i osod rhwng y pin REXT a'r ddaear, sy'n rheoli gwrthiant mewnol yr allbynnau, gweler y graff ar dudalen 9 y daflen ddata. Yn y DM634, gall y gwrthiant hwn hefyd gael ei reoli gan feddalwedd, gan osod y disgleirdeb cyffredinol (disgleirdeb byd-eang); Nid af i fanylion yn yr erthygl hon, byddaf yn rhoi gwrthydd 2.2 - 3 kOhm yma.

I ddeall sut i reoli'r sglodyn, gadewch i ni edrych ar y disgrifiad o ryngwyneb y ddyfais:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Ie, dyma hi, Saesneg Tsieineaidd yn ei holl ogoniant. Mae cyfieithu hyn yn broblemus, gallwch ei ddeall os dymunwch, ond mae ffordd arall - edrychwch ar sut mae'r cysylltiad â'r swyddogaeth debyg TLC5940 yn cael ei ddisgrifio yn y daflen ddata:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
... Dim ond tri pin sydd eu hangen i fewnbynnu data i'r ddyfais. Mae ymyl gynyddol y signal SCLK yn symud y data o'r pin SIN i'r gofrestr fewnol. Ar ôl i'r holl ddata gael ei lwytho, mae signal XLAT byr uchel yn clymu'r data a drosglwyddir yn ddilyniannol i'r cofrestrau mewnol. Mae cofrestrau mewnol yn gatiau sy'n cael eu hysgogi gan lefel signal XLAT. Mae'r holl ddata yn cael ei drosglwyddo'r rhan fwyaf arwyddocaol yn gyntaf.

Latch – clicied/clicied/clo.
Ymyl codi - ymyl blaen y pwls
MSB yn gyntaf – y rhan fwyaf arwyddocaol (ar y chwith) ymlaen.
i glocio data – trawsyrru data yn ddilyniannol (dipyn wrth damaid).

Word clicied yn aml yn y dogfennau ar gyfer sglodion ac yn cael ei gyfieithu mewn gwahanol ffyrdd, felly er mwyn deall byddaf yn caniatáu i mi fy hun

rhaglen addysgol fachYn y bôn, cofrestr shifft yw'r gyrrwr LED. "Shift" (symud) yn yr enw - symudiad bitwise data y tu mewn i'r ddyfais: mae pob darn newydd sy'n cael ei wthio y tu mewn yn gwthio'r gadwyn gyfan ymlaen o'i blaen. Gan nad oes unrhyw un eisiau arsylwi amrantu anhrefnus o'r LEDs yn ystod y shifft, mae'r broses yn digwydd mewn cofrestrau byffer sydd wedi'u gwahanu oddi wrth y cofrestrau gweithio gan damper (clicied) yn fath o ystafell aros lle mae'r darnau wedi'u trefnu yn y dilyniant a ddymunir. Pan fydd popeth yn barod, mae'r caead yn agor ac mae'r darnau'n mynd i'r gwaith, gan ddisodli'r swp blaenorol. Gair clicied yn y ddogfennaeth ar gyfer microcircuits bron bob amser yn awgrymu mwy llaith o'r fath, ni waeth pa gyfuniadau y caiff ei ddefnyddio.

Felly, mae trosglwyddo data i'r DM634 yn cael ei wneud fel hyn: gosodwch y mewnbwn DAI i werth y darn mwyaf arwyddocaol o'r LED pell, tynnwch DCK i fyny ac i lawr; gosod y mewnbwn DAI i werth y did nesaf, tynnu DCK; ac yn y blaen nes bod pob did wedi'i drosglwyddo (clocio i mewn), ar ôl hynny rydym yn tynnu LAT. Gellir gwneud hyn â llaw (bit-bang), ond mae'n well defnyddio rhyngwyneb SPI wedi'i deilwra'n arbennig ar gyfer hyn, gan ei fod yn cael ei gyflwyno ar ein STM32 mewn dau gopi.

Pill Glas STM32F103

Rhagarweiniol: Mae rheolwyr STM32 yn llawer mwy cymhleth nag Atmega328 nag y gallent ymddangos yn frawychus. Ar ben hynny, am resymau arbed ynni, mae bron pob perifferolion yn cael eu diffodd ar y dechrau, ac mae amlder y cloc yn 8 MHz o'r ffynhonnell fewnol. Yn ffodus, ysgrifennodd rhaglenwyr STM god sy'n dod â'r sglodyn i fyny i'r 72 MHz “wedi'i gyfrifo”, ​​ac roedd awduron yr holl IDEs rwy'n eu hadnabod yn ei gynnwys yn y weithdrefn gychwyn, felly nid oes angen i ni glocio (ond gallwch chi os ydych chi wir eisiau). Ond bydd yn rhaid i chi droi ar y perifferolion.

Dogfennaeth: Mae Blue Pill wedi'i gyfarparu â'r sglodyn STM32F103C8T6 poblogaidd, mae dwy ddogfen ddefnyddiol ar ei gyfer:

Yn y daflen ddata efallai y bydd gennym ddiddordeb mewn:

  • Pinouts - pinouts sglodion - rhag ofn y byddwn yn penderfynu gwneud y byrddau ein hunain;
  • Map Cof – map cof ar gyfer sglodyn penodol. Mae gan y Llawlyfr Cyfeirio fap ar gyfer y llinell gyfan, ac mae'n sôn am gofrestrau nad oes gan ein rhai ni.
  • Tabl Diffiniadau Pin – rhestru prif swyddogaethau a swyddogaethau amgen pinnau; ar gyfer y “bilsen las” gallwch ddod o hyd i luniau mwy cyfleus ar y Rhyngrwyd gyda rhestr o binnau a'u swyddogaethau. Felly, rydyn ni'n Google ar unwaith yn pinio Blue Pill ac yn cadw'r llun hwn wrth law:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
DS: roedd gwall yn y llun o'r Rhyngrwyd, a nodwyd yn y sylwadau, diolch am hynny. Mae'r llun wedi'i ddisodli, ond mae hon yn wers - mae'n well gwirio gwybodaeth nid o daflenni data.

Rydyn ni'n tynnu'r daflen ddata, yn agor y Llawlyfr Cyfeirio, ac o hyn ymlaen rydyn ni'n ei ddefnyddio'n unig.
Gweithdrefn: rydym yn delio â mewnbwn / allbwn safonol, yn ffurfweddu SPI, yn troi'r perifferolion angenrheidiol ymlaen.

Mewnbwn Allbwn

Ar yr Atmega328, mae I/O yn cael ei weithredu'n hynod o syml, a dyna pam y gall y doreth o opsiynau STM32 fod yn ddryslyd. Nawr dim ond casgliadau sydd eu hangen arnom, ond mae gan hyd yn oed y rhain bedwar opsiwn:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
draen agored, gwthio-tynnu, gwthio-tynnu amgen, draen agored amgen

"Tynnu-gwthio" (gwthio-tynnu) yw'r allbwn arferol o'r Arduino, gall y pin gymryd y gwerth naill ai UCHEL neu ISEL. Ond gyda “draen agored” mae yna anawsterau, er mewn gwirionedd mae popeth yn syml yma:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Cyfluniad allbwn / pan fydd y porthladd wedi'i neilltuo i allbwn: / byffer allbwn wedi'i alluogi: / - modd draen agored: mae "0" yn y gofrestr allbwn yn galluogi N-MOS, mae "1" yn y gofrestr allbwn yn gadael y porthladd yn y modd Hi-Z ( Nid yw P-MOS wedi'i actifadu ) / – modd gwthio-tynnu: mae “0” yn y gofrestr allbwn yn actifadu N-MOS, mae “1” yn y gofrestr allbwn yn actifadu P-MOS.

Yr holl wahaniaeth rhwng draen agored (draen agored) o "push-pull" (gwthio-tynnu) yw na all y pin cyntaf dderbyn y cyflwr UCHEL: wrth ysgrifennu un i'r gofrestr allbwn, mae'n mynd i'r modd gwrthiant uchel (rhwystriant uchel, Hi-Z). Wrth ysgrifennu sero, mae'r pin yn ymddwyn yr un peth yn y ddau fodd, yn rhesymegol ac yn drydanol.

Yn y modd allbwn arferol, mae'r pin yn darlledu cynnwys y gofrestr allbwn yn unig. Yn y "amgen" mae'n cael ei reoli gan y perifferolion cyfatebol (gweler 9.1.4):

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Os yw did porthladd wedi'i ffurfweddu fel pin swyddogaeth arall, mae'r gofrestr pin yn anabl ac mae'r pin wedi'i gysylltu â'r pin ymylol.

Disgrifir ymarferoldeb amgen pob pin yn Diffiniadau Pin Mae'r daflen ddata ar y ddelwedd a lawrlwythwyd. I'r cwestiwn beth i'w wneud os oes gan pin sawl swyddogaeth amgen, rhoddir yr ateb gan droednodyn yn y daflen ddata:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Os yw perifferolion lluosog yn defnyddio'r un pin, er mwyn osgoi gwrthdaro rhwng swyddogaethau amgen, dim ond un ymylol y dylid ei ddefnyddio ar y tro, wedi'i doglo gan ddefnyddio did galluogi cloc ymylol (yn y gofrestr RCC briodol).

Yn olaf, mae gan binnau yn y modd allbwn gyflymder cloc hefyd. Mae hon yn nodwedd arbed ynni arall; yn ein hachos ni, rydyn ni'n ei osod i'r eithaf ac yn ei anghofio.

Felly: rydym yn defnyddio SPI, sy'n golygu y dylai dau bin (gyda data a gyda signal cloc) fod yn “swyddogaeth gwthio-tynnu amgen”, a dylai un arall (LAT) fod yn “wthio-dynnu rheolaidd”. Ond cyn eu neilltuo, gadewch i ni ddelio â SPI.

SPI

Rhaglen addysgol fach arall

Mae SPI neu Ryngwyneb Ymylol Cyfresol (rhyngwyneb perifferol cyfresol) yn rhyngwyneb syml ac effeithiol iawn ar gyfer cysylltu MK â MKs eraill a'r byd allanol yn gyffredinol. Mae egwyddor ei weithrediad eisoes wedi'i ddisgrifio uchod, lle am y gyrrwr LED Tsieineaidd (yn y llawlyfr cyfeirio, gweler adran 25). Gall SPI weithredu yn y modd meistr (“meistr”) a chaethwas (“caethwas”). Mae gan SPI bedair sianel sylfaenol, ac ni ellir defnyddio pob un ohonynt:

  • MOSI, Allbwn Meistr / Mewnbwn Caethweision: mae'r pin hwn yn trosglwyddo data yn y modd meistr, ac yn derbyn data yn y modd caethweision;
  • MISO, Mewnbwn Meistr / Allbwn Caethweision: i'r gwrthwyneb, mae'n derbyn yn y meistr, ac yn trosglwyddo yn y caethwas;
  • SCK, Cloc Cyfresol: yn gosod amlder trosglwyddo data yn y meistr neu'n derbyn signal cloc yn y caethwas. Yn ei hanfod taro curiadau;
  • SS, Slave Select: gyda chymorth y sianel hon, mae'r caethwas yn gwybod bod eisiau rhywbeth ganddo. Ar STM32 fe'i gelwir yn NSS, lle mae N = negatif, h.y. mae'r rheolydd yn dod yn gaethwas os oes tir yn y sianel hon. Mae'n cyfuno'n dda â'r modd Allbwn Drain Agored, ond stori arall yw honno.

Fel popeth arall, mae SPI ar STM32 yn gyfoethog o ran ymarferoldeb, sy'n ei gwneud hi braidd yn anodd ei ddeall. Er enghraifft, gall weithio nid yn unig gyda SPI, ond hefyd gyda rhyngwyneb I2S, ac yn y ddogfennaeth mae eu disgrifiadau'n gymysg, mae angen torri'r gormodedd i ffwrdd mewn modd amserol. Mae ein tasg yn hynod o syml: mae angen i ni anfon data gan ddefnyddio MOSI a SCK yn unig. Rydyn ni'n mynd i adran 25.3.4 (cyfathrebu hanner dwplecs, cyfathrebu hanner dwplecs), lle rydyn ni'n dod o hyd 1 cloc ac 1 wifren ddata un cyfeiriad (1 signal cloc ac 1 ffrwd data un cyfeiriad):

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Yn y modd hwn, mae'r rhaglen yn defnyddio SPI naill ai yn y modd trawsyrru-yn-unig neu dderbyn yn unig. / Mae modd trosglwyddo yn unig yn debyg i'r modd deublyg: trosglwyddir data ar y pin trawsyrru (MOSI yn y modd meistr neu MISO yn y modd caethweision), a gellir defnyddio'r pin derbyn (MISO neu MOSI yn y drefn honno) fel pin I/O rheolaidd . Yn yr achos hwn, dim ond y byffer Rx y mae angen i'r cais ei anwybyddu (os caiff ei ddarllen, ni fydd unrhyw ddata a drosglwyddir yno).

Gwych, mae'r pin MISO yn rhad ac am ddim, gadewch i ni gysylltu'r signal LAT ag ef. Edrychwn ar Slave Select, y gellir ei reoli'n rhaglennol ar y STM32, sy'n hynod gyfleus. Rydym yn darllen y paragraff o'r un enw yn adran 25.3.1 SPI Disgrifiad Cyffredinol:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Mae gwybodaeth rheoli meddalwedd NSS (SSM = 1) / dewis caethweision wedi'i chynnwys yn rhan SSI y gofrestr SPI_CR1. Mae'r pin NSS allanol yn parhau i fod yn rhad ac am ddim ar gyfer anghenion cymwysiadau eraill.

Mae'n bryd ysgrifennu at y cofrestri. Penderfynais ddefnyddio SPI2, edrychwch am ei gyfeiriad sylfaenol yn y daflen ddata - yn adran 3.3 Map Cof:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Wel, gadewch i ni ddechrau:

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

Agorwch adran 25.3.3 gyda’r teitl hunanesboniadol “Configuring SPI in Master Mode”:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

1. Gosodwch amledd y cloc cyfresol gyda darnau BR[2:0] yn y gofrestr SPI_CR1.

Cesglir y cofrestri yn yr adran llawlyfr cyfeirio o'r un enw. Newid cyfeiriad (Cyfeiriad gwrthbwyso) ar gyfer CR1 - 0x00, yn ddiofyn mae pob did yn cael ei glirio (Ailosod gwerth 0x0000):

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Mae'r darnau BR yn gosod rhannwr cloc y rheolydd, gan bennu pa mor aml y bydd y SPI yn gweithredu. Ein hamledd STM32 fydd 72 MHz, mae'r gyrrwr LED, yn ôl ei daflen ddata, yn gweithredu gydag amledd hyd at 25 MHz, felly mae angen i ni rannu â phedwar (BR[2:0] = 001).

#define _SPI_CR1 0x00

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

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

2. Gosodwch y darnau CPOL a CPHA i ddiffinio'r berthynas rhwng trosglwyddo data ac amseriad cloc cyfresol (gweler y diagram ar dudalen 240)

Gan ein bod yn darllen taflen ddata yma ac nid yn edrych ar sgematigau, gadewch i ni edrych yn agosach ar ddisgrifiad testun y darnau CPOL a CPHA ar dudalen 704 (Disgrifiad Cyffredinol SPI):

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Cyfnod cloc a polaredd
Gan ddefnyddio darnau CPOL a CPHA y gofrestr SPI_CR1, gallwch ddewis pedair perthynas amseru yn rhaglennol. Mae did CPOL (polaredd cloc) yn rheoli cyflwr signal y cloc pan nad oes data'n cael ei drosglwyddo. Mae'r darn hwn yn rheoli'r dulliau meistr a chaethweision. Os caiff CPOL ei ailosod, mae'r pin SCK yn isel yn y modd gorffwys. Os yw'r did CPOL wedi'i osod, mae'r pin SCK yn uchel yn ystod y modd gorffwys.
Pan fydd y did CPHA (cyfnod cloc) wedi'i osod, y strôb trap did uchel yw ail ymyl y signal SCK (yn disgyn os yw CPOL yn glir, yn codi os gosodir CPOL). Mae'r data yn cael ei ddal gan yr ail newid yn y signal cloc. Os yw'r did CPHA yn glir, y strôb trap did uchel yw ymyl codi'r signal SCK (ymyl disgyn os yw CPOL wedi'i osod, ymyl codi os caiff CPOL ei glirio). Mae data'n cael ei ddal ar y newid cyntaf yn signal y cloc.

Ar ôl amsugno'r wybodaeth hon, rydym yn dod i'r casgliad bod yn rhaid i'r ddau did aros yn sero, oherwydd Rydym am i'r signal SCK aros yn isel pan nad yw'n cael ei ddefnyddio, ac i ddata gael ei drosglwyddo ar ymyl codi'r curiad (gweler Ffig. Rising Edge yn y daflen ddata DM634).

Gyda llaw, dyma ni'n dod ar draws nodwedd o'r eirfa mewn taflenni data ST am y tro cyntaf: ynddynt mae'r ymadrodd “ailosod y did i sero” wedi'i ysgrifennu i ailosod ychydigAc nid i glirio ychydig, fel, er enghraifft, Atmega.

3. Gosodwch y did DFF i benderfynu a yw'r bloc data yn fformat 8-bit neu 16-bit

Cymerais DM16 634-did yn benodol er mwyn peidio â thrafferthu gyda throsglwyddo data PWM 12-did, fel y DM633. Mae'n gwneud synnwyr gosod DFF i un:

#define DFF         0x0800

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

4. Ffurfweddwch y bit LSBFIRST yn y gofrestr SPI_CR1 i benderfynu ar y fformat bloc

Mae LSBFIRST, fel y mae ei enw'n awgrymu, yn ffurfweddu trosglwyddiad gyda'r darn lleiaf arwyddocaol yn gyntaf. Ond mae DM634 eisiau derbyn data gan ddechrau o'r darn mwyaf arwyddocaol. Felly, rydym yn ei adael wedi'i ailosod.

5. Yn y modd caledwedd, os oes angen mewnbwn o'r pin NSS, cymhwyswch signal uchel i'r pin NSS yn ystod y dilyniant trosglwyddo beit cyfan. Yn y modd meddalwedd NSS, gosodwch y darnau SSM a SSI yn y gofrestr SPI_CR1. Os yw'r pin NSS i gael ei ddefnyddio fel allbwn, dim ond y did SSOE sydd angen ei osod.

Gosod SSM a SSI i anghofio am y modd caledwedd NSS:

#define SSI         0x0100
#define SSM         0x0200

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

6. Rhaid gosod y darnau MSTR a SPE (dim ond os yw'r signal NSS yn uchel y maent yn parhau i fod wedi'u gosod)

Mewn gwirionedd, gyda'r darnau hyn rydym yn dynodi ein SPI yn feistr ac yn ei droi ymlaen:

#define MSTR        0x0004
#define SPE         0x0040

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

Mae SPI wedi'i ffurfweddu, gadewch i ni ysgrifennu swyddogaethau sy'n anfon bytes at y gyrrwr ar unwaith. Parhau i ddarllen 25.3.3 “Ffurfweddu SPI yn y modd meistr”:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Gorchymyn trosglwyddo data
Mae trosglwyddo yn dechrau pan fydd beit yn cael ei ysgrifennu i'r byffer Tx.
Mae'r beit data yn cael ei lwytho i mewn i'r gofrestr shifft yn cyfochrog modd (o'r bws mewnol) yn ystod trosglwyddiad y darn cyntaf, ac ar ôl hynny caiff ei drosglwyddo i dilyniannol Modd pin MOSI, y rhan gyntaf neu'r olaf ymlaen yn dibynnu ar osodiad y did LSBFIRST yn y gofrestr CPI_CR1. Gosodir baner TXE ar ôl trosglwyddo data o byffer Tx i gofrestr shifft, a hefyd yn cynhyrchu ymyriad os yw'r did TXEIE yn y gofrestr CPI_CR1 wedi'i osod.

Amlygais ychydig eiriau yn y cyfieithiad i dynnu sylw at un nodwedd o weithrediad SPI mewn rheolwyr STM. Ar Atmega mae baner TXE (Tx Gwag, Tx yn wag ac yn barod i dderbyn data) yn cael ei osod dim ond ar ôl i'r beit cyfan gael ei anfon allan. Ac yma gosodir y faner hon ar ôl i'r beit gael ei fewnosod yn y gofrestr sifft fewnol. Gan ei fod yn cael ei wthio yno gyda'r holl ddarnau ar yr un pryd (yn gyfochrog), ac yna mae'r data'n cael ei drosglwyddo'n ddilyniannol, mae TXE yn cael ei osod cyn i'r beit gael ei anfon yn llwyr. Mae hyn yn bwysig oherwydd yn achos ein gyrrwr LED, mae angen inni dynnu'r pin LAT ar ôl ei anfon holl data, h.y. Ni fydd baner TXE yn unig yn ddigon i ni.

Mae hyn yn golygu bod angen baner arall. Gadewch i ni edrych ar 25.3.7 - “Faneri Statws”:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
<…>
Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
baner BRYSUR
Mae'r faner BSY yn cael ei gosod a'i chlirio gan galedwedd (nid yw ysgrifennu ato yn cael unrhyw effaith). Mae baner BSY yn nodi cyflwr yr haen gyfathrebu SPI.
Mae'n ailosod:
pan fydd y trosglwyddiad wedi'i gwblhau (ac eithrio yn y modd meistr os yw'r trosglwyddiad yn barhaus)
pan fydd SPI yn anabl
pan fydd gwall modd meistr yn digwydd (MODF=1)
Os nad yw'r trosglwyddiad yn barhaus, caiff y faner BSY ei chlirio rhwng pob trosglwyddiad data

Iawn, bydd hyn yn dod yn ddefnyddiol. Dewch i ni ddarganfod ble mae'r byffer Tx wedi'i leoli. I wneud hyn, darllenwch “Cofrestr Ddata SPI”:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Darnau 15:0 DR[15:0] Cofrestr Data
Data a dderbyniwyd neu ddata i'w drosglwyddo.
Rhennir y gofrestr ddata yn ddwy glustog - un ar gyfer ysgrifennu (byffer trosglwyddo) ac un ar gyfer darllen (derbyn byffer). Mae ysgrifennu at y gofrestr ddata yn ysgrifennu at y byffer Tx, a bydd darllen o'r gofrestr ddata yn dychwelyd y gwerth a gynhwysir yn y byffer Rx.

Wel, a'r gofrestr statws, lle mae'r baneri TXE a BSY i'w cael:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Rydym yn ysgrifennu:

#define _SPI_DR  0x0C
#define _SPI_SR  0x08

#define BSY         0x0080
#define TXE         0x0002

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

Wel, gan fod angen i ni drosglwyddo 16 gwaith dau beit, yn ôl nifer yr allbynnau gyrrwr LED, rhywbeth fel hyn:

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

Ond nid ydym yn gwybod sut i dynnu'r pin LAT eto, felly awn yn ôl i I/O.

Aseinio pinnau

Yn y STM32F1, mae'r cofrestrau sy'n gyfrifol am gyflwr y pinnau yn eithaf anarferol. Mae'n amlwg bod mwy ohonyn nhw nag Atmega, ond maen nhw hefyd yn wahanol i sglodion STM eraill. Adran 9.1 Disgrifiad Cyffredinol o GPIO:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Pob un o'r porthladdoedd I/O pwrpas cyffredinol (GPIO) Mae ganddi ddwy gofrestr ffurfweddu 32-did (GPIOx_CRL a GPIOx_CRH), dwy gofrestr ddata 32-did (GPIOx_IDR a GPIOx_ODR), cofrestr set/ailosod 32-did (GPIOx_BSRR), cofrestr ailosod 16-did (GPIOx_BRR) a chofrestr 32-did cofrestr blocio didau (GPIOx_LCKR).

Mae'r ddwy gofrestr gyntaf yn anarferol, a hefyd yn eithaf anghyfleus, oherwydd mae'r 16 pin porthladd wedi'u gwasgaru ar eu traws mewn fformat “pedwar did y brawd”. Y rhai. mae pinnau sero i saith yn CRL, ac mae'r gweddill yn CRH. Ar yr un pryd, mae'r cofrestrau sy'n weddill yn cynnwys darnau holl biniau'r porthladd yn llwyddiannus - yn aml yn hanner "cadw" sy'n weddill.

Er mwyn symlrwydd, gadewch i ni ddechrau o ddiwedd y rhestr.

Nid oes angen cofrestr blocio arnom.

Mae'r cofrestrau gosod ac ailosod yn eithaf doniol gan eu bod yn rhannol yn dyblygu ei gilydd: dim ond yn BSRR y gallwch chi ysgrifennu popeth, lle bydd y darnau 16 uwch yn ailosod y pin i sero, a bydd y rhai isaf yn cael eu gosod i 1, neu gallwch chi hefyd defnyddiwch BRR, gyda'r 16 did isaf yn ailosod y pin . Rwy'n hoffi'r ail opsiwn. Mae'r cofrestrau hyn yn bwysig oherwydd eu bod yn darparu mynediad atomig i binnau:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Gosod neu Ailosod Atomig
Nid oes angen analluogi ymyriadau wrth raglennu GPIOx_ODR ar y lefel didau: gellir newid un did neu fwy gydag un gweithrediad ysgrifennu atomig APB2. Cyflawnir hyn trwy ysgrifennu "1" i'r gofrestr gosod/ailosod (GPIOx_BSRR neu, i'w ailosod yn unig, GPIOx_BRR) o'r darn sydd angen ei newid. Bydd darnau eraill yn aros heb eu newid.

Mae gan y cofrestrau data enwau eithaf hunanesboniadol - IDR = mewnbwn Cofrestr Cyfeiriad, cofrestr mewnbwn; ODR = Allbwn Cofrestr Cyfeiriad, cofrestr allbwn. Ni fydd eu hangen arnom yn y prosiect presennol.

Ac yn olaf, cofrestrau rheoli. Gan fod gennym ddiddordeb yn yr ail binnau SPI, sef PB13, PB14 a PB15, rydym yn edrych ar CRH ar unwaith:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Ac fe welwn y bydd angen i ni ysgrifennu rhywbeth mewn darnau o 20 i 31.

Rydym eisoes wedi cyfrifo uwchlaw'r hyn yr ydym ei eisiau o binnau, felly yma fe wnaf heb lun, byddaf yn dweud bod MODE yn nodi'r cyfeiriad (mewnbwn os yw'r ddau ddarn wedi'u gosod i 0) a chyflymder pin (mae angen 50MHz arnom, h.y. y ddau pin i “1”), ac mae CNF yn gosod y modd: “gwthio-dynnu” rheolaidd – 00, “amgen” – 10. Yn ddiofyn, fel y gwelwn uchod, mae gan bob pin y trydydd did o'r gwaelod (CNF0), mae'n eu gosod i'r modd mewnbwn fel y bo'r angen.

Gan fy mod yn bwriadu gwneud rhywbeth arall gyda'r sglodyn hwn, er symlrwydd, rwyf wedi diffinio'r holl werthoedd MODE a CNF posibl ar gyfer y cofrestrau rheoli is ac uwch.

Rhywsut fel hyn

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

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

Mae ein pinnau wedi'u lleoli ar borth B (cyfeiriad sylfaenol - 0x40010C00), cod:

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

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

//используем стандартный SPI2: MOSI на B15, CLK на B13
//LAT пусть будет на неиспользуемом MISO – B14

//очищаем дефолтный бит, он нам точно не нужен
_PORTB_ (_CRH) &= ~(CNF15_0 | CNF14_0 | CNF13_0 | CNF12_0);

//альтернативные функции для MOSI и SCK
_PORTB_ (_CRH) |= CNF15_1 | CNF13_1;

//50 МГц, MODE = 11
_PORTB_ (_CRH) |= MODE15_1 | MODE15_0 | MODE14_1 | MODE14_0 | MODE13_1 | MODE13_0;

Ac, yn unol â hynny, gallwch ysgrifennu diffiniadau ar gyfer LAT, a fydd yn cael eu plethu gan gofrestrau BRR a BSRR:

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

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

(LAT_low gan syrthni, mae wedi bod felly erioed, gadewch iddo aros)

Nawr mae popeth yn wych, ond nid yw'n gweithio. Oherwydd mai STM32 yw hwn, maen nhw'n arbed trydan, sy'n golygu bod angen i chi alluogi clocio'r perifferolion gofynnol.

Trowch clocio ymlaen

Yr oriawr, a elwir hefyd yn Cloc, sy'n gyfrifol am glocio. A gallem eisoes sylwi ar y talfyriad RCC. Edrychwn amdano yn y dogfennau: Ailosod a Rheoli Cloc yw hwn.

Fel y dywedwyd uchod, yn ffodus, gwnaed y rhan anoddaf o'r pwnc clocio i ni gan bobl o STM, a diolchwn yn fawr iddynt am hynny (unwaith eto byddaf yn rhoi dolen i Gwefan Di Halt, i'w gwneud yn glir pa mor ddryslyd ydyw). Dim ond cofrestrau sy'n gyfrifol am alluogi clocio ymylol sydd eu hangen arnom (Cofrestrau Galluogi Cloc Ymylol). Yn gyntaf, gadewch i ni ddod o hyd i gyfeiriad sylfaenol y PCRh, mae ar ddechrau'r “Map Cof”:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

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

Ac yna naill ai cliciwch ar y ddolen lle rydych chi'n ceisio dod o hyd i rywbeth yn y plât, neu, yn llawer gwell, ewch trwy'r disgrifiadau o'r cofrestrau galluogi o'r adrannau am galluogi cofrestri. Ble byddwn yn dod o hyd i RCC_APB1ENR a RCC_APB2ENR:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Ac maent, yn unol â hynny, yn cynnwys darnau sy'n cynnwys clocio SPI2, IOPB (I/O Port B) a swyddogaethau amgen (AFIO).

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

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

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

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

Gellir dod o hyd i'r cod terfynol yma.

Os oes gennych y cyfle a'r awydd i brofi, yna cysylltwch y DM634 fel hyn: DAI i PB15, DCK i PB13, LAT i PB14. Rydyn ni'n pweru'r gyrrwr o 5 folt, peidiwch ag anghofio cysylltu'r tiroedd.

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

STM8 PWM

PWM ar STM8

Pan oeddwn i newydd gynllunio'r erthygl hon, penderfynais, fel enghraifft, geisio meistroli rhywfaint o ymarferoldeb sglodyn anghyfarwydd gan ddefnyddio taflen ddata yn unig, fel na fyddwn yn y pen draw gyda chrydd heb esgidiau. Roedd STM8 yn ddelfrydol ar gyfer y rôl hon: yn gyntaf, roedd gen i un neu ddau o fyrddau Tsieineaidd gyda STM8S103, ac yn ail, nid yw'n boblogaidd iawn, ac felly mae'r demtasiwn i ddarllen a dod o hyd i ateb ar y Rhyngrwyd yn dibynnu ar ddiffyg yr union atebion hyn.

Mae gan y sglodion hefyd Taflen data и llawlyfr cyfeirio RM0016, yn y cyntaf mae cyfeiriadau pinout a chofrestru, yn yr ail - popeth arall. Mae STM8 wedi'i raglennu yn C mewn IDE ofnadwy ST Gweledol Datblygu.

Clocio ac I/O

Yn ddiofyn, mae STM8 yn gweithredu ar amlder o 2 MHz, rhaid cywiro hyn ar unwaith.

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Cloc HSI (Cyflymder Uchel Mewnol).
Mae'r signal cloc HSI yn deillio o osgiliadur mewnol 16 MHz RC gyda rhannwr rhaglenadwy (1 i 8). Mae wedi'i osod yn y gofrestr rhannwr cloc (CLK_CKDIVR).
Sylwch: ar y dechrau, mae osgiliadur HSI RC gyda rhannwr o 8 yn cael ei ddewis fel prif ffynhonnell y signal cloc.

Rydym yn dod o hyd i gyfeiriad y gofrestr yn y daflen ddata, y disgrifiad yn refman ac yn gweld bod angen clirio'r gofrestr:

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

Gan ein bod ni'n mynd i redeg PWM a chysylltu'r LEDs, gadewch i ni edrych ar y pinout:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Mae'r sglodion yn fach, mae llawer o swyddogaethau'n cael eu hatal ar yr un pinnau. Yr hyn sydd mewn cromfachau sgwâr yw “swyddogaeth amgen”, caiff ei newid gan “option beit” (beit opsiwn) – rhywbeth fel ffiwsiau Atmega. Gallwch newid eu gwerthoedd yn rhaglennol, ond nid yw'n angenrheidiol, oherwydd Dim ond ar ôl ailgychwyn y caiff y swyddogaeth newydd ei actifadu. Mae'n haws defnyddio ST Visual Programmer (wedi'i lawrlwytho gyda Visual Develop), a all newid y beit hyn. Mae'r pinout yn dangos bod pinnau CH1 a CH2 yr amserydd cyntaf wedi'u cuddio mewn cromfachau sgwâr; mae angen gosod y darnau AFR1 ac AFR0 yn STVP, a bydd yr ail un hefyd yn trosglwyddo allbwn CH1 yr ail amserydd o PD4 i PC5.

Felly, bydd 6 pin yn rheoli'r LEDs: PC6, PC7 a PC3 ar gyfer yr amserydd cyntaf, PC5, PD3 a PA3 ar gyfer yr ail.

Mae sefydlu'r pinnau I/O eu hunain ar STM8 yn symlach ac yn fwy rhesymegol nag ar STM32:

  • cyfarwydd o gofrestr cyfeiriad data Atmega DDR (Cofrestr Cyfeiriad Data): 1 = allbwn;
  • y gofrestr reoli gyntaf CR1, pan fydd allbwn, yn gosod y modd gwthio-dynnu (1) neu ddraen agored (0); ers i mi gysylltu'r LEDs i'r sglodion gyda catodes, rwy'n gadael sero yma;
  • yr ail gofrestr rheoli CR2, pan fydd allbwn, yn gosod y cyflymder cloc: 1 = 10 MHz

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

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

gosodiad PWM

Yn gyntaf, gadewch i ni ddiffinio'r termau:

  • Amledd PWM – pa mor aml y mae'r amserydd yn ticio;
  • Ail-lwytho'n awtomatig, AR – gwerth y gellir ei lwytho'n awtomatig y bydd yr amserydd yn cyfrif iddo (cyfnod curiad y galon);
  • Digwyddiad Diweddaru, UEV – digwyddiad sy'n digwydd pan fydd yr amserydd wedi cyfrif i AR;
  • Cylch Dyletswydd PWM – cylch dyletswydd PWM, a elwir yn aml yn “ffactor dyletswydd”;
  • Dal/Cymharu Gwerth – gwerth ar gyfer dal/cymharu, y mae'r amserydd wedi cyfrif iddo bydd yn gwneud rhywbeth (yn achos PWM, mae'n gwrthdroi'r signal allbwn);
  • Gwerth Preload - gwerth wedi'i lwytho ymlaen llaw. Cymharwch werth Ni all newid tra bod yr amserydd yn ticio, fel arall bydd y cylch PWM yn torri. Felly, mae gwerthoedd a drosglwyddir newydd yn cael eu gosod mewn byffer a'u tynnu allan pan fydd yr amserydd yn cyrraedd diwedd ei gyfrif i lawr ac yn cael ei ailosod;
  • Ymyl-alinio и Moddau wedi'u halinio yn y canol – aliniad ar hyd y ffin ac yn y canol, yr un peth ag un Atmel PWM Cyflym и PWM cam-gywir.
  • OCiREF, Allbwn Cymharu Signal Cyfeirnod - signal allbwn cyfeirio, mewn gwirionedd, yr hyn sy'n ymddangos ar y pin cyfatebol yn y modd PWM.

Fel sydd eisoes yn amlwg o'r pinout, mae gan ddau amserydd alluoedd PWM - y cyntaf a'r ail. Mae'r ddau yn 16-bit, mae gan y cyntaf lawer o nodweddion ychwanegol (yn benodol, gall gyfrif i fyny ac i lawr). Mae angen i’r ddau ohonom weithio’n gyfartal, felly penderfynais ddechrau gyda’r ail un sy’n amlwg yn dlotach, er mwyn peidio â defnyddio rhywbeth nad yw yno ar ddamwain. Rhywfaint o broblem yw bod y disgrifiad o ymarferoldeb PWM yr holl amserwyr yn y llawlyfr cyfeirio yn y bennod am yr amserydd cyntaf (17.5.7 Modd PWM), felly mae'n rhaid i chi neidio yn ôl ac ymlaen trwy gydol y ddogfen trwy'r amser.

Mae gan PWM ar STM8 fantais bwysig dros PWM ar Atmega:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
PWM wedi'i Alinio â'r Ffin
Cyfluniad cyfrif o'r gwaelod i'r brig
Mae cyfrif o'r gwaelod i fyny yn weithredol os yw'r did DIR yn y gofrestr TIM_CR1 yn cael ei glirio
Enghraifft
Mae'r enghraifft yn defnyddio'r modd PWM cyntaf. Mae'r signal cyfeirio PWM OCiREF yn cael ei ddal yn uchel cyhyd â TIM1_CNT < TIM1_CCRi. Fel arall, mae'n cymryd lefel isel. Os yw'r gwerth cymhariaeth yn y gofrestr TIM1_CCRi yn fwy na'r gwerth llwytho awtomatig (cofrestr TIM1_ARR), cedwir y signal OCiREF ar 1. Os mai 0 yw'r gwerth cymhariaeth, cedwir OCiREF ar sero....

Amserydd STM8 yn ystod digwyddiad diweddaru sieciau yn gyntaf cymharu gwerth, a dim ond wedyn yn cynhyrchu signal cyfeirio. Mae amserydd Atmega yn sgriwio i fyny yn gyntaf ac yna'n cymharu, gan arwain at compare value == 0 nodwydd yw'r allbwn, y mae'n rhaid ymdrin â hi rywsut (er enghraifft, trwy wrthdroi'r rhesymeg yn rhaglennol).

Felly beth rydyn ni eisiau ei wneud: PWM 8-did (AR == 255), cyfrif o'r gwaelod i'r brig, aliniad ar hyd y ffin. Gan fod y bylbiau golau wedi'u cysylltu â'r sglodion gan gathodau, dylai'r PWM allbwn 0 (LED ymlaen) nes cymharu gwerth ac 1 ar ôl.

Yr ydym eisoes wedi darllen am rai Modd PWM, felly rydym yn dod o hyd i'r gofrestr ofynnol o'r ail amserydd trwy chwilio yn y llawlyfr cyfeirio ar gyfer yr ymadrodd hwn (18.6.8 - TIMx_CCMR1):

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
110: Modd PWM cyntaf - wrth gyfrif o'r gwaelod i'r brig, mae'r sianel gyntaf yn weithredol tra TIMx_CNT < TIMx_CCR1. Fel arall, mae'r sianel gyntaf yn anactif. [Ymhellach yn y ddogfen mae copi-gludo gwallus o amserydd 1] 111: Ail fodd PWM – wrth gyfrif o'r gwaelod i'r brig, mae'r sianel gyntaf yn anactif tra TIMx_CNT < TIMx_CCR1. Fel arall, mae'r sianel gyntaf yn weithredol.

Gan fod y LEDs wedi'u cysylltu â'r MK trwy gathodau, mae'r ail fodd yn addas i ni (yr un cyntaf hefyd, ond nid ydym yn gwybod hynny eto).

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Did 3 OC1PE: Galluogi pin 1 rhaglwytho
0: Mae cofrestr rhaglwytho ar TIMx_CCR1 wedi'i hanalluogi. Gallwch ysgrifennu at TIMx_CCR1 unrhyw bryd. Mae'r gwerth newydd yn gweithio ar unwaith.
1: Mae cofrestr rhaglwytho ar TIMx_CCR1 wedi'i galluogi. Gweithrediadau darllen/ysgrifennu cyrchu'r gofrestr rhaglwytho. Mae'r gwerth rhaglwythedig TIMx_CCR1 yn cael ei lwytho i'r gofrestr gysgodol yn ystod pob digwyddiad diweddaru.
* Nodyn: Er mwyn i'r modd PWM weithio'n iawn, rhaid galluogi'r cofrestrau rhaglwytho. Nid yw hyn yn angenrheidiol yn y modd signal sengl (mae'r did OPM wedi'i osod yn y gofrestr TImx_CR1).

Iawn, gadewch i ni droi popeth sydd ei angen arnom ar gyfer tair sianel yr ail amserydd ymlaen:

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

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

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

Mae AR yn cynnwys dwy gofrestr wyth did, mae popeth yn syml:

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

TIM2_ARRH = 0;
TIM2_ARRL = 255;

Dim ond o'r gwaelod i'r brig y gall yr ail amserydd gyfrif, aliniad ar hyd y ffin, nid oes angen newid dim. Gadewch i ni osod y rhannwr amledd, er enghraifft, i 256. Ar gyfer yr ail amserydd, mae'r rhannwr wedi'i osod yn y gofrestr TIM2_PSCR ac mae'n bŵer dau:

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

Y cyfan sydd ar ôl yw troi'r casgliadau ymlaen a'r ail amserydd ei hun. Mae'r broblem gyntaf yn cael ei datrys gan gofrestrau Dal/Cymharu Galluogi: mae dwy, tair sianel wedi'u gwasgaru ar eu traws yn anghymesur. Yma gallwn hefyd ddysgu ei bod yn bosibl newid polaredd y signal, h.y. mewn egwyddor, roedd yn bosibl defnyddio PWM Modd 1. Ysgrifennwn:

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

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

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

Ac yn olaf, rydyn ni'n cychwyn yr amserydd yn y gofrestr TImx_CR1:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

Gadewch i ni ysgrifennu analog syml o AnalogWrite(), a fydd yn trosglwyddo'r gwerthoedd gwirioneddol i'r amserydd i'w cymharu. Enwir y cofrestri yn rhagweladwy Dal/Cymharu cofrestrau, mae dau ohonyn nhw ar gyfer pob sianel: y rhai 8 did isel eu trefn yn TIM2_CCRxL a'r rhai lefel uchel yn TIM2_CCRxH. Gan ein bod wedi creu PWM 8-did, mae'n ddigon i ysgrifennu'r darnau lleiaf arwyddocaol yn unig:

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

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

Bydd y darllenydd sylwgar yn sylwi bod gennym PWM ychydig yn ddiffygiol, yn methu â chynhyrchu llenwad 100% (ar uchafswm gwerth 255, mae'r signal yn cael ei wrthdroi am un cylch amserydd). Ar gyfer LEDs nid yw hyn o bwys, a gall y darllenydd sylwgar eisoes ddyfalu sut i'w drwsio.

Mae PWM ar yr ail amserydd yn gweithio, gadewch i ni symud ymlaen i'r cyntaf.

Mae gan yr amserydd cyntaf yn union yr un darnau yn yr un cofrestrau (dim ond bod y darnau hynny a arhosodd yn “gadw” yn yr ail amserydd yn cael eu defnyddio'n weithredol yn y cyntaf ar gyfer pob math o bethau datblygedig). Felly, mae'n ddigon dod o hyd i gyfeiriadau'r un cofrestrau yn y daflen ddata a chopïo'r cod. Wel, newidiwch werth y rhannwr amledd, oherwydd ... mae'r amserydd cyntaf eisiau derbyn nid pŵer o ddau, ond gwerth 16-did union mewn dwy gofrestr Uchel Prescaler и isel. Rydyn ni'n gwneud popeth a ... nid yw'r amserydd cyntaf yn gweithio. Beth sy'n bod?

Dim ond trwy edrych trwy'r adran gyfan am gofrestrau rheoli amserydd 1 y gellir datrys y broblem, lle rydym yn edrych am yr un nad oes gan yr ail amserydd. Bydd 17.7.30 Torri'r gofrestr (TIM1_BKR), lle mae'r darn hwn:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Galluogi prif allbwn

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

Dyna i gyd yn sicr nawr, y cod yn yr un lle.

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

STM8 Amlblecs

Amlblecsio ar STM8

Y trydydd prosiect bach yw cysylltu wyth LED RGB â'r ail amserydd yn y modd PWM a gwneud iddynt ddangos gwahanol liwiau. Mae'n seiliedig ar y cysyniad o amlblecsio LED, sef os byddwch chi'n troi LEDs ymlaen ac i ffwrdd yn gyflym iawn, iawn, bydd yn ymddangos i ni eu bod ymlaen yn gyson (dyfalbarhad gweledigaeth, syrthni canfyddiad gweledol). Fe wnes i unwaith rhywbeth fel hyn ar Arduino.

Mae'r algorithm gwaith yn edrych fel hyn:

  • cysylltu anod y LED RGB cyntaf;
  • ei oleuo, gan anfon y signalau angenrheidiol i'r cathodes;
  • aros tan ddiwedd y cylch PWM;
  • cysylltu anod yr ail RGB LED;
  • ei goleuo...

Wel, etc. Wrth gwrs, ar gyfer gweithrediad hardd mae'n ofynnol bod yr anod wedi'i gysylltu a bod y LED yn cael ei “gynnau” ar yr un pryd. Wel, neu bron. Mewn unrhyw achos, mae angen i ni ysgrifennu cod a fydd yn allbwn gwerthoedd mewn tair sianel o'r ail amserydd, yn eu newid pan gyrhaeddir UEV, ac ar yr un pryd yn newid y LED RGB gweithredol ar hyn o bryd.

Gan fod newid LED yn awtomatig, mae angen i ni greu "cof fideo" y bydd y triniwr ymyriad yn derbyn data ohono. Mae hwn yn gyfres syml:

uint8_t colors[8][3];

Er mwyn newid lliw LED penodol, bydd yn ddigon i ysgrifennu'r gwerthoedd gofynnol i'r amrywiaeth hon. A bydd y newidyn yn gyfrifol am nifer y LED gweithredol

uint8_t cnt;

Demux

Ar gyfer amlblecsio cywir, yn rhyfedd ddigon, mae angen dadamlblecsydd CD74HC238 arnom. Demultiplexer - sglodyn sy'n gweithredu'r gweithredwr mewn caledwedd <<. Trwy dri phin mewnbwn (didiau 0, 1 a 2) rydyn ni'n bwydo rhif tri-did X iddo, ac mewn ymateb mae'n actifadu rhif allbwn (1<<X). Defnyddir gweddill mewnbynnau'r sglodyn i raddfa'r dyluniad cyfan. Mae angen y sglodyn hwn nid yn unig i leihau nifer y pinnau sydd wedi'u meddiannu gan y microreolydd, ond hefyd er diogelwch - er mwyn peidio â throi mwy o LEDs nag y bo modd yn ddamweiniol a pheidio â llosgi'r MK. Mae'r sglodyn yn costio ceiniog a dylid ei gadw yn eich cabinet meddyginiaeth cartref bob amser.

Bydd ein CD74HC238 yn gyfrifol am gyflenwi foltedd i anod y LED a ddymunir. Mewn amlblecs llawn, byddai'n cyflenwi foltedd i'r golofn trwy P-MOSFET, ond yn y demo hwn mae'n bosibl yn uniongyrchol, oherwydd mae'n tynnu 20 mA, yn ôl graddfeydd uchaf absoliwt yn y daflen ddata. Oddiwrth taflen wybodaeth CD74HC238 mae angen pinouts a'r daflen dwyllo hon:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
H = lefel foltedd uchel, L = lefel foltedd isel, X – dim ots

Rydym yn cysylltu E2 ac E1 i ddaear, E3, A0, A1 ac A3 i binnau PD5, PC3, PC4 a PC5 o STM8. Gan fod y tabl uchod yn cynnwys lefelau isel ac uchel, rydym yn ffurfweddu'r pinnau hyn fel pinnau gwthio-tynnu.

PWM

Mae PWM ar yr ail amserydd wedi'i ffurfweddu yn yr un modd ag yn y stori flaenorol, gyda dau wahaniaeth:

Yn gyntaf, mae angen inni alluogi'r ymyriad ymlaen Digwyddiad Diweddaru (UEV) a fydd yn galw swyddogaeth sy'n toglo'r LED gweithredol. Gwneir hyn trwy newid y darn Galluogi Ymyriad Diweddaru mewn cofrestr gydag enw dweud

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
Ymyrraeth galluogi cofrestr

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

Mae'r ail wahaniaeth yn gysylltiedig â ffenomen amlblecsio, megis ysbrydion – llewyrch parasitig deuodau. Yn ein hachos ni, gall ymddangos oherwydd bod yr amserydd, ar ôl achosi ymyrraeth ar yr UEV, yn parhau i dicio, ac nid oes gan y triniwr ymyriad amser i newid y LED cyn i'r amserydd ddechrau ysgrifennu rhywbeth i'r pinnau. I frwydro yn erbyn hyn, bydd yn rhaid i chi wrthdroi'r rhesymeg (0 = disgleirdeb mwyaf, 255 = dim byd wedi'i oleuo) ac osgoi gwerthoedd cylch dyletswydd eithafol. Y rhai. sicrhau ar ôl UEV bod y LEDs yn mynd allan yn gyfan gwbl am un cylch PWM.

Newid polaredd:

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

Ceisiwch osgoi gosod r, g a b i 255 a chofiwch eu gwrthdroi wrth eu defnyddio.

Yn torri ar draws

Hanfod ymyriad yw bod y sglodyn yn rhoi'r gorau i weithredu'r brif raglen o dan rai amgylchiadau ac yn galw rhywfaint o swyddogaeth allanol. Mae ymyriadau yn digwydd oherwydd dylanwadau allanol neu fewnol, gan gynnwys yr amserydd.

Pan wnaethom greu prosiect yn ST Visual Develop am y tro cyntaf, yn ogystal â main.c derbyniasom ffenestr gyda ffeil dirgel stm8_interrupt_vector.c, wedi'i gynnwys yn awtomatig yn y prosiect. Yn y ffeil hon, mae swyddogaeth yn cael ei neilltuo i bob ymyriad NonHandledInterrupt. Mae angen inni rwymo ein swyddogaeth i'r ymyriad a ddymunir.

Mae gan y daflen ddata dabl o fectorau ymyrraeth, lle rydyn ni'n dod o hyd i'r rhai rydyn ni eu hangen:

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8
13 TIM2 diweddariad/gorlif
14 TIM2 dal/cymharu

Mae angen i ni newid y LED yn UEV, felly mae angen torri ar draws #13.

Yn unol â hynny, yn gyntaf, yn y ffeil stm8_interrupt_vector.c newid enw rhagosodedig y swyddogaeth sy'n gyfrifol am ymyriad Rhif 13 (IRQ13) i'ch un chi:

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

Yn ail, bydd yn rhaid i ni greu ffeil main.h gyda'r cynnwys canlynol:

#ifndef __MAIN_H
#define __MAIN_H

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

Ac yn olaf, ysgrifennwch y swyddogaeth hon yn eich 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;
}

Y cyfan sydd ar ôl yw galluogi ymyriadau. Gwneir hyn gan ddefnyddio'r gorchymyn cydosodwr rim - bydd yn rhaid i chi chwilio amdano i mewn Llawlyfr Rhaglennu:

//enable interrupts
_asm("rim");

Gorchymyn cydosodwr arall yw sim – yn diffodd ymyriadau. Rhaid eu diffodd tra bod gwerthoedd newydd yn cael eu hysgrifennu i'r “cof fideo”, fel nad yw ymyriad a achosir ar yr eiliad anghywir yn difetha'r arae.

Pob cod - ar GitHub.

Darllenwch daflenni data 2: SPI ar STM32; PWM, amseryddion ac ymyriadau ar STM8

Os bydd rhywun o leiaf yn gweld yr erthygl hon yn ddefnyddiol, yna ni wnes i ei hysgrifennu yn ofer. Byddaf yn falch o dderbyn sylwadau a sylwadau, byddaf yn ceisio ateb popeth.

Ffynhonnell: hab.com

Ychwanegu sylw