Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

В први део Покушао сам да кажем хоби инжењерима електронике који су одрасли из Ардуино панталона како и зашто треба да читају таблице са подацима и другу документацију за микроконтролере. Испоставило се да је текст велики, па сам обећао да ћу показати практичне примере у посебном чланку. Па, он је себе назвао млечном печурком...

Данас ћу вам показати како да користите датасхеетове за решавање прилично једноставних, али неопходних за многе пројекте, задатака на СТМ32 (Блуе Пилл) и СТМ8 контролерима. Сви демо пројекти су посвећени мојим омиљеним ЛЕД диодама, палићемо их у великим количинама, за шта ћемо морати да користимо разне занимљиве периферије.

Текст се опет показао огромним, па ради погодности правим садржај:

СТМ32 Блуе Пилл: 16 ЛЕД диода са ДМ634 драјвером
СТМ8: Постављање шест ПВМ пинова
СТМ8: 8 РГБ ЛЕД на три пина, прекида

Дисцлаимер: Нисам инжењер, не претендујем да имам дубоко знање у електроници, чланак је намењен аматерима попут мене. У ствари, пре две године сам себе сматрао циљном публиком. Да ми је неко тада рекао да таблице података на непознатом чипу нису страшне за читање, не бих трошио много времена тражећи неке делове кода на интернету и измишљајући штаке са маказама и лепљивом траком.

Фокус овог чланка је на листовима са подацима, а не на пројектима, тако да код можда није баш уредан и често скучен. Сами пројекти су веома једноставни, иако су погодни за прво упознавање са новим чипом.

Надам се да ће мој чланак помоћи некоме у сличној фази урањања у хоби.

СТМКСНУМКС

16 ЛЕД диода са ДМ634 и СПИ

Мали пројекат који користи Блуе Пилл (СТМ32Ф103Ц8Т6) и ДМ634 ЛЕД драјвер. Користећи табеле са подацима, открићемо драјвер, СТМ ИО портове и конфигурисати СПИ.

ДМКСНУМКС

Тајвански чип са 16 16-битних ПВМ излаза, може се повезати у ланце. 12-битни модел ниске класе познат је из домаћег пројекта Лигхтпацк. Својевремено, бирајући између ДМ63к и добро познатог ТЛЦ5940, изабрао сам ДМ из неколико разлога: 1) ТЛЦ на Алиекпресс-у је дефинитивно лажан, али овај није; 2) ДМ има аутономни ПВМ са сопственим генератором фреквенције; 3) могао би се купити јефтино у Москви, уместо да чека пакет од Алија. И, наравно, било је занимљиво научити како да сами контролишете чип, уместо да користите готову библиотеку. Чипови су сада углавном представљени у пакету ССОП24, лако се лемљују на адаптер.

Пошто је произвођач Тајвански, лист са подацима чип је написан на кинеском енглеском, што значи да ће бити забавно. Прво погледамо пиноут (Пин Цоннецтион) да разумете на коју ногу да повежете са чиме, и опис иглица (Пин Десцриптион). 16 пинова:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Извори истосмерне струје (отворени одвод)

Лавабо / Излаз отвореног одвода – одвод; извор прилива струје; излаз, у активном стању, повезан са земљом - ЛЕД диоде су повезане са драјвером помоћу катода. Електрично, ово, наравно, није „отворени одвод“ (отворени одвод), али у таблицама података ова ознака за пинове у режиму одвода се често налази.

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Спољни отпорници између РЕКСТ и ГНД за подешавање вредности излазне струје

Референтни отпорник је инсталиран између РЕКСТ пина и масе, који контролише унутрашњи отпор излаза, погледајте графикон на страни 9 у техничком листу. У ДМ634, овај отпор се такође може контролисати софтвером, подешавајући укупну осветљеност (глобална светлост); Нећу улазити у детаље у овом чланку, само ћу овде ставити отпорник од 2.2 - 3 кОхм.

Да бисмо разумели како да контролишемо чип, погледајмо опис интерфејса уређаја:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Да, ево га, кинески енглески у свој својој слави. Превођење овога је проблематично, можете га разумети ако желите, али постоји још један начин - погледајте како је веза са функционално сличним ТЛЦ5940 описана у таблици са подацима:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
... За унос података у уређај потребна су само три пина. Растућа ивица СЦЛК сигнала помера податке са СИН пина у интерни регистар. Након што су сви подаци учитани, кратки високи КСЛАТ сигнал затвара секвенцијално пренете податке у интерне регистре. Интерни регистри су капије које покреће ниво КСЛАТ сигнала. Сви подаци се прво преносе најважнији бит.

Латцх – засун/засун/брава.
Растућа Ивица – предња ивица пулса
Прво МСБ – најзначајнији (крајњи леви) бит унапред.
на податке сата – пренос података секвенцијално (бит по бит).

Ворд реза се често налази у документацији за чипове и преводи се на разне начине, па ћу, ради разумевања, дозволити себи

