|
1. Połączenie górnego i dolnego poziomu W tym artykule omówimy funkcję snu oraz metodę budzenia w CC2430. W rzeczywistym użyciu węzeł CC2430 jest zazwyczaj zasilany bateriami, dlatego kontrola jego zużycia energii jest kluczowa. Poniżej znajduje się fragment chińskiej instrukcji CC2430 dotyczący wprowadzenia 4 trybów zużycia energii w CC2430:
Jak widać w powyższej tabeli, CC2430 ma łącznie 4 tryby zasilania:PM0(całkowicie przytomny),PM1(trochę senny),PM2(półprzytomny, półprzytomny),PM3(Śpi bardzo ciężko). Im dalej z tyłu, tym więcej funkcji jest wyłączonych, a zużycie energii coraz mniejsze. Relacja konwersji między nimi wygląda następująco:
PutPM1、PM2BudzićPM0, istnieją trzy sposoby: reset, zewnętrzne przerwanie, przerwanie timera uśpienia; Ale umieśćPM3BudzićPM0, istnieją tylko dwa sposoby: reset, zewnętrzne przerwanie (dzieje się tak, ponieważ wPM3Wszystkie oscylatory przestały działać, a oczywiście timer snu był wyłączony~) Przejdźmy przez mały eksperyment, aby wyjaśnić, jak wejść w tryb uśpienia i jak się obudzićPM0stan. 2. Systematyczny sen i eksperymenty z przerwanym budzeniem(1) Wprowadzenie do eksperymentuInicjalizacja systemu, wPM0
→ wejśćPM1
→ Obudzić się przy timerze snu po 1 sekundziePM0
→ wejśćPM2
→ został wybudzony przez timer uśpienia po 2 sekundachPM0
→ wejśćPM3
→ Czekam na naciśnięcie S1, co wywołuje zewnętrzne przerwanie i budzi sięPM0
(2) Schemat przepływu programu
(Uwaga: Zaokrąglone pole na powyższym obrazku wskazuje stan zdrowia systemu)
(3) Kod źródłowy eksperymentalny i analiza (Następujące pola można kliknąć~)Definicja pliku nagłówka i makra[url=]
[/url]
/* Opis eksperymentalny: Eksperyment z przerwanym snem budzeniowym, który wprowadza czuwanie w trzech trybach snu
*/
#include #define LED_ON 0 #define LED_OFF 1#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3 [url=] [/url]
Podfunkcje[url=] [/url]
/*Inicjalizacja zegara systemu -------------------------------------------------------*/
pustkaxtal_init(pustka)
{ SEN &= ~0x04; //Wszystkie są zasilane
podczas gdy(! (SEN &0x40)); //Oscylator kryształowy jest włączony i stabilny
CLKCON &= ~0x47; //Wybierz oscylator kryształowy 32MHz
SEN |=0x04;
}
/*Inicjalizacja LED -------------------------------------------------------*/
pustkaled_init(pustka)
{ P1SEL =0x00; //P1 to zwykły port I/O
P1DIR |=0x0F; //P1.0 P1.1 P1.2 P1.3 wyjście
led1 = LED_OFF; //Wyłącz wszystkie diody LED
led2 = LED_OFF; led3 = LED_OFF; led4 = LED_OFF;
}
/*Zewnętrzna inicjalizacja przerwań -------------------------------------------------------*/
pustkaio_init(pustka)
{ P0INP &= ~0X02; //P0.1 ma podciąganie i podciąganie w dół
EA =1; //Całkowite przerwanie dozwolone
IEN1 |= 0X20; //P0IE = 1, P0 przerwań jest włączone
PICTL |= 0X09; //P0.1 pozwala na przerwania, wyzwalania drop edge
P0IFG &= ~0x02; //P0.1 Znak przerwania clear0
}
/*Inicjalizacja przerwania przez timer uśpienia -------------------------------------------------------*/
pustkasleepTimer_init(pustka)
{ STIF=0; //Znacznik przerwania timera snu jest czysty 0
STIE=1; //Włącz timer uśpienia przerwany
EA=1; //Otwórz całkowite przerwanie
}
/*Ustaw zaplanowany odstęp czasu na czas snu -------------------------------------------------------*/
pustkasetSleepTimer(bez sygnaturyintsec)
{ NiepodpisanydługiesleepTimer =0;
sleepTimer |= ST0; //Uzyskaj wartość liczną aktualnego timera snu
sleepTimer |= (bez znakudługie)ST1 <<8; sleepTimer |= (bez znakudługie)ST2 <<16;
sleepTimer += ((unsigneddługie)sec* (niepodpisanydługie)32768); //Do tego wymagany czas trwania
ST2 = (bez znakuchar(SleepTimer >>16); //Ustaw wartość porównawczą timera snu
ST1 = (bez znakuchar(SleepTimer >>8); ST0 = (bez znakuchar)sleepTimer;
}
/*Wybierz tryb zasilania -------------------------------------------------------*/
pustkaPowerMode(bez znakuchartryb)
{
jeśli(tryb <4) { SEN &=0xfc; //Usuń SLEEP.MODE na 0
SLEEP |= tryb; //Wybierz tryb zasilania
PCON |=0x01; //Włącz ten tryb zasilania
}
}
/*Funkcja opóźnienia -------------------------------------------------------*/
pustkaOpóźnienie (bez podpisuintn)
{ Niepodpisanyinti,j;
dla(i=0; i<n; i++)
dla(j=0; j <1000; j++);
}
[url=] [/url]
Główna funkcja[url=] [/url]
/*Główna funkcja -------------------------------------------------------*/
pustkamain(pustka)
{ xtal_init(); led_init();
//Status PM0, światło włączone i opóźnienie
led1 = LED_ON; //Jasność LED1 wskazuje, że system działa w trybie PM0
Opóźnienie(10);
//PM1 stan, światła zgaszone
setSleepTimer(1); //Ustaw interwał czasu timera snu na 1 s
sleepTimer_init(); //Włącz timer uśpienia przerwany
led1 = LED_OFF; PowerMode(1); //Ustaw tryb zasilania na PM1
//Po 1 sekundach PM1 wchodzi w PM0, zapala się i opóźnia
led1 = LED_ON; Opóźnienie(50);
//PM2, światła zgaszone
setSleepTimer(2); //Ustaw interwał czasu dla timera snu na 2 sekundy
led1 = LED_OFF; PowerMode(2); //Ustaw tryb zasilania na PM2
//Po 2 sekundach PM2 wchodzi w PM0, zapala się i opóźnia
led1=0; Opóźnienie(50);
//PM3, światła zgaszone
io_init(); //Inicjalizacja zewnętrznych przerwań
led1 = LED_OFF; PowerMode(3); //Ustaw tryb zasilania na PM3
//Gdy wystąpi zewnętrzne przerwanie, PM3 wchodzi w PM0 i zapala się
led1 = LED_ON;
podczas gdy(1);
}
[url=] [/url]
Procedury obsługi przerwań[url=] [/url]
/*Program obsługi zewnętrznych przerwań -------------------------------------------------------*/
#pragmawektor = P0INT_VECTOR __interruptpustkaP0_ISR(pustka)
{ EA =0; //Brama jest przerwana
Opóźnienie(50);
jeśli((P0IFG &0x02) >0) //są przerwane
{ P0IFG &= ~0x02; //P0.1 Znak przerwania clear0
} P0IF =0; //P0 znak przerwania clear0
EA =1; //Przerwanie otwarte
}
/*Timer uśpienia przerywa programy serwisowe -------------------------------------------------------*/
#pragmawektor= ST_VECTOR __interruptpustkasleepTimer_IRQ(pustka)
{ EA=0; //Brama jest przerwana
STIF=0; //Znacznik przerwania timera snu jest czysty 0
EA=1; //Przerwanie otwarte
}
[url=] [/url]
Jak użyć timera uśpienia, aby obudzić system, można podsumować następująco:Otwórz przerwanie timera uśpienia→ ustaw interwał czasu uśpienia → tryb zasilania (Uwaga: krok "Ustaw interwał czasu uśpienia" musi być przed "Ustaw tryb zasilania", ponieważ system nie będzie kontynuował wykonywania programu po wejściu w tryb uśpienia) Następnie skupmy się na podfunkcji ustalającej interwał timera snu:setSleepTimer Przede wszystkim krótkie wprowadzenie do timera snu: działa on dalej32,768kHzof24. miejsceTimer, gdy system działaOprócz PM3We wszystkich trybach zasilania timer uśpienia będzie następującyNieprzerwana praca。 Rejestry używane przez timery uśpienia to:ST0,ST1,ST2。 Poniżej znajduje się szczegółowe wprowadzenie do jego funkcji z chińskiego podręcznika CC2430:
Widać, że ich funkcje obejmują dwa aspekty:Przeczytaj,Napisz。 Przeczytaj: Używany do odczytu wartości licznika bieżącego timera, czyli kolejności, w jakiej należy wykonać odczyty:Czytaj ST0 → Czytaj ST1 → Czytaj ST2 Napisz: Używany do ustawienia wartości porównawczej timera (gdy wartość licznika = wartość porównawcza, następuje przerwanie), kolejność zapisu musi być następująca:Zapisz ST2 → zapisz ST1 → zapisz ST0 OK, wyjaśnijmy to w połączeniu z kodem źródłowym: (1) Najpierw zdefiniuj nieznakomicie długą zmienną (32-bitową) sleepTimer, aby otrzymać aktualną wartość licznika sleep: NiepodpisanydługiesleepTimer =0;
sleepTimer |= ST0; //Uzyskaj wartość liczną aktualnego timera snu
sleepTimer |= (bez znakudługie)ST1 <<8; sleepTimer |= (bez znakudługie)ST2 <<16;
(2) Następnie dodaj wymagany przedział czasowy: sleepTimer += ((unsigneddługie)sec* (niepodpisanydługie)32768); //Do tego wymagany czas trwania
Oto krótkie wyjaśnienie: Dlaczego 1 oznacza 32768? Ponieważ timer działa poniżej 32,768kHz, za każdą dodaną 1 sekundę do timera potrzeba 1/32768 s; Dodaj 32768 i będziesz potrzebował 1; (3) Na koniec wartość sleepTimer jest używana jako wartość porównawcza timera: ST2 = (bez znakuchar(SleepTimer >>16); //Ustaw wartość porównawczą timera snu
ST1 = (bez znakuchar(SleepTimer >>8); ST0 = (bez znakuchar)sleepTimer;
W ten sposób możesz skutecznie ustawić czas działania timera~ (Uwaga: Jeśli chodzi o pozostałe części kodu źródłowego, uważam, że w połączeniu z szczegółowymi adnotacjami łatwo to zrozumieć i nie będę tego tu powtarzać) (4) Wyniki eksperymentalneUruchamiając program, obserwując LED1, zjawisko wygląda następująco:LED1 (czyli włączony-> wyłączony raz raz),, po 1 sekundzie znów po sekundach, potem pozostaje wyłączony, a następnie naciska S1, LED1 się zapala. Zjawisko eksperymentalne jest całkowicie zgodne z oczekiwaniem, Over~
3. PodsumowanieOch~ Po dwóch dniach wolnego czasu w końcu zdobyłem ten dziennik. Naprawdę odkryłem, że pisanie bloga, zwłaszcza "przyjaznego czytelnikowi" wpisu, to naprawdę fizyczna praca: rygor, estetyka, logika... Wszystko sprowadza się do rozwagi. Za każdym razem, gdy publikuję kod, wydaje mi się, że jest za długi, ale niechętnie używam narzędzia do składania, które jest dołączone do ogrodu bloga. Dlatego w tym wpisie na blogu autor wstępnie dodał kilka elementów JQuery, aby zapewnić płynne składanie kodu, i wciąż pozostaje pewne poczucie satysfakcji, hehe (JQuery rookie, nie śmiej się z mistrza~). Ale nie wiem, czy to naprawdę poprawia czytelność artykułu, a czytelnicy i znajomi są mile widziani, by komentować :) W tym miesiącu autor naprawdę postanowił zakorzenić się w ogrodzie blogowym, więc spędziłam dużo wolnego czasu na pisaniu wpisów na blogu. Kiedy pisałem bloga po raz pierwszy, choć komentarzy było niewiele, większość logów miała wskaźnik klikania przekraczający 500, co było dla mnie małym zachętą! Publikowanie treści o mikrokontrolerach w ogrodzie blogowym wymaga odwagi, ale ja się tego nie zajmę~ Dziewięć wpisów na blogu od początku do dziś koncentruje się na wykorzystaniu podstawowych modułów sprzętowych na chipie CC2430. Jak dotąd przejrzeliśmy właściwie większość peryferiów CC2430, ale wciąż są takie rzeczy jak dostęp do Flash, generator liczb losowych, koprocesor AES, komunikacja RF itd., których nie poruszaliśmy. Jednak podróż Zigbee nie jest zakończona, a autor zamierza selektywnie uzupełnić te braki w kolejnym temacie (implementacja protokołu Z-Stack). W następnym wpisie na blogu planuję zakończyć pierwszą podróż Zigbee nieco bardziej kompleksowym i rozszerzonym eksperymentem – "systemem monitorowania temperatury" oraz wyjaśnić, jak kompleksowo zastosować wcześniej zdobyte punkty wiedzy. W rzeczywistości nie kwalifikuje się do nazywania "WyjaśnienieJako początkujący autor ma nadzieję tylko wzajemnie się wspierać i wspólnie robić postępy w procesie pisania doktoratu! </n; i++)
|