STM32: alapvető időzítők. STM32F3

Valójában tehát azonnal térjünk át a programozásra. Vegyük bármelyik alapvető mikrokontroller időzítőt STM32F3, minimális beállítást fogunk végezni, és rendszeres időközönként megpróbálunk megszakításokat generálni. A legegyszerűbb példa 😉

Tehát attól Szabványos perifériakönyvtár szükségünk van néhány fájlra, amelyek interakciót valósítanak meg az időzítő regiszterekkel:

#include "stm32f30x_gpio.h" #include "stm32f30x_rcc.h" #include "stm32f30x_tim.h" #include "stm32f30x.h" /*******************************************************************/ TIM_TimeBaseInitTypeDef időzítő; /*******************************************************************/

A minimális időzítő inicializálása így néz ki. Egyébként ezzel egyidőben az egyik vezérlőlábat is beállítjuk, hogy kimeneti módban működjön. Csak a LED-et kell villogni 😉

/*******************************************************************/ void initAll() ( // Órazás – hol nélküle RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE) ; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE) ; // Ezen a tűn van egy kék LED (STM32F3Discovery) gpio.GPIO_Mode = GPIO_Mode_OUT; gpio.GPIO_Pin = GPIO_Pin_8; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Speed ​​= GPIO_Speed_50MHz; GPIO_Init(GPIOE, & gpio) ; // És itt van a régóta várt TIM2 időzítő beállítás TIM_TimeBaseStructInit(&timer) ; timer.TIM_Prescaler = 7200 ; timer.TIM_Period = 20000 ; TIM_TimeBaseInit(TIM2, & időzítő) ; /*******************************************************************/

Itt érdemes odafigyelni két olyan számra, amelyek a semmiből jönnek - 7200 és 20000 . Most találjuk ki, hogy mi az 😉 Az időzítőm frekvenciával van beállítva 72 MHz. Ennek a frekvenciának a felosztásához van szükség az előskálázóra, más néven előskálázóra) Így azt kapjuk 72 MHz / 7200 = 10 kHz. Tehát az időzítő egy pipája megfelel (1/10000) másodperc, ami egyenlő 100 mikroszekundum. Az időzítő periódusa az az érték, amelyig a számlálás után a program az időzítő túlcsordulása esetén a megszakításkezelőhöz repül. Esetünkben az időzítő ig ketyeg 20000 , ami megfelel (100 * 20000) µs vagy 2 másodperc. Vagyis a LED (amit a megszakításkezelőben kapcsolunk be és ki) egy ponttal villog 4 másodperc (2 másodperc bekapcsolva, 2 másodperc nem ég =)). Most már minden világos, folytatjuk...

Funkcióban fő() inicializálási függvénynek hívjuk, és engedélyezzük a megszakításokat és az időzítőt is. Egy ciklusban míg (1) még kevesebb kód - csak üres 😉

/*******************************************************************/ int main() ( __enable_irq() ; initAll() ; TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE) ; TIM_Cmd(TIM2, ENABLE) ; NVIC_EnableIRQ(TIM2_IRQn) ; while (1) ( ) /*******************************************************************/

Minden, csak írni kell néhány sort a megszakításkezelőnek, és a munka kész:

/*******************************************************************/ void TIM2_IRQHandler() ( TIM_ClearITPendingBit(TIM2, TIM_IT_Update) ; if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_8) == 1 ) ( GPIO_ResetBits(GPIOE))(GPIO_PendingBit) /*******************************************************************/

Miután bevillantotta a programot a vezérlőbe, villogó kék LED-et észlelünk, tehát a program megfelelően működik! Elvileg ennyi mára, kiderült egy ilyen rövid cikk)

Már megnéztük a SysTick időzítőt, amely a Cortex mag része. Ezzel azonban nem ér véget. Az stm32-ben sok időzítő található, és ezek különböznek egymástól. A céltól függően egy vagy másik időzítőt kell választania:

  • SysTick;
  • általános célú időzítők - TIM2, TIM3, TIM4, TIM15, TIM16, TIM17;
  • haladó időzítő (angol fejlett időzítő) - TIM1;
  • watchdog időzítő.

