Tym razem chciałem przedstawić sposób obsługi timerów w mikrokontrolerze z rdzeniem Cortex M3. Opiszę sposób inicjalizacji timerów oraz zastosowanie licznik SysTick jako pętli opóźniającej.
Wstęp
W tym układzie jest możliwość obsługi 7 wbudowanych timerów. Z czego do użytku typowego wykorzystuje się cztery z nich.
- Cztery 16 bitowe timery;
- Dwa układy czuwające (Watchdog);
- Jeden Systick - jest to 24 bitowy licznik zliczający w dół od zadanej wartości.
Taktowanie
Układ taktowany jest z wewnętrznego oscylatora. Jego częstotliwość taktowania wynosi 8MHz. Przy korzystaniu z powielacza częstotliwości sygnał jest odpowiednio zwiększany do pożądanej wartości. Następnie ustawiamy wartość PLLMul, która przemnaża podawaną częstotliwość z HSI podzieloną przez 2. Wartość PLLMul można wybrać z przedziału od 2 do 16.
Jeśli chcemy uzyskać wartość taktowania maksymalną, jaką można otrzymać poprzez wewnętrzny oscylator, czyli 64MHz, to należy wybrać parametr PLLMul na 16 oraz AHB Prescaler na 1.
W takim przypadku otrzymamy następujące maksymalne taktowanie wszystkich linii.
- APB1 GPIO - 32 MHz;
- APB1 Timer - 64 MHz;
- APB2 GPIO - 64 MHz;
- APB2 Timer - 64 MHz;
Program 1 - Inicjalizacja SysTicka
Działanie systicka polega na zmniejszaniu wartości w kolejnych przejściach od wartości zadanej. Po przejściu układu przez 0 generowane jest przerwanie. Po wywołaniu przerwania zliczanie rozpoczyna się od nowa. Jego zadaniem jest odliczanie podanego przedziału czasu.
Konfiguracja tego licznika rozpoczyna się od podania wartości początkowej, od której nastąpi odliczanie. Od niej oraz od wartości taktowania zależy jak często będzie zgłaszane przerwanie przez licznik.
W pierwszej kolejności należy zdeklarować zmienną przechowującą wartości. Dalej następuje wybranie wartości początkowej licznika czyli co ile przerwanie będzie zgłaszane.
Przerwanie od licznika ma być zgłaszane co 1 ms czyli 1/1000 s. W związku z tym wybieramy sygnał jakim jest główny sygnał taktujący czyli 64MHz. Sygnał ten zostaje podzielony przez wartość 1000. Dzięki takiej operacji przerwanie będzie zgłaszane co 64000 takty układu.
Konfiguracja tego licznika rozpoczyna się od podania wartości początkowej, od której nastąpi odliczanie. Od niej oraz od wartości taktowania zależy jak często będzie zgłaszane przerwanie przez licznik.
W pierwszej kolejności należy zdeklarować zmienną przechowującą wartości. Dalej następuje wybranie wartości początkowej licznika czyli co ile przerwanie będzie zgłaszane.
Przerwanie od licznika ma być zgłaszane co 1 ms czyli 1/1000 s. W związku z tym wybieramy sygnał jakim jest główny sygnał taktujący czyli 64MHz. Sygnał ten zostaje podzielony przez wartość 1000. Dzięki takiej operacji przerwanie będzie zgłaszane co 64000 takty układu.
#include "stm32f10x.h" #define PinDioda GPIO_Pin_5 #define LineDioda GPIOA #define ClockGPIOA RCC_APB2Periph_GPIOA volatile uint32_t timer = 0; void DelayInitial(void); void DelayMs(uint32_t); void SysTick_Handler(void); void GpioInit(void); int main(void) { GpioInit(); DelayInitial(); while (1) { GPIO_SetBits(LineDioda, PinDioda); DelayMs(1000); GPIO_ResetBits(LineDioda, PinDioda); DelayMs(2000); } } void GpioInit(void) { //inicjalizacja obiektu GPIO GPIO_InitTypeDef GpioInit; //Włączenie zegara dla linii GPIOA RCC_APB2PeriphClockCmd(ClockGPIOA, ENABLE); //Inicjalizacja pinu Dioda GPIO_StructInit(&GpioInit); //Wybranie konfigurowanego pinu GpioInit.GPIO_Pin = PinDioda; //Ustawienie pinu jak wyjście PushPull GpioInit.GPIO_Mode = GPIO_Mode_Out_PP; //Inicjalizacja linii z podanymi ustawieniami GPIO_Init(LineDioda, &GpioInit); } void SysTick_Handler() { if(timer) { timer--; } } void DelayMs(uint32_t time) { timer = time; while(timer) {} } void DelayInitial(void) { //Ustawienie opóźnień co 1ms = 64000000 / 1000 SysTick_Config(SystemCoreClock / 1000); }
W przypadku gdy chcemy wywołać przerwania co 1us. Wtedy należy zmienić parametry w części DelayInit(). Wartość częstotliwości należy w takim przypadku podzielić przez 1000000. W takim przypadku przerwanie będzie wykonywane co 64 takty zegara.
Systick pozwala na wykonanie bardzo dokładnej pętli opóźniającej. Dodatkowo możliwe jest jego zastosowanie w przypadkach pomiaru długości trwania stanu wysokiego np. w czujniku HCSR-04. Gdzie mierzona jest odległość czujnika od przeszkody. W takim przypadku mierzy się ilość wystąpień przerwania w czasie występowania stanu wysokiego na pinie.
void DelayInitial(void) { SysTick_Config(SystemCoreClock / 1000000); }
Systick pozwala na wykonanie bardzo dokładnej pętli opóźniającej. Dodatkowo możliwe jest jego zastosowanie w przypadkach pomiaru długości trwania stanu wysokiego np. w czujniku HCSR-04. Gdzie mierzona jest odległość czujnika od przeszkody. W takim przypadku mierzy się ilość wystąpień przerwania w czasie występowania stanu wysokiego na pinie.