мали образовни програмЛЕД драјвер је у суштини регистар померања. "Смена" (схифт) у имену - побитно кретање података унутар уређаја: сваки нови бит гурнут унутра гура цео ланац напред испред себе. Пошто нико не жели да посматра хаотично трептање ЛЕД диода током смене, процес се одвија у бафер регистрима одвојеним од радних регистара помоћу дампера (реза) је нека врста чекаонице у којој су битови распоређени у жељеном редоследу. Када је све спремно, затварач се отвара и битови иду на посао, замењујући претходну серију. Реч реза у документацији за микро кола скоро увек се подразумева такав пригушивач, без обзира у којим комбинацијама се користи.

Дакле, пренос података на ДМ634 се врши на следећи начин: подесите ДАИ улаз на вредност најзначајнијег бита далеког ЛЕД-а, повуците ДЦК горе-доле; поставите ДАИ улаз на вредност следећег бита, повуците ДЦК; и тако даље док се сви битови не пренесу (цлоцкед ин), након чега повлачимо ЛАТ. Ово се може урадити ручно (бит-банг), али је боље користити СПИ интерфејс посебно скројен за ово, пошто је на нашем СТМ32 представљен у два примерка.

Блуе Пилл СТМ32Ф103

Уводно: СТМ32 контролери су много сложенији од Атмега328 него што би могли изгледати застрашујуће. Штавише, из разлога уштеде енергије, скоро све периферије се искључују у старту, а фреквенција такта је 8 МХз од унутрашњег извора. На срећу, СТМ програмери су написали код који доводи чип до „израчунатих“ 72 МХз, а аутори свих ИДЕ које знам укључили су га у процедуру иницијализације, тако да не морамо да тактујемо (али можете ако заиста желите). Али мораћете да укључите периферне уређаје.

Документација: Блуе Пилл је опремљен популарним СТМ32Ф103Ц8Т6 чипом, за њега постоје два корисна документа:

У табели са подацима можда ће нас занимати:

  • Пиноутс – пиноутс чип – у случају да одлучимо да сами направимо плоче;
  • Меморијска карта – меморијска мапа за одређени чип. У Референтном приручнику постоји мапа за цео ред, а помињу се регистри које наш нема.
  • Табела са дефиницијама пинова – листа главних и алтернативних функција пинова; за „плаву пилулу“ можете пронаћи погодније слике на Интернету са листом иглица и њихових функција. Стога, одмах тражимо пиноут Блуе Пилл и држимо ову слику при руци:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
НБ: дошло је до грешке на слици са интернета, што је забележено у коментарима, хвала на томе. Слика је замењена, али ово је лекција - боље је проверити информације не из таблица података.

Уклонимо лист са подацима, отворимо Референтни приручник и од сада користимо само њега.
Процедура: бавимо се стандардним улазом/излазом, конфигуришемо СПИ, укључујемо потребне периферије.

Улаз излаз

На Атмега328, И/О је имплементиран изузетно једноставно, због чега обиље СТМ32 опција може бити збуњујуће. Сада су нам потребни само закључци, али чак и ови имају четири опције:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
отворени одвод, пусх-пулл, алтернативни пусх-пулл, алтернативни отворени одвод

"Повуци-гурај" (пусх-пулл) је уобичајени излаз из Ардуино-а, пин може имати вредност ХИГХ или ЛОВ. Али са „отвореним одводом“ постоје тешкоће, иако је у ствари овде све једноставно:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Конфигурација излаза / када је порт додељен излазу: / излазни бафер је омогућен: / – режим отвореног одвода: „0” у излазном регистру омогућава Н-МОС, „1” у излазном регистру оставља порт у Хи-З режиму ( П-МОС није активиран ) / – пусх-пулл режим: “0” у излазном регистру активира Н-МОС, “1” у излазном регистру активира П-МОС.

Сва разлика између отвореног одвода (отворени одвод) од „пусх-пулл“ (пусх-пулл) је да у првом пину не може да прихвати стање ХИГХ: када уписује један у излазни регистар, прелази у режим високог отпора (висока импеданса, Хи-З). Када уписујете нулу, пин се понаша исто у оба режима, и логички и електрични.

У нормалном излазном режиму, пин једноставно емитује садржај излазног регистра. У "алтернативи" га контролишу одговарајући периферни уређаји (видети 9.1.4):

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Ако је бит порта конфигурисан као пин алтернативне функције, пин регистар је онемогућен и пин је повезан са периферним пином.

Алтернативне функције сваког пина описане су у Дефиниције пин-а Лист са подацима се налази на преузетој слици. На питање шта учинити ако пин има неколико алтернативних функција, одговор је дат фуснотом у таблици са подацима:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Ако више периферних уређаја користи исти пин, да би се избегао конфликт између алтернативних функција, требало би да се користи само једна периферија истовремено, која се укључује помоћу бита за омогућавање периферног сата (у одговарајућем РЦЦ регистру).

Коначно, пинови у излазном режиму такође имају брзину такта. Ово је још једна функција за уштеду енергије; у нашем случају, само је поставимо на максимум и заборавимо.

Дакле: користимо СПИ, што значи да два пина (са подацима и са тактним сигналом) треба да буду „алтернативна пусх-пулл функција“, а још један (ЛАТ) треба да буде „обичан пусх-пулл“. Али пре него што их доделимо, хајде да се позабавимо СПИ.