Utóbbiról csak annyit érdemes megemlíteni, hogy a rendszer lefagyásának szabályozására szolgál, és időnként vissza kell állítani az időzítőt. Ha az időzítőt nem állítják vissza egy bizonyos időintervallumon belül, a watchdog időzítő alaphelyzetbe állítja a rendszert (mikrovezérlőt).

Az időzítők különböző bitméretekben kaphatók: például a SysTick 24 bites, és az összes időzítő, ami nálunk van, 16 bites (vagyis 2 16 = 65535-ig számolhat), kivéve a WatchDogot. Ezen túlmenően minden időzítőnek van egy bizonyos számú csatornája, vagyis valójában kettő, három stb. számára is működhet. Ezek az időzítők működhetnek inkrementális kódolókkal, Hall-érzékelőkkel, PWM-et generálhatnak (impulzusszélesség-moduláció, eng. Pulse). Szélességmoduláció – amiről később fogunk beszélni) és így tovább. Ezenkívül megszakításokat generálhatnak, vagy kéréseket intézhetnek más modulokhoz (például a DMA-hoz - Közvetlen memóriahozzáférés) különféle események esetén:

  • túlcsordulás (angolul overflow);
  • jelrögzítés (eng. input capture);
  • összehasonlítás (angol output összehasonlítás);
  • event-trigger (angol eseményindító).

Ha az időzítő túlcsordulásával (pontosabban a "0" elérésével) minden világos számunkra - a SysTick-et vettük figyelembe -, akkor még nem ismerjük a többi lehetséges működési módot. Nézzük meg őket részletesebben.

Jelfelvétel

Ez a mód kiválóan alkalmas az impulzusok periódusának (vagy számának, mondjuk másodpercenkénti) mérésére. Amikor impulzus érkezik az MK kimenetre, az időzítő megszakítást generál, amelyből eltávolíthatjuk az aktuális számlálóértéket (a TIM_CCRx regiszterből, ahol x a csatorna száma), és elmenthetjük egy külső változóba. Ekkor jön a következő impulzus, és egy egyszerű kivonással megkapjuk a két impulzus közötti "időt". Megfoghatja az impulzus bevezető és lefutó élét, vagy akár mindkettőt egyszerre. Miért van erre szükség? Tegyük fel, hogy van egy mágnesed, amelyet egy keréken lévő korongra ragasztottál, és egy Hall-effektus érzékelőt egy kerékpárvillára. Ezután, ahogy megpörgeti a kereket, impulzust kap minden alkalommal, amikor a keréken lévő mágnes ugyanabban a síkban van, mint a Hall-érzékelő. Ismerve a távolságot, amelyet a mágnes repül fordulatonként, és az időt, kiszámíthatja a mozgás sebességét.

Létezik PWM rögzítési mód is, de ez inkább egy speciális módja az időzítő beállításának, mintsem külön üzemmód: az egyik csatorna a felfutó, a másik pedig a lefutó éleket fogja fel. Ezután az első csatorna érzékeli az időszakot, a második pedig a töltést.

Összehasonlítás mód

Ebben az üzemmódban a kiválasztott időzítő csatorna a megfelelő érintkezőhöz csatlakozik, és amint az időzítő elér egy bizonyos értéket, a kimeneti állapot az üzemmód beállításától függően változik (lehet "1" vagy "0", vagy a kimeneti állapot egyszerűen fordítva van).

PWM generálási mód

Ahogy a neve is sugallja, az időzítő ebben a módban impulzusszélesség-modulációt generál. Erről az üzemmódról, valamint arról, hogy hol lehet / kell használni, a következő leckében fogunk többet beszélni, miután megvizsgáltuk a jelrögzítést.

Fejlett időzítő segítségével háromfázisú PWM alakítható ki, ami nagyon hasznos a háromfázisú motor vezérléséhez.

Holtidő üzemmód

