Takže tu máme druhý program, opět blikání LEDkou, ale tentokrát pomocí přerušení od časovače SysTick. Změna frekvence blikání je řešena tlačítkem (USER BUTTON). Program byl opět převzatý ze stránek mcu.cz přesněji z http://mcu.cz/comment-n2119.html. Jako pomůcka nám pomůže vývojový diagram.
Nejprve se zavolá funkce Delay() v té se provede zápis hodnoty do TimeForDelay, poté se čeká dokud není TimeForDelay = 0. Dekrementace TimeForDelay se provádí ve funkci DelayTime(), ta se volá po přerušení ze SysTick_Handler (přerušení od časovače). Jak často má k přerušení docházet je nastaveno takto:
if(SysTick_Config(SystemCoreClock / 1000)){
while(1);
}
Pro lepší pochopení tohoto příkazu ho trochu rozebereme. Do SysTick_Config se zapíše hodnota (SystemCoreClock / 1000). To znamená 8 000 000Hz / 1000 => 8000, ale protože je to if (xxx) znamená to, že dokud není SysTick_Config = 8000 zůstane v nekonečné smyčce. Proto výsledné zpoždění je 1ms.
Pokud SysTick_Config není nastaven, resp. nemá nastavený jiné hodiny, pak je frekvence odebíráná z interních hodin (8MHz).
Nastavení „co se stane, když nastane přerušení“ se nastavuje v knihovně stm32f30x_it.c
void SysTick_Handler(void)
{
DelayTime();
}
V tomto případě se pouze zavolá funkce DelayTime, v které se provedou následující příkazy:
Porovná se hodnota TimeForDelay jestli už není nulová, pokud ne, dekrementuje se hodnota TimeForDelay. Ve funkci Delay(), ale stále čekáme (while TimeForDelay != 0) dokud nebude TimeForDelay nulový. Po dalším přerušení se opět zavolá funkce DelayTime() a zkontroluje se hodnota TimeForDelay. Pokud je už nulová, neprovede se žádná další instrukce ve fci DelayTime (už žádná není), zatímco v funkci Delay() se ukončí čekání na nulovou hodnotu TimeForDelay. Poté se pokračuje další instrukcí, tedy pro zapnutí/vypnutí LED. Následuje další instrukce, kde zapíšeme ve funkci Delay() novou hodnotu TimeForDelay. A celý proces se opakuje. Tlačítkem (USER BUTTON) pouze měníme hodnotu TimeForDelay.
Následuje kompletní kód v main.c
/*
* STM32F303-Discovery – LED, USER_BUTTON and interrupt timer SysTick
* Petus 2.9.2013
* source: mcu.cz – Mard
*/
/* Includes ——————————————————————*/
#include
#include „stm32f30x.h“
#include „stm32f30x_conf.h“
#include „STM32F3_Discovery.h“
/* Private typedef ———————————————————–*/
/* Private define ————————————————————*/
/* Private macro ————————————————————-*/
/* Private variables ———————————————————*/
/* Private function prototypes ———————————————–*/
__IO uint32_t Count;
static __IO uint32_t TimeForDelay;
void GPIO_Initi(void); // GPIO set
void Delay(__IO uint32_t nCount);
void DelayTime(void);
int main(void)
{
GPIO_Initi();
if(SysTick_Config(SystemCoreClock / 1000)){
while(1);
}
while (1)
{
if(0 != STM_EVAL_PBGetState(BUTTON_USER)){
Count = 100;
}
else{
Count = 500;
}
STM_EVAL_LEDOff(LED9); // LED9 off
Delay(Count);
STM_EVAL_LEDOn(LED9); // LED9 on
Delay(Count);
}
}
void GPIO_Initi(void)
{
STM_EVAL_LEDInit(LED8);
STM_EVAL_LEDOff(LED8);
STM_EVAL_LEDInit(LED9);
STM_EVAL_LEDOff(LED9);
STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO);
}
void DelayTime(void){
if(TimeForDelay != 0x00){
TimeForDelay–;
}
}
void Delay(__IO uint32_t nTick){
TimeForDelay = nTick;
while(TimeForDelay != 0);
}