СПИ

Још један мали образовни програм

СПИ или Сериал Перипхерал Интерфаце (серијски периферни интерфејс) је једноставан и веома ефикасан интерфејс за повезивање МК-а са другим МК-овима и спољним светом уопште. Принцип његовог рада је већ описан горе, где се говори о кинеском ЛЕД драјверу (у референтном приручнику, погледајте одељак 25). СПИ може да ради у мастер („мастер”) и славе („славе”) режиму. СПИ има четири основна канала, од којих се сви не могу користити:

  • МОСИ, главни излаз / славе улаз: овај пин преноси податке у мастер моду и прима податке у славе режиму;
  • МИСО, главни улаз / славе излаз: напротив, прима у мастер, а преноси у славе;
  • СЦК, Сериал Цлоцк: поставља фреквенцију преноса података у главном или прима сигнал такта у славе-у. У суштини ударање ритмова;
  • СС, Славе Селецт: уз помоћ овог канала, роб зна да се од њега нешто тражи. На СТМ32 се зове НСС, где је Н = негативно, тј. контролер постаје славе ако постоји уземљење у овом каналу. Добро се комбинује са режимом Опен Драин Оутпут, али то је друга прича.

Као и све остало, СПИ на СТМ32 је богат функционалношћу, што га чини помало тешким за разумевање. На пример, може да ради не само са СПИ, већ и са И2С интерфејсом, а у документацији су њихови описи помешани, потребно је благовремено одрезати вишак. Наш задатак је изузетно једноставан: само треба да пошаљемо податке користећи само МОСИ и СЦК. Идемо на одељак 25.3.4 (полудуплекс комуникација, полудуплекс комуникација), где налазимо 1 сат и 1 једносмерна жица за пренос података (1 такт сигнал и 1 једносмерни ток података):

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
У овом режиму, апликација користи СПИ у режиму само за пренос или само за пријем. / Режим само за пренос је сличан дуплекс режиму: подаци се преносе на пин за пренос (МОСИ у мастер режиму или МИСО у славе режиму), а пријемни пин (МИСО или МОСИ респективно) се може користити као обичан И/О пин . У овом случају, апликација треба само да игнорише Рк бафер (ако је прочитан, тамо неће бити пренетих података).

Одлично, МИСО пин је слободан, хајде да повежемо ЛАТ сигнал на њега. Погледајмо Славе Селецт, који се на СТМ32 може контролисати програмски, што је изузетно згодно. Прочитали смо истоимени пасус у одељку 25.3.1 Општи опис СПИ:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Софтверска контрола НСС (ССМ = 1) / Информација о избору славе налази се у ССИ биту регистра СПИ_ЦР1. Екстерни НСС пин остаје слободан за друге потребе апликације.

Време је за упис у регистре. Одлучио сам да користим СПИ2, потражим његову основну адресу у таблици са подацима - у одељку 3.3 Мапа меморије:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Па, да почнемо:

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

Отворите одељак 25.3.3 са саморазумљивим насловом „Конфигурисање СПИ у главном режиму“:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

1. Подесите серијску фреквенцију такта са битовима БР[2:0] у регистру СПИ_ЦР1.

Регистри се прикупљају у истоименом делу референтног приручника. Промена адресе (Одступање адресе) за ЦР1 – 0к00, подразумевано се бришу сви битови (Ресетуј вредност 0к0000):

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