Néhány időzítő rendelkezik ezzel a funkcióval; késleltetéseket kell létrehozni a kimeneteken, amelyek például az átmenő áramok kizárásához szükségesek a teljesítménykapcsolók vezérlésekor.

A tanfolyamon csak a "jelrögzítést" és a "pwm generálást" fogjuk használni.

A rögzítési mód az időzítő egy speciális működési módja, melynek lényege a következő, hogy amikor a mikrokontroller egy bizonyos kimenetén a logikai szint megváltozik, a számláló regiszter értéke egy másik regiszterbe kerül, amit az ún. befogási nyilvántartás.

Mire való?
Ezzel az üzemmóddal megmérheti az impulzus időtartamát vagy a jel periódusát.

Az STM32 rögzítési mód néhány funkcióval rendelkezik:

  • az a lehetőség, hogy kiválassza, melyik front legyen aktív
  • a bemeneti jel frekvenciájának megváltoztatása egy előskálázó segítségével (1,2,4,8)
  • minden rögzítési csatorna beépített bemeneti szűrővel rendelkezik
  • a rögzítési jel forrása egy másik időzítő is lehet
  • minden csatornához két jelző van biztosítva, az első akkor van beállítva, ha rögzítés történt, a második, ha rögzítés történt az első jelzővel

A regiszterek a rögzítési mód beállítására szolgálnak. CCMR1(1 és 2 csatornához) és CCMR2(3-hoz és 4-hez), valamint regisztereket CCER, DIER.

Nézzük meg közelebbről a regiszterbit mezőket CCMR2, amelyek a 4 időzítő csatorna beállításáért felelősek, ezt a példában konfiguráljuk. Azt is szeretném megjegyezni, hogy ugyanabban a regiszterben vannak olyan bitmezők, amelyeket az időzítő összehasonlító módban történő beállításakor használunk.

CC4S- meghatározza a negyedik csatorna irányát (bemenet vagy kimenet). Ha egy csatornát bemenetként konfigurál, rögzítési jelet rendel hozzá

  • 00 - csatorna kimenetként működik
  • 01 - csatorna bemenetként működik, rögzítő jel - TI4
  • 10 - csatorna bemenetként működik, rögzítő jel - TI3
  • 11 - csatorna bemenetként működik, rögzítő jel - TRC
IC4PSC– határozza meg az osztási tényezőt a rögzítő jelhez
  • 00 - az osztó nincs használatban, az IC1PS rögzítési jel minden eseményhez generálódik
  • 01 - minden második eseményhez rögzítési jel generálódik
  • 10 - minden negyedik eseményhez rögzítési jel generálódik
  • 11 - minden nyolcadik eseményhez rögzítési jel generálódik
IC4F- a bemeneti szűrő beállítására tervezték, a minták számán túl, amelyek során a mikrokontroller nem reagál a bemeneti jelekre, a mintavételezési frekvenciát is beállíthatja. Lényegében az él megérkezésének pillanatától a "nyugtázó" mintáig állítjuk be a késleltetési időt.

Most pedig nézzük a regisztert CCER.

CC4E- engedélyezi/letiltja a rögzítési módot.
CC4P- meghatározza az elejét, amely mentén a rögzítés történik, 0 - elöl, 1 - hátul.

És regisztrálj DIER.

CC4DE- lehetővé teszi a DMA-hoz intézett kérelem benyújtását.
CC4IE- Lehetővé teszi a rögzítési megszakítást.

A rögzítés megtörténte után egy rögzítési esemény jön létre, amely beállítja a megfelelő jelzőt. Ez megszakítást és kérést okozhat DMA ha engedélyezik őket a nyilvántartásban DIER. Ezenkívül egy rögzítési esemény programozottan is előállítható az eseménygeneráló regiszter bitmezőjének beállításával EGR:

Bit mezők CC1G, CC2G, CC3G és CC4G lehetővé teszi, hogy eseményt generáljon a megfelelő rögzítési/összehasonlítási csatornán.

Apropó, CCR1, CCR2, CCR3 és CCR4- rögzítő regiszterek, amelyek a rögzítő jelen tárolják az időzítő értékét.

