czwartek, 3 listopada 2016

[3] STM32F1 - Rejestry - Timer na przerwaniach

Ten post chciałbym poświęcić na opisanie timerów w mikrokontrolerze STM32F103.

Rejestry:


Dokładny opis przedstawionych rejestrów znajduje się w dokumentacji producenta CD00017119.

TIMx_CR1 - jest to 16 bitowy rejestr kontrolny. Do wyboru są takie ustawienia jak prędkość (CKD), automatyczne przeładowanie (ARPE), sposób zliczania (CMS), kierunek (DIR), tryb jedno-impulsowy (OPM), żądanie aktualizacji źródła (URS), wyłączenie aktualizacji UEV (UDIS), włączenie zliczania (CEN);

TIMx_CR2 - Podobnie jak CR1 on także jest 16 bitowy. Do ustawienia możliwe są tryby pracy, sposoby podłączenia do wyprowadzeń, DMA, aktualizacje oraz kontrola przeładowania.


TIMx_PSC - dzielnik dla timera


TIMx_ARR - do niego podaje się wartość, po której nastąpi automatyczne przeładowanie licznika


TIMx_CNT - licznik, na 16 bitach przechowuje wartość do jakiej lub od jakiej będzie zliczał.


TIMx_SR - przechowuje flagi wyzwalane wystąpieniem różnych zdarzeń


TIMx_EGR - generacja zdarzeń.


TIMx_DIER - pozwala na ustawienie trybu pracy DMA oraz przerwań


TIMx_SMCR - 16 bitowy rejestr kontrolny trybu slave, ustawienie polaryzacji przełącznika, zewnętrznego zegara, dzielnika, rodzaj filtru, tryb pracy, sposobu wyzwalania poprzez inny timer oraz wybranie rodzaju pracy w trybie slave.


W przypadku timerów dla przerwania należy uruchomić tylko wewnętrzne tzn. NVIC.

Programowanie:


Należy je rozpocząć standardowo od włączenia zegarów dla wykorzystywanych portów oraz dla timera. Następnie należy aktywować pin na którym chcemy określony sygnał wyprowadzić.

Co do rejestrów licznika wprowadza się do rejestru dzielnika (TIMx_PSC), rejestru przeładowania (TIMx_ARR), wybór akcji przy jakiej licznik ma generować przerwanie (TIMx_DIER) oraz na samym końcu należy włączyć sam licznik za pomocą rejestru kontrolnego (TIMx_CR1). Dalej należy włączyć przerwania od odpowiedniego timera.

  1. #include "stm32f10x.h"
  2. volatile uint8_t zmienna = 0;
  3. int main(void)
  4. {
  5.     RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
  6.     RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
  7.     RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
  8.     //Konfiguracja GPIOB PB0 jako output, 2MHz
  9.     GPIOB->CRL = 1<<1;
  10.     //Konfiguracja GPIOA PA7 jako output, 2MHz
  11.     GPIOA->CRL = 1<<29;
  12.     //Konfiguracja TIM1
  13.     TIM1->PSC = 2999;
  14.     TIM1->ARR = 59999;
  15.     TIM1->DIER = TIM_DIER_UIE;
  16.     TIM1->CR1 = TIM_CR1_CEN;
  17.     NVIC_EnableIRQ(TIM1_UP_IRQn);
  18.     while (1){}
  19. }
  20. __attribute__((interrupt)) void TIM1_UP_IRQHandler(void)
  21. {
  22.     if(TIM1->SR & TIM_SR_UIF)
  23.     {
  24.         TIM1->SR =~TIM_SR_UIF;
  25.         //Zmiana stanu na
  26.         if(zmienna == 0)
  27.         {
  28.             GPIOB->BSRR |= GPIO_BSRR_BS0;
  29.             GPIOA->BSRR |= GPIO_BSRR_BS7;
  30.             zmienna = 1;
  31.         }
  32.         else if(zmienna == 1)
  33.         {
  34.             GPIOB->BSRR |=~ GPIO_BSRR_BS0;
  35.             GPIOA->BSRR |=~ GPIO_BSRR_BS7;
  36.             zmienna = 0;
  37.         }
  38.     }
  39. }