LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

STM32F0Discovery: jak zacząć

W pliku stm32f0_discovery.c znajdują się definicje sześciu pomocnych funkcji do pracy z diodami i przyciskiem:

--- Konfiguracja wyprowadzeń do których podłączone są diody
void STM_EVAL_LEDInit(Led_TypeDef Led);
--- Włączenie diody
void STM_EVAL_LEDOn(Led_TypeDef Led);
--- Wyłączenie diody
void STM_EVAL_LEDOff(Led_TypeDef Led);
--- Przełączenie stanu diody na przeciwny
void STM_EVAL_LEDToggle(Led_TypeDef Led);
--- Konfiguracja wyprowadzenia do którego podłączony jest przycisk
void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode);
--- Odczytanie stanu linii do której jest podłączony przycisk
uint32_t STM_EVAL_PBGetState(Button_TypeDef Button);

Pierwsza funkcja przyjmuje jako argument wartość LED3 (liczba 0) albo LED4 (liczba 1), włącza sygnał zegarowy w obu przypadkach taktujący układ PORTC, który jest podłączony do szyny AHB, konfiguruje wyprowadzenie (PC8 lub PC9) na wyjście typu push-pull bez wewnętrznych rezystorów podciągających i do pracy z maksymalną częstotliwością 50 MHz:

void STM_EVAL_LEDInit(Led_TypeDef Led){
  GPIO_InitTypeDef  GPIO_InitStructure;
  
  /* Włączenie sygnału zegarowego dla danego portu */
  RCC_AHBPeriphClockCmd(GPIO_CLK[Led], ENABLE);

  /* Konfiguracja wyprowadzenia GPIO_LED */
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN[Led];
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIO_PORT[Led], &GPIO_InitStructure);
}

Druga funkcja wykorzystuje rejestr BSRR do ustawiania w stan wysoki określonych linii portu. Tutaj pod nazwą GPIO_PIN[Led] kryje się wartość GPIO_Pin_8 lub GPIO_Pin_9 (które są zdefiniowane jawnie w pliku stm32f0xx_gpio.h):

void STM_EVAL_LEDOn(Led_TypeDef Led){
  GPIO_PORT[Led]->BSRR = GPIO_PIN[Led];
}

Funkcja wyłączająca diodę jest podobna do poprzedniej, ale wykorzystuje rejestr BRR do zerowania określonej linii portu:

void STM_EVAL_LEDOff(Led_TypeDef Led){
  GPIO_PORT[Led]->BRR = GPIO_PIN[Led];
}

Funkcja zmieniająca stan diody na przeciwny operuje na rejestrze danych wyjściowych ODR. Pobiera ona zawartość tego rejestru, wykonuje na niej operację XOR z wartością GPIO_Pin_8 lub GPIO_Pin_9 i zapisuje z powrotem do rejestru ODR:

void STM_EVAL_LEDToggle(Led_TypeDef Led){
  GPIO_PORT[Led]->ODR ^= GPIO_PIN[Led];
}

Linia do której podłączony jest przycisk konfigurowana jest w funkcji STM_EVAL_PBInit() do której należy przekazać 2 argumenty. Pierwszy określa jaki przycisk będzie konfigurowany, a że na płytce jest dostępny tylko jeden przycisk do zastosowania w aplikacji to wystarczy przekazać stałą BUTTON_USER, albo liczbę 0. Drugi argument mówi czy linia będzie tylko skonfigurowana (BUTTON_MODE_GPIO) czy również będzie skonfigurowane przerwanie od zmiany jej stanu (BUTTON_USER_EXTI). W programie głównym wykorzystano pierwszą opcję bez wykorzystania przerwań, a linia PA0 jest konfigurowana jako wejście bez rezystorów podciągających, gdyż taki znajduje się już na płytce. Listing funkcji jest następujący:

void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode){
  GPIO_InitTypeDef GPIO_InitStructure;
  EXTI_InitTypeDef EXTI_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Włącz sygnały zegarowe */
  RCC_AHBPeriphClockCmd(BUTTON_CLK[Button], ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  /* Konfiguracja linii jako wejście */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin = BUTTON_PIN[Button];
  GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStructure);

  if (Button_Mode == BUTTON_MODE_EXTI){
    /* Connect Button EXTI Line to Button GPIO Pin */
    SYSCFG_EXTILineConfig(BUTTON_PORT_SOURCE[Button], BUTTON_PIN_SOURCE[Button]);

    /* Configure Button EXTI line */
    EXTI_InitStructure.EXTI_Line = BUTTON_EXTI_LINE[Button];
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    if (Button != BUTTON_USER){
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    }
    else{
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    
    }
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* Enable and set Button EXTI Interrupt to the lowest priority */
    NVIC_InitStructure.NVIC_IRQChannel = BUTTON_IRQn[Button];
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure); 
  }
}
Autor: Jan Szemiet