A rögzítési jel kialakulásának szabályozása érdekében a regiszterben SR Minden csatornának két zászlója van.

CC4IF- beállítva a rögzítési jel generálásakor, ezeket a jelzőket szoftverrel vagy a megfelelő rögzítési/összehasonlítási regiszter kiolvasásával alaphelyzetbe állítjuk.
CC4OF- állítsa be, ha a CC4IF jelző nem törlődött, de újabb rögzítési jel érkezett. Ez a jelző programozottan nulla beírásával törlődik.

Most alkalmazzuk a megszerzett tudást a gyakorlatban, a jelgenerátortól a TIM5_CH4 bemenetig egy 50 Hz-es frekvenciájú szinuszost fogunk alkalmazni, és megpróbáljuk megmérni a periódusát. A folyamat felgyorsítása érdekében a DMA használatát javaslom. Az, hogy az MK melyik kimenete felel meg a TIM5 4. csatornájának, az MK-ról szóló adatlapon található. Pinouts és pin leírás.

Mert DMA regisztrációs cím szükséges CCR4, itt találja meg. Nyitunk RM0008és a táblázatban Regisztrálja a határcímeket keresse meg a TIM5 kezdőcímét.


regiszter eltolás CCR4 alatt található ugyanabban a dokumentumban regisztrálni térképet.

#include "stm32f10x.h" #define TIM5_CCR4_Address ((u32)0x40000C00+0x40) #define DMA_BUFF_SIZE 2 uint16_t buff;//Puffer uint16_t volatile T; void DMA2_Channel1_IRQHandler (void) ( T = (buff > buff) ? (buff - buff) : (65535+ buff - buff); DMA2->IFCR |= DMA_IFCR_CGIF1; ) void Init_DMA(void) ( RCC->RCCD_MANRBENR_RCCD_MANR2 | ; //Az első DMA-modul órajelének engedélyezése DMA2_Channel1->CPAR = TIM5_CCR4_Address; //Adja meg a periféria címét - az ADC konverziós eredményregisztert a normál csatornákhoz DMA2_Channel1->CMAR = (uint32_t)buff; //Állítsa be a memóriacímet - a a tömb alapcíme a RAM-ban DMA2_Channel1 ->CCR &= ~DMA_CCR1_DIR; //Adja meg az adatátvitel irányát a perifériáról a memóriába DMA2_Channel1->CNDTR = DMA_BUFF_SIZE; //Az átvitt értékek számaDMA2_Channel1->CCR = ~DMA_CCR1_PINC; //Ne növelje a perifériacímet minden DMA2_Channel1 átvitel után ->CCR |= DMA_CCR1_MINC; //Növelje a memóriacímet minden átvitel után DMA2_Channel1->CCR |= DMA_CCR1_PSIZE_0; //Periféria adatmérete -_216C bitméret DMA216 CCR |= DMA_CCR1_MSIZE_0; //Memória adatmérete - 16 bit DMA2_Channel1- >CCR |= DMA_CCR1_PL; //A prioritás nagyon magas DMA2_Channel1->CCR |= DMA_CCR1_CIRC; //DMA engedélyezése ciklikus módban DMA2_Channel1->CCR |= DMA_CCR1_TCIE;//Megszakítás engedélyezése az átvitel végén DMA2_Channel1->CCR |= DMA_CCR1_EN; // Az 1. DMA csatorna engedélyezése ) int main(void) ( Init_DMA(); // az A port órajelének engedélyezése, az alternatív funkciók és az időzítő RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN; RCC->APB1ENR |= RCC_IMB -1EN; >PSC = 56000-1;//új frekvencia 1Khz TIM5->CCMR2 |= TIM_CCMR2_CC4S_0;//válasszon TI4-et a TIM5_CH4 TIM5->CCMR2-hez &= ~(TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC) és nem osztó használja a TIM5- >CCER &= ~TIM_CCER_CC4P;//rögzítés kiválasztása a felfutó élen TIM5->CCER |= TIM_CCER_CC4E;//rögzítési mód engedélyezése a 4. csatornához TIM5->DIER |= TIM_DIER_CC4DE;//kérelem létrehozásának engedélyezése DMA-hoz //TIM5 ->DIER |= TIM_DIER_CC4IE; //rögzítési megszakítás engedélyezése TIM5->CR1 |= TIM_CR1_CEN; //számláló engedélyezése //NVIC->ISER |= NVIC_ISER_SETENA_18; //TIM5 megszakítás NVIC->ISER_2 |_= NVENA ; //DMA megszakítás while(1) ( ) )