БР битови постављају делилац такта контролера, одређујући тако фреквенцију на којој ће СПИ радити. Наша фреквенција СТМ32 ће бити 72 МХз, ЛЕД драјвер, према његовом датасхеет-у, ради са фреквенцијом до 25 МХз, тако да треба да поделимо са четири (БР[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. Подесите ЦПОЛ и ЦПХА битове да дефинишете однос између преноса података и времена серијског сата (погледајте дијаграм на страни 240)

Пошто овде читамо таблицу са подацима и не гледамо шеме, хајде да ближе погледамо текстуални опис битова ЦПОЛ и ЦПХА на страници 704 (СПИ општи опис):

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Фаза и поларитет сата
Користећи ЦПОЛ и ЦПХА бите регистра СПИ_ЦР1, можете програмски изабрати четири временска односа. Бит ЦПОЛ (поларитет сата) контролише стање сигнала такта када се не преносе подаци. Овај бит контролише главни и славе мод. Ако је ЦПОЛ ресетован, пин СЦК је низак у режиму мировања. Ако је ЦПОЛ бит постављен, СЦК пин је висок током режима мировања.
Када је ЦПХА (фаза такта) бит постављен, строб за замку високог бита је друга ивица СЦК сигнала (пада ако је ЦПОЛ чист, расте ако је ЦПОЛ постављен). Подаци се хватају другом променом сигнала сата. Ако је ЦПХА бит чист, строб за замку високог бита је растућа ивица СЦК сигнала (падајућа ивица ако је ЦПОЛ подешен, растућа ивица ако је ЦПОЛ обрисан). Подаци се снимају при првој промени сигнала сата.

Пошто смо апсорбовали ово знање, долазимо до закључка да оба бита морају остати нула, јер Желимо да СЦК сигнал остане низак када се не користи, а подаци да се преносе на растућој ивици импулса (погледајте Сл. Растућа Ивица у таблици са подацима ДМ634).

Иначе, овде смо први пут наишли на карактеристику речника у СТ таблицама података: у њима је написана фраза „ресетујте бит на нулу“ да се мало ресетујемИ не да се мало разбистри, као, на пример, Атмега.

3. Подесите ДФФ бит да одредите да ли је блок података 8-битни или 16-битни формат

Посебно сам узео 16-битни ДМ634 да се не бих мучио са преношењем 12-битних ПВМ података, као што је ДМ633. Има смисла поставити ДФФ на један:

#define DFF         0x0800

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

4. Конфигуришите ЛСБФИРСТ бит у регистру СПИ_ЦР1 да бисте одредили формат блока

ЛСБФИРСТ, као што му име каже, конфигурише пренос са најмањим битом прво. Али ДМ634 жели да прими податке почевши од најзначајнијег бита. Стога га остављамо ресетован.

5. У хардверском режиму, ако је потребан унос са НСС пина, примените високи сигнал на НСС пин током читаве секвенце преноса бајтова. У софтверском режиму НСС, подесите ССМ и ССИ битове у регистру СПИ_ЦР1. Ако се НСС пин треба користити као излаз, потребно је подесити само ССОЕ бит.

Инсталирајте ССМ и ССИ да заборавите на НСС хардверски режим:

#define SSI         0x0100
#define SSM         0x0200

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

6. МСТР и СПЕ битови морају бити подешени (они остају подешени само ако је НСС сигнал висок)

У ствари, са овим битовима означавамо наш СПИ као мастер и укључујемо га:

#define MSTR        0x0004
#define SPE         0x0040

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

СПИ је конфигурисан, хајде да одмах напишемо функције које шаљу бајтове драјверу. Наставите да читате 25.3.3 „Конфигурисање СПИ у главном режиму“:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Налог за пренос података
Пренос почиње када се бајт упише у Тк бафер.
Бајт података се учитава у регистар померања на паралелно режиму (са интерне магистрале) током преноса првог бита, након чега се преноси на редни МОСИ пин режим, први или последњи бит унапред у зависности од подешавања ЛСБФИРСТ бита у регистру ЦПИ_ЦР1. ТКСЕ заставица се поставља након преноса података из Тк бафера у регистар померања, а такође генерише прекид ако је постављен ТКСЕИЕ бит у регистру ЦПИ_ЦР1.

Истакнуо сам неколико речи у преводу да бих скренуо пажњу на једну особину имплементације СПИ у СТМ контролерима. На Атмеги ТКСЕ застава (Тк Емпти, Тк је празан и спреман за пријем података) се поставља тек након што је цео бајт послат напоље. И овде се ова заставица поставља након што је бајт убачен у интерни регистар померања. Пошто се тамо гура са свим битовима у исто време (паралелно), а затим се подаци преносе секвенцијално, ТКСЕ се поставља пре него што се бајт у потпуности пошаље. Ово је важно јер у случају нашег ЛЕД драјвера, потребно је да повучемо ЛАТ пин након слања све података, тј. Сама ТКСЕ застава нам неће бити довољна.

То значи да нам је потребна још једна застава. Погледајмо 25.3.7 - „Заставице статуса“:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
<…>
Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
БУСИ флаг
БСИ заставица се поставља и брише хардвером (писање у њу нема ефекта). Ознака БСИ означава стање СПИ комуникационог слоја.
Ресетује:
када је пренос завршен (осим у главном режиму ако је пренос континуиран)
када је СПИ онемогућен
када дође до грешке главног режима (МОДФ=1)
Ако пренос није континуиран, БСИ заставица се брише између сваког преноса података

Добро, ово ће добро доћи. Хајде да сазнамо где се налази Тк бафер. Да бисте то урадили, прочитајте „СПИ регистар података“:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Битови 15:0 ДР[15:0] Регистар података
Примљени подаци или подаци за пренос.
Регистар података је подељен на два бафера - један за писање (бафер за пренос) и један за читање (бафер за пријем). Уписивање у регистар података уписује се у Тк бафер, а читање из регистра података ће вратити вредност садржану у Рк баферу.

Па, и статусни регистар, где се налазе ТКСЕ и БСИ заставице:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Пишемо:

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

Па, пошто треба да пренесемо 16 пута два бајта, према броју излаза ЛЕД драјвера, нешто овако:

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

Али још увек не знамо како да извучемо ЛАТ пин, па ћемо се вратити на И/О.

Додељивање пинова

У СТМ32Ф1, регистри одговорни за стање пинова су прилично необични. Јасно је да их има више од Атмеге, али се разликују и од осталих СТМ чипова. Одељак 9.1 Општи опис ГПИО:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Сваки од И/О портова опште намене (ГПИО) има два 32-битна регистра конфигурације (ГПИОк_ЦРЛ и ГПИОк_ЦРХ), два 32-битна регистра података (ГПИОк_ИДР и ГПИОк_ОДР), 32-битни регистар за постављање/ресетовање (ГПИОк_БСРР), 16-битни регистар за ресетовање (ГПИОк_БРР) и 32- регистар за блокирање битова (ГПИОк_ЛЦКР).

Прва два регистра су необична, а такође и прилично незгодна, јер су пинови са 16 портова разбацани по њима у формату „четири бита по брату“. Оне. пинови од нула до седам су у ЦРЛ, а остали су у ЦРХ. У исто време, преостали регистри успешно садрже битове свих пинова порта - често остајући половина „резервисана“.

Ради једноставности, почнимо од краја листе.

Не треба нам регистар за блокирање.

Регистри за постављање и ресетовање су прилично смешни по томе што се делимично дуплирају: све можете да упишете само у БСРР, где ће виших 16 битова ресетовати пин на нулу, а нижи ће бити постављени на 1, или можете такође користите БРР, чијих доњих 16 битова само ресетује пин. Свиђа ми се друга опција. Ови регистри су важни јер обезбеђују атомски приступ пиновима:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Атомиц Сет или Ресет
Нема потребе да се онемогућују прекиди када се програмира ГПИОк_ОДР на нивоу бита: један или више битова се могу променити са једном операцијом атомског писања АПБ2. Ово се постиже уписивањем "1" у регистар за постављање/ресетовање (ГПИОк_БСРР или, само за ресетовање, ГПИОк_БРР) бита који треба да се промени. Остали битови ће остати непромењени.

Регистри података имају сасвим разумљива имена - ИДР = Улазни Регистар праваца, улазни регистар; ОДР = Излаз Регистар праваца, излазни регистар. Неће нам требати у тренутном пројекту.

И на крају, контролни регистри. Пошто нас занимају други СПИ пинови, односно ПБ13, ПБ14 и ПБ15, одмах гледамо ЦРХ:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

И видимо да ћемо морати нешто написати у битовима од 20 до 31.

Изнад смо већ схватили шта желимо од пинова, па ћу овде без снимка екрана, само ћу рећи да МОДЕ одређује правац (улаз ако су оба бита постављена на 0) и брзину пинова (потребно нам је 50МХз, тј. оба пина на “1”), а ЦНФ поставља режим: регуларни “пусх-пулл” – 00, “алтернативе” – 10. Подразумевано, као што видимо горе, сви пинови имају трећи бит одоздо (ЦНФ0), поставља их у режим плутајући улаз.

Пошто планирам да урадим нешто друго са овим чипом, ради једноставности дефинисао сам све могуће МОДЕ и ЦНФ вредности и за доњи и за горњи контролни регистр.

Некако овако

#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

Наши пинови се налазе на порту Б (основна адреса – 0к40010Ц00), код:

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

И, сходно томе, можете написати дефиниције за ЛАТ, које ће се трзати регистрима БРР и БСРР:

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

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

(ЛАТ_ниско само по инерцији, увек је тако било, нека остане)

Сада је све супер, али не ради. Пошто је ово СТМ32, они штеде електричну енергију, што значи да морате омогућити тактирање потребних периферних уређаја.

Укључите сат

Сат, такође познат као Цлоцк, одговоран је за сат. И већ смо могли приметити скраћеницу РЦЦ. Тражимо га у документацији: ово је Ресетовање и контрола сата.

Као што је горе речено, срећом, најтежи део теме цлоцкинга урадили су за нас људи из СТМ-а, на чему им се пуно захваљујемо (још једном даћу линк до Сајт Ди Халта, да би било јасно колико је то збуњујуће). Потребни су нам само регистри одговорни за омогућавање периферног такта (регистри за омогућавање периферног сата). Прво, пронађимо основну адресу РЦЦ-а, она је на самом почетку „Мапе меморије“:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

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

И онда или кликните на линк где покушавате да пронађете нешто у табли, или, много боље, прођите кроз описе регистара за омогућавање из одељака о омогућити регистре. Где ћемо пронаћи РЦЦ_АПБ1ЕНР и РЦЦ_АПБ2ЕНР:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

И они, сходно томе, садрже битове који укључују тактирање СПИ2, ИОПБ (И/О порт Б) и алтернативне функције (АФИО).

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

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

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

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

Коначни код се може наћи овде.

Ако имате прилику и жељу да тестирате, онда повежите ДМ634 овако: ДАИ на ПБ15, ДЦК на ПБ13, ЛАТ на ПБ14. Напајамо драјвер од 5 волти, не заборавите да повежете уземљење.

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

СТМ8 ПВМ

ПВМ на СТМ8

Када сам тек планирао овај чланак, одлучио сам, као пример, да покушам да савладам неке функционалности непознатог чипа користећи само датасхеет, како не бих завршио са обућаром без чизама. СТМ8 је био идеалан за ову улогу: прво, имао сам неколико кинеских плоча са СТМ8С103, а друго, није баш популаран, па стога искушење да се прочита и нађе решење на Интернету почива на недостатку самих ових решења.

Чип такође има лист са подацима и референтни приручник РМ0016, у првом се налазе пиноут и регистарске адресе, у другом - све остало. СТМ8 је програмиран у Ц у ужасном ИДЕ-у СТ Висуал Девелоп.

Сат и И/О

Подразумевано, СТМ8 ради на фреквенцији од 2 МХз, ово се мора одмах исправити.

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
ХСИ (Интерни Хигх Спеед) сат
ХСИ сигнал такта је изведен из интерног РЦ осцилатора од 16 МХз са програмабилним разделником (1 до 8). Поставља се у регистру разделника сата (ЦЛК_ЦКДИВР).
Напомена: на почетку, ХСИ РЦ осцилатор са дјелитељем од 8 је одабран као водећи извор сигнала такта.

Проналазимо адресу регистра у таблици са подацима, опис у рефман-у и видимо да регистар треба да се обрише:

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

Пошто ћемо покренути ПВМ и повезати ЛЕД диоде, погледајмо пиноут:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Чип је мали, многе функције су суспендоване на истим пиновима. Оно што је у угластим заградама је „алтернативна функционалност“, она се мења помоћу „бајтова опција“ (бајтова опција) – нешто попут Атмега осигурача. Њихове вредности можете променити програмски, али то није неопходно, јер Нова функционалност се активира тек након поновног покретања. Лакше је користити СТ Висуал Программер (преузет уз Висуал Девелоп), који може да промени ове бајтове. Пиноут показује да су пинови ЦХ1 и ЦХ2 првог тајмера сакривени у угластим заградама; потребно је подесити АФР1 и АФР0 битове у СТВП, а други ће такође пренети ЦХ1 излаз другог тајмера са ПД4 на ПЦ5.

Тако ће 6 пинова контролисати ЛЕД диоде: ПЦ6, ПЦ7 и ПЦ3 за први тајмер, ПЦ5, ПД3 и ПА3 за други.

Постављање самих И/О пинова на СТМ8 је једноставније и логичније него на СТМ32:

  • познато из Атмега ДДР регистра праваца података (Регистар праваца података): 1 = излаз;
  • први контролни регистар ЦР1, на излазу, поставља пусх-пулл мод (1) или отворени одвод (0); пошто спајам ЛЕД диоде на чип са катодама, овде остављам нуле;
  • други контролни регистар ЦР2, на излазу, поставља брзину такта: 1 = 10 МХз

#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

ПВМ подешавање

Прво, хајде да дефинишемо појмове:

  • ПВМ фреквенција – учесталост којом тајмер откуцава;
  • Аутоматско поновно учитавање, АР – вредност која се може аутоматски учитати до које ће тајмер рачунати (период импулса);
  • Догађај ажурирања, УЕВ – догађај који се јавља када је тајмер одбројао до АР;
  • ПВМ радни циклус – ПВМ радни циклус, који се често назива „фактор рада“;
  • Снимите/упоредите вредност – вредност за снимање/поређење, до које је тајмер рачунао урадиће нешто (у случају ПВМ, он инвертује излазни сигнал);
  • Прелоад Валуе – унапред учитана вредност. Упоредите вредност не може да се промени док тајмер откуцава, иначе ће се ПВМ циклус прекинути. Стога се нове пренете вредности стављају у бафер и извлаче када тајмер достигне крај свог одбројавања и ресетује се;
  • Поравнано по ивицама и Режими поравнати по средини – поравнање дуж границе и у центру, исто као и Атмелово Брзи ПВМ и ПВМ са исправном фазом.
  • ОЦиРЕФ, Референтни сигнал за поређење излаза – референтни излазни сигнал, у ствари, оно што се појављује на одговарајућем пину у ПВМ режиму.

Као што је већ јасно из пиноута, два тајмера имају ПВМ могућности – први и други. Оба су 16-битна, прва има много додатних функција (нарочито може да броји и нагоре и надоле). И једно и друго треба да радимо подједнако, па сам одлучио да почнем са очигледно лошијом другом, да случајно не користим нешто чега нема. Неки проблем је што се опис ПВМ функционалности свих тајмера у референтном приручнику налази у поглављу о првом тајмеру (17.5.7 ПВМ режим), тако да морате стално да скачете напред-назад кроз документ.

ПВМ на СТМ8 има важну предност у односу на ПВМ на Атмеги:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Боундари Алигнед ПВМ
Конфигурација налога од дна до врха
Бројање одоздо према горе је активно ако је ДИР бит у регистру ТИМ_ЦР1 обрисан
Пример
Пример користи први ПВМ режим. ПВМ референтни сигнал ОЦиРЕФ се држи на високом нивоу све док ТИМ1_ЦНТ < ТИМ1_ЦЦРи. Иначе је потребан низак ниво. Ако је вредност поређења у регистру ТИМ1_ЦЦРи већа од вредности аутоматског учитавања (ТИМ1_АРР регистар), ОЦиРЕФ сигнал се држи на 1. Ако је вредност поређења 0, ОЦиРЕФ се држи на нули....

СТМ8 тајмер током ажурирање догађаја прво проверава упореди вредност, и тек тада производи референтни сигнал. Атмега-ин тајмер прво зезне, а затим упоређује, што резултира compare value == 0 излаз је игла, са којом се мора некако позабавити (на пример, програмским инвертовањем логике).

Дакле, шта желимо да урадимо: 8-битни ПВМ (AR == 255), рачунајући одоздо према горе, поравнање дуж границе. Пошто су сијалице повезане са чипом катодама, ПВМ би требало да даје 0 (ЛЕД укључен) док упореди вредност и 1 после.

О некима смо већ читали ПВМ режим, тако да проналазимо потребан регистар другог тајмера претрагом у референтном приручнику за ову фразу (18.6.8 - ТИМк_ЦЦМР1):

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
110: Први ПВМ режим – када се броји одоздо према горе, први канал је активан док је ТИМк_ЦНТ < ТИМк_ЦЦР1. У супротном, први канал је неактиван. [даље у документу постоји погрешан цопи-пасте са тајмера 1] 111: Други ПВМ режим – када се броји одоздо према горе, први канал је неактиван док је ТИМк_ЦНТ < ТИМк_ЦЦР1. У супротном, први канал је активан.

Пошто су ЛЕД диоде повезане са МК катодама, други режим нам одговара (и први, али то још не знамо).

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Бит 3 ОЦ1ПЕ: Омогући предоптерећење пина 1
0: Регистар унапред учитавања на ТИМк_ЦЦР1 је онемогућен. Можете писати на ТИМк_ЦЦР1 у било ком тренутку. Нова вредност делује одмах.
1: Регистар претходног учитавања на ТИМк_ЦЦР1 је омогућен. Операције читања/писања приступају регистру претходног учитавања. Претходно учитана вредност ТИМк_ЦЦР1 се учитава у регистар сенки током сваког догађаја ажурирања.
*Напомена: Да би ПВМ режим исправно функционисао, регистри претходног оптерећења морају бити омогућени. Ово није неопходно у режиму једног сигнала (ОПМ бит је постављен у ТИМк_ЦР1 регистру).

У реду, хајде да укључимо све што нам треба за три канала другог тајмера:

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

АР се састоји од два осмобитна регистра, све је једноставно:

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

TIM2_ARRH = 0;
TIM2_ARRL = 255;

Други тајмер може да броји само одоздо према горе, поравнање дуж границе, ништа не треба мењати. Поставимо дјелитељ фреквенције, на примјер, на 256. За други тајмер, раздјелник је постављен у ТИМ2_ПСЦР регистру и има степен два:

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

Остаје само да укључите закључке и сам други тајмер. Први проблем решавају регистри Сними/упореди омогућити: по њима су асиметрично распоређена два, три канала. Овде можемо сазнати и да је могуће променити поларитет сигнала, тј. у принципу, било је могуће користити ПВМ Моде 1. Пишемо:

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

И коначно, покрећемо тајмер у регистру ТИМк_ЦР1:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

Хајде да напишемо једноставан аналог АналогВрите(), који ће пренети стварне вредности у тајмер ради поређења. Регистри су именовани предвидљиво Регистри за снимање/упоређивање, постоје два од њих за сваки канал: 8 битова нижег реда у ТИМ2_ЦЦРкЛ и они високог реда у ТИМ2_ЦЦРкХ. Пошто смо креирали 8-битни ПВМ, довољно је написати само најмање битне битове:

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

Пажљиви читалац ће приметити да имамо мало неисправан ПВМ, који није у стању да произведе 100% попуњавања (на максималној вредности од 255, сигнал се инвертује за један циклус тајмера). За ЛЕД диоде ово није важно, а пажљив читалац већ може погодити како то поправити.

ПВМ на другом тајмеру ради, пређимо на први.

Први тајмер има потпуно исте битове у истим регистрима (само они битови који су остали „резервисани“ у другом тајмеру се активно користе у првом за све врсте напредних ствари). Стога је довољно пронаћи адресе истих регистара у датасхеет-у и копирати код. Па промените вредност разделника фреквенције, јер... први тајмер жели да прими не степен два, већ тачну 16-битну вредност у два регистра Пресцалер Хигх и низак. Радимо све и... први тајмер не ради. Шта је било?

Проблем се може решити само тако што ћемо прегледати цео одељак о контролним регистрима тајмера 1, где тражимо онај који други тајмер нема. Тамо ће да буде 17.7.30 Регистар прекида (ТИМ1_БКР), где се налази овај бит:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Омогућите главни излаз

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

То је сада све сигурно, шифра тамо.

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

СТМ8 Мултиплекс

Мултиплексирање на СТМ8

Трећи мини-пројекат је да повеже осам РГБ ЛЕД диода са другим тајмером у ПВМ режиму и учини их да показују различите боје. Заснован је на концепту ЛЕД мултиплексирања, а то је да ако укључите и искључите ЛЕД диоде врло, врло брзо, чиниће нам се да су стално укључене (упорност вида, инерција визуелне перцепције). Једном сам овако нешто на Ардуину.

Алгоритам рада изгледа овако:

  • спојио аноду прве РГБ ЛЕД диоде;
  • упалио га, шаљући потребне сигнале на катоде;
  • чекао до краја ПВМ циклуса;
  • спојио аноду другог РГБ ЛЕД-а;
  • запалио...

Па итд. Наравно, за леп рад потребно је да анода буде повезана и да се ЛЕД истовремено „упали“. Па, или скоро. У сваком случају, потребно је да напишемо код који ће емитовати вредности у три канала другог тајмера, променити их када се достигне УЕВ и истовремено променити тренутно активну РГБ ЛЕД.

Пошто је пребацивање ЛЕД-а аутоматско, потребно је да креирамо „видео меморију“ из које ће руковалац прекида примати податке. Ово је једноставан низ:

uint8_t colors[8][3];

Да бисте променили боју одређене ЛЕД диоде, биће довољно да у овај низ упишете потребне вредности. А варијабла ће бити одговорна за број активне ЛЕД диоде

uint8_t cnt;

Демук

За правилно мултиплексирање, потребан нам је, зачудо, ЦД74ХЦ238 демултиплексер. Демултиплексер - чип који имплементира оператор у хардверу <<. Кроз три улазна пина (битови 0, 1 и 2) уносимо му тробитни број Кс, а као одговор активира излазни број (1<<X). Преостали улази чипа се користе за скалирање целог дизајна. Овај чип нам је потребан не само да бисмо смањили број заузетих пинова микроконтролера, већ и ради сигурности - како не бисмо случајно укључили више ЛЕД диода него што је могуће и не спалили МК. Чип кошта пени и увек га треба држати у кућном ормарићу за лекове.

Наш ЦД74ХЦ238 ће бити одговоран за снабдевање напоном аноде жељене ЛЕД диоде. У пуноправном мултиплексу, он би довео напон на колону преко П-МОСФЕТ-а, али у овом демо-у то је могуће директно, јер повлачи 20 мА, према Апсолутни максимум Оцене у таблици са подацима. Од Датасхеет ЦД74ХЦ238 требају нам пиноут-и и ова варалица:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Х = ниво високог напона, Л = ниво ниског напона, Кс – није брига

Повезујемо Е2 и Е1 на масу, Е3, А0, А1 и А3 на пинове ПД5, ПЦ3, ПЦ4 и ПЦ5 на СТМ8. Пошто горња табела садржи и ниске и високе нивое, ми конфигуришемо ове пинове као пусх-пулл пинове.

ПВМ

ПВМ на другом тајмеру је конфигурисан на исти начин као у претходној причи, са две разлике:

Прво, морамо да укључимо прекид Ажурирај догађај (УЕВ) који ће позвати функцију која укључује активну ЛЕД диоду. Ово се ради променом бита Омогућавање прекида ажурирања у регистру са карактеристичним именом

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
Регистар за омогућавање прекида

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

Друга разлика је везана за феномен мултиплексирања, као нпр гхостинг – паразитски сјај диода. У нашем случају, то се може појавити због чињенице да тајмер, након што је изазвао прекид на УЕВ-у, наставља да откуцава, а руковалац прекида нема времена да пребаци ЛЕД пре него што тајмер почне нешто да пише на пинове. Да бисте се изборили са овим, мораћете да инвертујете логику (0 = максимална осветљеност, 255 = ништа не светли) и избегавате екстремне вредности радног циклуса. Оне. осигурајте да се након УЕВ-а ЛЕД диоде потпуно угасе за један ПВМ циклус.

Промена поларитета:

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

Избегавајте постављање р, г и б на 255 и не заборавите да их обрнете када их користите.

Прекида

Суштина прекида је да под одређеним околностима чип престаје да извршава главни програм и позива неку спољну функцију. До прекида долази услед спољашњих или унутрашњих утицаја, укључујући тајмер.

Када смо први пут креирали пројекат у СТ Висуал Девелоп, поред main.c добили смо прозор са мистериозном датотеком stm8_interrupt_vector.c, аутоматски укључен у пројекат. У овој датотеци, функција је додељена сваком прекиду NonHandledInterrupt. Морамо да повежемо нашу функцију са жељеним прекидом.

Таблица са подацима има табелу вектора прекида, где налазимо оне који су нам потребни:

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8
13 ТИМ2 ажурирање/преливање
14 ТИМ2 снимање/упоређивање

Морамо да променимо ЛЕД на УЕВ, тако да нам је потребан прекид #13.

Сходно томе, прво, у фајлу stm8_interrupt_vector.c промените подразумевано име функције одговорне за прекид бр. 13 (ИРК13) у своје:

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

Друго, мораћемо да креирамо датотеку main.h са следећим садржајем:

#ifndef __MAIN_H
#define __MAIN_H

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

И на крају, упишите ову функцију у свој 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;
}

Остаје само да омогући прекиде. Ово се ради помоћу команде асемблера rim - мораћете да га потражите унутра Приручник за програмирање:

//enable interrupts
_asm("rim");

Друга команда асемблера је sim – искључује прекиде. Морају се искључити док се нове вредности уписују у „видео меморију“, тако да прекид изазван у погрешном тренутку не поквари низ.

Сав код - на ГитХуб-у.

Читање листова са подацима 2: СПИ на СТМ32; ПВМ, тајмери ​​и прекиди на СТМ8

Ако бар некоме овај чланак буде користан, онда га нисам узалуд написао. Биће ми драго да добијем коментаре и примедбе, покушаћу да одговорим на све.

Извор: ввв.хабр.цом

Додај коментар