Novinka:STM32F0xx 6.
(Kategorie: Mikroprocesory)
Napsal mard
01.01.1970

Zkusme se tedy realizovat nějaký první pokusný projekt s Cortex M0. Tento díl by měl být jakýmsi návodem pro začínající s STM32F0Discovery kitem, tímto nejlevnějším kitem s ARM mcu na trhu. V tomto dílu zkusíme nastavit PWM výstup.



Úvod

Program budeme tvořit v Atollic TrueSTUDIO (for ARM). V tomto prostředí (Eclipse) můžete vytvářet programy pro většinu ARM Cortex M čipů a tak jde o šikovný způsob, jak jednou ranou zabít více problémů. Na čip STM32F0xx budete potřebovat nejméně verzi 3.1.0 (což je právě aktuální verze). Tato verze se chová jako Pro verze (tj. máte k dispozici většinu vymožeností, ale nově oproti verzím předcházejícím se zavedlo omezení na velikost kódu 32 kB výsledného binárního souboru. Omezení se sice dá odstranit, ale pro demonstrační příklad k tomuto dílu si vystačíme s omezením bez jakýchkoliv problémů.


Začínáme s projektem

Klasicky vytvoříme nový projekt v C (Lite verze bohužel C++ neumí).



Pokračujeme volbou Embedded C a napíšeme jméno projektu. Postupně jsem dospěl k tom že si píšu jako první část názvu typ mcu na který je projekt psán. Už se mi to začínalo plést a tohle mi pomáhá.
K dalšímu kroku se dostaneme přes tlačítko Next.



Nyní se dostáváme k novince ve verzi 3.1.0 a to je volba výrobce, protože prostředí umožňuje psát třeba pro Toshibu či NXP. Takže pochopitelně zvolíme ST Microelectronics a pokud budeme tvořit projekt pro nějaký kit, tak zvolíme i jméno tohoto ktu (v tomto případě pochopitelně STM32F0Discovery).



Tím pomalu končíme s vytvořením projektu, ještě odklepneme ST-Link jako náš debugger a necháme volbu na Tiny printf. Jiné volby jsou nám zatím k ničemu. Full printf nám vloží do kódu objekt tak velký, že se dostaneme přes limit velikosti a poslední volba nám umožní využívat metodu, kterou zde prezentoval kubik1 na přesměrování vstupu a výstupu.



Nyní máme projekt vytvořený a TrueSTUDIO nám k němu dohrálo jak knihovny (CMSIS a Peripherial Libraries), tak tiny verzi printf (tu ale nebudeme potřebovat). Navrch byl vytvořen soubor main.c, který obsahuje první demoaplikaci - blikání LED.


Vlastní program

Pro psaní budete určitě potřebovat dokumentaci od ST. Podívejte se na link v odkazech dole, který vede na homepage STM32F0 na webu ST. Tam najdete resources a stáhněte si Firmware pro STM32F0Discovery kit - tam naleznete příklady kódu (počet se postupně rozšiřuje, dnes je k dispozici 21 examples). Dále budete potřebovat Dataheet k STM32F051 a zejména obsažný Reference Manual (pro STM32F05x je potřeba RefMan číslo 91). Bez těchto věcí se budete probíjet kupředu jen těžko.

Takže se podívejme, co potřebujeme k rozjetí PWM. Vybereme si čítač, který použijeme - určitě nebudeme vytvářet PWM tak, že bychom v cyklu měnili hodnoty na výstupních pinech. Tohle je možné u 8-mi bitů, ale ARM nemám dává mnohem víc možností jak to řešit lépe. Já potřeboval vyřešit výstup 32 kHz hodinového signálu a nechtěl jsem na takovou trivialitu "vyplácat" kvalitní Timer 1. Proto jsem zvolil nakonec Timer 14, jehož výstup vede (jak se můžete přesvědčit v datasheetu v Table 13) na pin PA4. Takže další práci máme s nastavením tohoto pinu jako alternativního výstupu (alternativního proto, že jinak bychom z něj měli normální výstup, který bychom museli nastavovat my a ne výstup který bude měnit čítač).

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_4);