Az STM32 számos nagyon kényelmes és rugalmas időzítőt tartalmaz. Még a legfiatalabb mikrokontrollerben is (STM32F030F4P6) van 4 ilyen időzítő.

8. Állítsa be a projektet - adja hozzá a szükséges fájlokat

Az időzítő használatához tartalmaznunk kell az stm32f10x_tim.c perifériakönyvtár fájlt. Ugyanígy kattintson a jobb gombbal a Munkaterületen (bal oldali ablak) a StdPeriphLib csoport Add –> Add Files, a LibrariesSTM32F10x_StdPeriph_Driversrcstm32f10x_tim.c fájlra.

Engedélyeznie kell a fejléc használatát is ehhez a fájlhoz. Nyissa meg az stm32f10x_conf.h fájlt (kattintson jobb gombbal a fájl nevére a kódban: "Open stm32f10x_conf.h". Törölje a megjegyzéseket az #include "stm32f10x_tim.h" sorból.

9. Adjon hozzá egy időzítőt

Az üres ciklus késleltetése szentségtörés, különösen egy olyan erős kristályon, mint az STM32, egy csomó időzítővel. Ezért ezt a késleltetést időzítővel fogjuk elvégezni.

Az STM32 különböző időzítőkkel rendelkezik, amelyek tulajdonságaikban különböznek. A legegyszerűbbek a Basic időzítők, a nehezebbek az általános célú időzítők, a legnehezebbek pedig az Advanced időzítők. Az egyszerű időzítők csak a ciklusok számlálására korlátozódnak. A bonyolultabb időzítőkben megjelenik a PWM. A legkifinomultabb időzítők például képesek 3 fázisú PWM-et generálni előre és hátra kimenetekkel és holtidővel. Egy egyszerű, 6-os időzítő elég nekünk.

Egy kis elmélet

Az időzítőtől csak egy bizonyos értékig kell számolnunk és megszakítást generálnunk (igen, megtanuljuk a megszakítások használatát is). A TIM6 időzítő órajele a rendszerbuszról történik, de nem közvetlenül, hanem egy előskálázón keresztül - egy egyszerű programozható ellenosztón (gondoljunk csak, a Szovjetunióban gyártottak speciális mikroáramkörök-számlálókat, és a programozhatóak külön hiányosságok voltak - és most Csak úgy véletlenül beszélek egy ilyen számlálóról). Az előskálázó tetszőleges értékre állítható 1-től (azaz a teljes buszfrekvencia, 24 MHz, a számlálót fogja érni) 65536-ig (azaz 366 Hz-ig).

Az órajelek viszont növelik a belső időzítő számlálóját, nulláról indulva. Amint a számláló értéke eléri az ARR értéket, a számláló túlcsordul, és bekövetkezik a megfelelő esemény. Az esemény bekövetkezésekor az időzítő ismét 0-t tölt be a számlálóba, és nullától kezdi a számlálást. Ugyanakkor megszakítást is kiválthat (ha be van állítva).

Valójában a folyamat egy kicsit bonyolultabb: két ARR-regiszter létezik - külső és belső. A számítás során az aktuális értéket pontosan összehasonlítjuk a belső regiszterrel, és csak túlcsordulás esetén frissül a belső a külsőről. Így biztonságosan módosíthatja az ARR-t az időzítő futása közben - bármikor.

A kód

A kód nagyon hasonló lesz az előzőhöz, mert. az összes periféria inicializálása ugyanúgy történik - azzal az egyetlen kivétellel, hogy a TIM6 időzítő az APB1 buszon lóg. Ezért az időzítő engedélyezése: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

Most létrehozunk egy TIM_TimeBaseInitTypeDef típusú struktúrát, inicializáljuk (TIM_TimeBaseStructInit), beállítjuk, átadjuk az időzítő inicializálási funkciójának (TIM_TimeBaseInit) és végül engedélyezzük az időzítőt (TIM_Cmd).

TIM_TimeBaseInitTypeDef TIM_InitStructure; // A struktúra beállítása TIM_TimeBaseStructInit(&TIM_InitStructure); // A TIM_InitStructure struktúra inicializálása TIM_Prescaler = 24000; // Előskálázó TIM_InitStructure.TIM_Period = 1000; // Időzítő periódusa TIM_TimeBaseInit(TIM6, &TIM_InitStructure); // Időzítő beállítás funkció TIM_Cmd(TIM6, ENABLE); // Kapcsolja be az időzítőt

Mik azok a varázsszámok? Emlékszünk rá, hogy a buszon 24 MHz órajel van (a projektbeállításainkkal). Az időzítő előskálázót 24000-re állítva ezt a frekvenciát elosztjuk 24 ezerrel, és 1kHz-et kapunk. Ez a frekvencia az időzítő számlálójának bemenetére kerül.

A számláló értéke 1000. Ez azt jelenti, hogy a számláló 1000 ciklus alatt túlcsordul, azaz. pontosan 1 másodperc.

Ezek után tényleg van egy működő időzítőnk. De ez még nem minden.

10. Kezelje a megszakításokat

Oké, megszakítások. Számomra egykor (a PIC-napok alatt) sötét erdő volt, és megpróbáltam egyáltalán nem használni őket - és nem is tudtam, hogyan. Azonban olyan erőt tartalmaznak, amelyet általában nem érdemes figyelmen kívül hagyni. Igaz, a megszakítások az STM32-ben még bonyolultabb dolog, főleg az ezek megelőzésének mechanizmusa; de erről majd később.

Amint azt korábban megjegyeztük, az időzítő megszakítást generál a számláló túlcsordulásának pillanatában - ha az eszköz megszakítási feldolgozása egyáltalán engedélyezett, akkor ez a megszakítás engedélyezve van, és az előző visszaáll. Ezt a kifejezést elemezve megértjük, mire van szükségünk:

  1. A TIM6 időzítő megszakítások engedélyezése egyáltalán;
  2. A TIM6 időzítő megszakítás engedélyezése a számláló túlcsordulásához;
  3. Írjon egy megszakításkezelő eljárást;
  4. A megszakítás feldolgozása után állítsa vissza.

Megszakítások engedélyezése

Őszintén szólva, nincs semmi bonyolult. Először is engedélyezze a TIM6 megszakításokat: NVIC_EnableIRQ(TIM6_DAC_IRQn); Miért ilyen név? Mert az STM32 magban a TIM6 és a DAC megszakításainak ugyanaz a száma. Nem tudom miért csinálták így - spórolás, számhiány, vagy csak valami örökölt dolog - mindenesetre ez nem fog gondot okozni, mert ez a projekt nem használ DAC-ot. Még ha DAC-ot használtunk is a projektünkben, a megszakítás beírásakor megtudhattuk, hogy konkrétan ki hívta. Szinte az összes többi időzítőnek egyetlen megszakítása van.

Megszakítási forrásesemény konfigurációja: TIM_ITConfig(TIM6, TIM_DIER_UIE, ENABLE); - kapcsolja be a TIM6 időzítő megszakítását a TIM_DIER_UIE eseménynél, pl. ARR érték frissítési esemény. Ahogy a képről emlékszünk, ez a pult túlcsordulásával egy időben történik – tehát pontosan erre az eseményre van szükségünk.

Jelenleg az időzítő esetek kódja a következő:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); TIM_TimeBaseInitTypeDef TIM_InitStructure; TIM_TimeBaseStructInit(&TIM_InitStructure); TIM_InitStructure.TIM_Prescaler = 24000; TIM_InitStructure.TIM_Period = 1000; TIM_TimeBaseInit(TIM6, &TIM_InitStructure); TIM_Cmd(TIM6, ENGEDÉLYEZÉS); NVIC_EnableIRQ(TIM6_DAC_IRQn); TIM_ITConfig(TIM6, TIM_DIER_UIE, ENGEDÉLYEZÉS);

