Obsługa programowanego detektora napięcia PVD
PVD (Programmable Voltage Detector) jest wewnętrznym blokiem sprzętowym w mikrokontrloerach STM32 mającym za zadanie monitorowanie wartości napięcia zasilania. Progi, po których przekroczeniu generowane będzie przerwanie, mogą być programowane przez użytkownika w szerokich granicach.
Komparator analogowy zastosowany w PVD ma histerezę równą 100 mV. Programowany detektor poziomu napięcia jest wewnętrznie połączony z przerwaniem EXTI16, które może być generowane w chwili, gdy napięcie będzie mniejsze, większe lub różne od podanej wartości.
Rys. 1. Przykładowy sposób zaprogramowania PVD
Na rys. 1 przedstawiono sytuację, w której układ PVD został skonfigurowany do generowania przy napięciu różnym od podanej wartości. Za dobre napięcie zasilania w tym przykładzie jest uznawane napięcie o wartości powyżej 3 V, natomiast próg PVD został ustalony na 2,8 V. Na rysunku pokazano również, w jaki sposób działa 100 mV histereza. Czarne punkty wskazują miejsca wygenerowania przerwania.
Napięcie progu wyzwalania może być programowane w granicach od 2,2 V do 2,9 V, z krokiem co 0,1 V. Tak szeroki zakres pozwala na dobór parametru stosownie do wymagań aplikacji. Napięcie ustala się wywołując funkcję PWR_PVDLevelConfig() z odpowiednim parametrem. Przykładowo, jeśli projektowane urządzenie wymaga generowania przerwania po przekroczeniu napięcia 2,8 V, to należy w programie umieścić linijkę:
PWR_PVDLevelConfig(PWR_PVDLevel_2V8);
Oczywiście nie należy zapominać o wcześniejszym włączeniu programowanego detektora poziomu napięcia wywołując funkcję PWR_PVDCmd() z argumentem ENABLE.
Układ monitorujący może zwracać wartość napięcia zasilającego, jednak tego typu funkcja nie została zaimplementowana w bibliotekach firmy STMicroelectronics i do tego celu należ napisać własną, której przykład przedstawiono na list. 1.
List. 1. Przykładowa funkcja zwracająca wartość napięcia zasilającego
u8 PWR_PVDGetLevel(void) { u8 temp_val = 0; temp_val = (u8) ((PWR->CR >> 5) & 0x07); return temp_val; }
Nieco zawiłe działanie na wartości wpisywanej do zmiennej temp_val jest podyktowane pozycją bitów PLS2:0 ustawiających próg napięcia w rejestrze kontrolnym PWR_CR (rys. 2). Zajmują one pozycje 5…7, dlatego należy wykonać operację pięciokrotnego przesunięcia bitowego w prawo. Następnie w tym przykładzie zerowane są wszystkie bity oprócz trzech najmłodszych a wynik rzutowany na 8–bitowy typ bez znaku.
Rys. 2. Lokalizacja bitów PLS2…0 w rejestrze PWR_CR
Funkcję wykorzystano w przykładzie programu zmieniającym stan wyprowadzeń zależnie od wartości napięcia. Został on podzielony na dwie części: program główny i funkcję obsługi przerwania od PVD. Zadaniem pierwszej jest wstępna konfiguracja PVD i jego przerwania. Stosowny fragment programu przedstawiono na list. 2.
List. 2. Wstępna konfiguracja PVD i jego przerwania
int main(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_Conf(); NVIC_Conf(); GPIO_Conf(); // Wybranie grupy priorytetów NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // Konfiguracja i wlaczenie przerwania NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // Bedzie generowane przerwanie na zboczu opadajacym na EXTI_Line16 EXTI_InitStructure.EXTI_Line = EXTI_Line16; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); while(1); }
W pierwszej kolejności konfigurowany jest NVIC tak, aby był przygotowany na przyjęcie i obsługę przerwania z kanału 16. Następnie ustawiane są parametry samego przerwania. Tutaj ważny jest wybór zbocza, przy którym będzie ono generowane. Przedstawiony przykład działa w oparciu o reakcję na zejście napięcia zasilającego poniżej danego progu. W związku z tym przerwanie musi być generowane na zboczu opadającym. Po wykonaniu czynności konfiguracyjnych, mikrokontroler przechodzi do nieskończonej pętli while() i oczekuje na nadejście przerwania od programowanego detektora poziomu napięcia.
List. 3. Funkcja obsługi przerwania od PVD
void PVD_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line16) != RESET) { u8 level = 0; level = PWR_PVDGetLevel(); // Odczytanie, ktory // prog zostal przekroczony switch level { case 1: // poziom 2,2V GPIO_SetBits(GPIOB, GPIO_Pin_15); break; case 2: // poziom 2,3V PWR_PVDLevelConfig(PWR_PVDLevel_2V2); GPIO_SetBits(GPIOB, GPIO_Pin_14); break; case 3: // poziom 2,4V PWR_PVDLevelConfig(PWR_PVDLevel_2V3); GPIO_SetBits(GPIOB, GPIO_Pin_13); break; case 4: // poziom 2,5V PWR_PVDLevelConfig(PWR_PVDLevel_2V4); GPIO_SetBits(GPIOB, GPIO_Pin_12); break; case 5: // poziom 2,6V PWR_PVDLevelConfig(PWR_PVDLevel_2V5); GPIO_SetBits(GPIOB, GPIO_Pin_11); break; case 6: // poziom 2,7V PWR_PVDLevelConfig(PWR_PVDLevel_2V6); GPIO_SetBits(GPIOB, GPIO_Pin_10); break; case 7: // poziom 2,8V PWR_PVDLevelConfig(PWR_PVDLevel_2V7); GPIO_SetBits(GPIOB, GPIO_Pin_9); break; case 8: // poziom 2,9V PWR_PVDLevelConfig(PWR_PVDLevel_2V8); GPIO_SetBits(GPIOB, GPIO_Pin_8); break; } // Wyczysc flage przerwania EXTI_ClearITPendingBit(EXTI_Line16); } }
Drugim blokiem prezentowanej aplikacji jest funkcja obsługi przerwania od PVD – PVD_IRQHandler(). Pokazano ją na list. 3. Wykonuje ona sprawdzenie źródła przerwania oraz za pomocą wcześniej opisywanej funkcji, odczytuje wartość napięcia. W tym przykładzie, po przekroczeniu każdego z progów ustalany jest stan wysoki kolejnego wyprowadzenia mikrokontrolera i ustawiany kolejny próg napięcia.
Pewne wątpliwości może budzić sposób realizacji tego przykładu na płytce ewaluacyjnej STM3210B – EVAL/A, która ma już wmontowany na stałe stabilizator napięcia 3,3 V. Można to w łatwy sposób obejść. Wystarczy po zaprogramowaniu mikrokontrolera odłączyć źródło napięcia zasilania i wpiąć się z zewnętrznym napięciem o wartości około 3 V na wyjście stabilizatora 3,3 V zyskując w ten sposób możliwość jego regulacji. W trakcie zmniejszania napięcia zasilania na kolejnych wyprowadzeniach portu GPIOB, od PB8 zaczynając, będą pojawiać się stany wysokie. |