GPIO_Mode_AF nám nastaví Alternate Function, GPIO_OType_PP znamená Output Type = Push Pull a GPIO_PuPd_UP nám nastaví Push Pull na UP, tj. v klidu bude na výstupu logická jednička.

V posledním řádku pomocí funkce GPIO_PinAFConfig() nastavíme kterou z alternativních funkcí máme připojenu na GPIO pin. Zde je to GPIO_AF_4
(4 alternativní funkce), ale v jiných případech si pochopitelně správné číslo musíte ve výše zmíněné tabulce 13 v datasheetu spočítat.

Tak to bychom měli nastavený výstup, ale nic by se na něm neobjevilo, protože čítač/časovač TIM14 ještě nemáme nastavený. Tak se do toho pustíme.

TimerPeriod = (SystemCoreClock / 32768 ) - 1;
/* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */
Channel1Pulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);

/* TIM14 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14 , ENABLE);

/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);


Hodnotu TimerPeriod jsme spočítal tak, aby na výstupu byl 32 kHz hodinový signál (ono to není přesně 32kHz, ale 32.768 kHz a proto se dělí tak divným číslem). Abych se nemusel babrat s počítáním frekvence mcu, tak jsem použil hodnotu SystemCoreClock. Chci střídu 50%, proto je Channel1Pulse polovina periody. Až si budete s příkladem hrát tak si pochopitelně můžete měnit hodnoty v celém rozsahu, od 0 do TimerPeriod.
Pak jsme pustil hodiny do čítače (časté opomenutí u sklerotiků, proto to raději dělám hned na začátku nastavování). Zbytek je klasika, pmocí které nastavím čítač. Tím čítač čítá, ale nic negeneruje. To také musíme nastavit.

/* Channel 1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
TIM_OC1Init(TIM14, &TIM_OCInitStructure);


Nastavíme PWM výstup a potřebné parametry. Nakonec vše zapíšeme do mcu pomocí TIM_OC1Init(). Kdybychom nastavovali i jiné vystupní kanály, tak bychom postupně používali TIM_OC2Init(), atd. Ale jen u těch čítačů, které mají více kanálový výstup (v Table 3, kap 4.12 v datasheetu se můžete přesvědčit že to nejsou všechny).

Tím máme čítač i generování PWM nastavené a stačí to vše jen spustit. To provedeme následovně.

/* TIM14 counter enable */
TIM_Cmd(TIM14, ENABLE);

/* TIM14 Main Output Enable */
TIM_CtrlPWMOutputs(TIM14, ENABLE);


A nyní už zbývá program jen přeložit a otestovat pomocí LED s odporem (1k) připojené mezi PA4 a GND.


Závěr

Program v tomto dílu není nic převratného, jde jen o ukázku řešení a příklad pro vytvoření nového projektu. Zdrojový kód pro tento příklad je v odkazech, takže ti, kteří nebudou schopni podle tohoto návodu si program napsat sami, si mohou ověřit, kde udělali chybu.


Odkazy

Zdrojový kód k tomuto dílu naleznete zde.

Předcházející články:
STM32F0xx 1. naleznete zde. (popis jádra, různé typy pouzder)
STM32F0xx 2. naleznete zde. (popis jádra, různé typy pouzder)
STM32F0xx 3. naleznete zde. (pouzdro LQFP64 a LQFP48 v Eagle)
STM32F0xx 4. naleznete zde. (Verze redukce 1.0)
STM32F0xx 5. naleznete zde. (redukce verze 2.0)

Stránka STMicroelectronics týkající se F0 je zde.



Tato novinka je z -MCU Mikroelektronika - Community Site
( http://mcu.cz/news.php?extend.3174 )