Megszakítás kezelés

Most nem indíthatja el a projektet - az időzítő legelső megszakítása nem találja meg a kezelőjét, és a vezérlő lefagy (pontosabban a HARD_FAULT kezelőbe esik, ami lényegében ugyanaz). Meg kell írnod.

Egy kis elmélet

Nagyon konkrét névvel kell rendelkeznie, érvénytelen TIM6_DAC_IRQHandler(void). Ezt a nevet, az úgynevezett megszakítási vektort az indítófájl írja le (projektünkben ez startup_stm32f10x_md_vl.s - ezt saját szemével láthatja, 126. sor). Valójában a vektor a megszakításkezelő címe, és amikor megszakítás történik, az ARM mag bemászik a kezdeti területre (ahová az indítófájlt lefordítják - azaz a helye teljesen mereven van beállítva, a megszakítás legelején). flash memória), megkeresi a vektort ott, és a megfelelő helyre megy a kódban.

Eseményellenőrzés

Az első dolog, amit meg kell tennünk, amikor belépünk egy ilyen kezelőbe, hogy ellenőrizzük, melyik esemény okozta a megszakítást. Most már csak egy eseményünk van, de egy valódi projektben több esemény is lehet egy időzítőn. Ezért ellenőrizzük az eseményt, és végrehajtjuk a megfelelő kódot.

