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); } }