Programunkban ez az ellenőrzés így fog kinézni: if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) - minden tiszta, a TIM_GetITStatus függvény ellenőrzi, hogy az időzítő rendelkezik-e a megadott eseményrel, és 0 vagy 1 értéket ad vissza.

Az UIF zászló törlése

A második lépés a megszakítási jelző törlése. Vissza a képhez: a legutolsó UIF-gráf a megszakítási jelző. Ha nem törli, a következő megszakítás nem hívható meg, és a vezérlő ismét HARD_FAULT-ba kerül (mi az!).

Műveletek végrehajtása megszakításban

Egyszerűen átkapcsoljuk a LED állapotát, mint az első programban. A különbség az, hogy most a programunk megnehezíti! Valójában sokkal helyesebb így írni.

If(állapot) GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET); else GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET); állapot = 1 - állapot;

Az int state=0 globális változót használjuk;

11. Minden projekt kód időzítővel

#include "stm32f10x_conf.h" int state=0; void TIM6_DAC_IRQHandler(void) ( if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) ( TIM_ClearITPendingBit(TIM6, TIM_IT_Update); if(state) else_RESET_, GPIOGPP_8;GPIO_GRP_8;GPIO_GRP_8 = 1 - state; ) ) void main() ( RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Speed ​​​​= GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOC , &GPIO_InitStructure ); GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); TIM_TimeBaseInitTypeDef TIM_InitStructure; TIM_TimeBaseStructInit(&TIM_InitStructure); TIM_InitStructure.TIM_Prescaler = 24000; TIM_InitStructure.TIM_Period = 1000; TIM_TimeBaseInit(TIM6, &TIM_InitStructure); TIM_Cmd(TIM6 , ENABLE ); NVIC_EnableIRQ(TIM6_DAC_IRQn); TIM_ITConfig(TIM6, TIM_DIER_UIE, ENABLE); while(1) ( ) )

Archiválás az időzítő projekttel.

Nos, mellesleg az időzítő magát a lábat tudja váltani, megszakítások és kézi feldolgozás nélkül. Ez lesz a harmadik projektünk.

A teljes ciklus:

1. I/O portok

2. Időzítő és megszakítások

3. Időzítő kimenetek

4. Külső megszakítások és NVIC

5. Telepítse a FreeRTOS-t

Megtekintések száma: 235