|
1. Verbindung der oberen und unteren Ebenen In diesem Artikel werden wir die Schlaffunktion und die Aufwachungsmethode von CC2430 besprechen. Im tatsächlichen Einsatz wird der CC2430-Knoten in der Regel mit Batterien versorgt, daher ist die Steuerung seines Stromverbrauchs entscheidend. Im Folgenden ein Auszug aus dem chinesischen Handbuch CC2430 zur Einführung der vier Energieverbrauchsmodi des CC2430:
Wie Sie in der obigen Tabelle sehen können, hat der CC2430 insgesamt 4 Leistungsmodi:PM0(ganz wach),PM1(etwas schläfrig),PM2(halb wach und halb schlafend),PM3(Sehr fest schlafend). Je weiter hinten, desto mehr Funktionen werden ausgeschaltet und der Stromverbrauch wird immer niedriger. Die Konversionsbeziehung zwischen ihnen ist wie folgt:
SetzenPM1、PM2Wach aufPM0Es gibt drei Möglichkeiten: Zurücksetzen, externe Unterbrechung, Unterbrechung des Schlaftimers; Aber hierPM3Wach aufPM0, es gibt nur zwei Wege: Zurücksetzen, externer Interrupt (das liegt daran, dass inPM3Alle Oszillatoren hörten auf zu funktionieren, und natürlich war der Schlaftimer ausgeschaltet~) Lassen Sie uns ein kleines Experiment durchgehen, um vorzustellen, wie man in den Schlafmodus geht und aufwachtPM0Staat. 2. Systematischer Schlaf und unterbrochene Aufwachungsexperimente(1) Einführung in das ExperimentSysteminitialisierung, inPM0
→ eintretenPM1
→ Nach 1 Sekunden vom Schlaftimer aufwachenPM0
→ eintretenPM2
→ wurde nach zwei Sekunden vom Schlaftimer gewecktPM0
→ eintretenPM3
→ Warte, bis die Taste S1 gedrückt wird, was einen externen Interrupt auslöst und aufwachtPM0
(2) Programmflussdiagramm
(Hinweis: Das abgerundete Feld im obigen Bild zeigt den Gesundheitszustand des Systems an.)
(3) Experimenteller Quellcode und Analyse (Die folgenden Kästchen können angeklickt werden~)Header-Datei und Makro-Definition[url=]
[/url]
/* Experimentelle Beschreibung: Experiment mit unterbrochenem Aufwachen, das Wachheit in drei Schlafmodi einführt
*/
#include #define LED_ON 0 #define LED_OFF 1#defineled1 P1_0
#defineled2 P1_1
#defineled3 P1_2
#defineled4 P1_3 [url=] [/url]
Teilfunktionen[url=] [/url]
/*Systemtakt-Initialisierung -------------------------------------------------------*/
Leerextal_init(Leere)
{ SCHLAF &= ~0x04; //Alle sind mit Strom versorgt
während(! (SCHLAF &0x40)); //Der Kristalloszillator ist eingeschaltet und stabil
CLKCON &= ~0x47; //Wählen Sie einen 32-MHz-Kristalloszillator
SCHLAF |=0x04;
}
/*LED-Initialisierung -------------------------------------------------------*/
Leereled_init(Leere)
{ P1SEL =0x00; //P1 ist der normale I/O-Port
P1DIR |=0x0F; //P1.0 P1.1 P1.2 P1.3 Ausgang
led1 = LED_OFF; //Schalten Sie alle LEDs aus.
led2 = LED_OFF; led3 = LED_OFF; led4 = LED_OFF;
}
/*Externe Interrupt-Initialisierung -------------------------------------------------------*/
Leereio_init(Leere)
{ P0INP &= ~0X02; //P0.1 hat Pull-up und Pull-down
EA =1; //Vollständige Unterbrechung erlaubt
IEN1 |= 0X20; //P0IE = 1, P0-Interrupts aktivieren
PICTL |= 0X09; //P0.1 erlaubt Interrupts, Drop-Edge-Triggers
P0IFG &= ~0x02; //P0.1 Interrupt Mark clear0
}
/*Initialisierung von Schlaftimer-Interrupts -------------------------------------------------------*/
LeeresleepTimer_init(Leere)
{ STIF=0; //Die Unterbrechungsmarke für den Schlaftimer ist klar 0
STIE=1; //Einschalten des Schlaftimers unterbrochen
EA=1; //Öffne die totale Unterbrechung
}
/*Stelle das geplante Intervall für den Schlaftimer ein -------------------------------------------------------*/
LeeresetSleepTimer (unsignedIntsec)
{ UnsigniertlangsleepTimer =0;
sleepTimer |= ST0; //Erhalten Sie den Zählwert des aktuellen Schlaftimers
sleepTimer |= (unsignedlang)ST1 <<8; sleepTimer |= (unsignedlang)ST2 <<16;
sleepTimer += ((nicht signiert)lang)sec * (unsigniert)lang)32768); //Plus die erforderliche Zeitdauer
ST2 = (unsigniert)char(sleepTimer >>16); //Stellen Sie den Vergleichswert des Schlaftimers ein
ST1 = (unsigniert)char(sleepTimer >>8); ST0 = (nicht signiert)char)sleepTimer;
}
/*Schalten Sie den Energiemodus -------------------------------------------------------*/
LeerePowerMode (unsignedcharModus)
{
wenn(Modus <4) { SCHLAF &=0xfc; //SLEEP.MODE auf 0 löschen
SLEEP |= Modus; //Schalten Sie den Energiemodus
PCON |=0x01; //Aktivieren Sie diesen Energiemodus
}
}
/*Verzögerungsfunktion -------------------------------------------------------*/
LeereVerzögerung (nicht unterzeichnet)Intn)
{ UnsigniertInti,j;
für(i=0; i<n; i++)
für(j=0; j <1000; j++);
}
[url=] [/url]
Hauptfunktion[url=] [/url]
/*Hauptfunktion -------------------------------------------------------*/
Leeremain(Leere)
{ xtal_init(); led_init();
//PM0-Status, Licht an und Verzögerung
led1 = LED_ON; //Die Helligkeit LED1 zeigt an, dass das System im PM0-Modus arbeitet
Verzögerung(10);
//PM1-Zustand, Licht aus
setSleepTimer(1); //Stelle das Zeitintervall des Schlaftimers auf 1 Sekunden ein
sleepTimer_init(); //Einschalten des Schlaftimers unterbrochen
led1 = LED_OFF; PowerMode(1); //Stellen Sie den Energiemodus auf PM1 ein
//Nach 1 Sekunden geht PM1 in PM0 ein, leuchtet auf und verzögert sich
led1 = LED_ON; Verzögerung(50);
//PM2, Licht aus
setSleepTimer(2); //Stelle das Zeitintervall für den Schlaftimer auf 2 Sekunden ein
led1 = LED_OFF; PowerMode(2); //Stellen Sie den Energiemodus auf PM2 ein
//Nach 2 Sekunden tritt PM2 in PM0 ein, leuchtet auf und verzögert sich
led1=0; Verzögerung(50);
//PM3, Licht aus
io_init(); //Externe Interrupts initialisieren
led1 = LED_OFF; PowerMode(3); //Stell den Energiemodus auf PM3 ein
//Wenn eine externe Unterbrechung auftritt, tritt PM3 in PM0 ein und leuchtet auf
led1 = LED_ON;
während(1);
}
[url=] [/url]
Interrupt-Service-Prozeduren[url=] [/url]
/*Externes Interrupt-Service-Programm -------------------------------------------------------*/
#pragmaVektor = P0INT_VECTOR __interruptLeereP0_ISR(Leere)
{ EA =0; //Das Tor wird unterbrochen
Verzögerung(50);
wenn((P0IFG &0x02) >0) //Die Schlüssel werden unterbrochen
{ P0IFG &= ~0x02; //P0.1 Interrupt Mark clear0
} P0IF =0; //P0-Unterbrechungsmarkierung clear0
EA =1; //Offene Unterbrechung
}
/*Schlaftimer unterbricht Serviceprogramme -------------------------------------------------------*/
#pragmaVektor= ST_VECTOR __interruptLeeresleepTimer_IRQ(Leere)
{ EA=0; //Das Tor wird unterbrochen
STIF=0; //Die Unterbrechungsmarke für den Schlaftimer ist klar 0
EA=1; //Offene Unterbrechung
}
[url=] [/url]
Wie man einen Schlaftimer verwendet, um das System aufzuwecken, lässt sich wie folgt zusammenfassen:Öffne den Schlaftimer-Interrupt → setze das Zeitintervall des Schlaftimers → setze den Energiemodus (Hinweis: Der Schritt "Set the Sleep Timer Interval" muss vor "Power Mode einstellen" erfolgen, da das System das Programm nach dem Ruhezustand nicht weiter ausführt.) Als Nächstes konzentrieren wir uns auf die Unterfunktion, die das Intervall des Schlaftimers festlegt:setSleepTimer Zunächst eine kurze Einführung in den Schlaftimer: Er läuft auf32,768kHzvon24. PlatzTimer, wenn das System läuftZusätzlich zu PM3In allen Energiemodi ist der SchlaftimerUnunterbrochener Betrieb。 Die von Schlaftimern verwendeten Register sind:ST0,ST1,ST2。 Im Folgenden finden Sie eine ausführliche Einführung in ihre Funktionen aus dem chinesischen Handbuch CC2430:
Man sieht, dass ihre Funktionen zwei Aspekte umfassen:Lesen,schreib。 Lesen: Verwendet zum Auslesen des Zählwerts des aktuellen Timers, die Reihenfolge, in der die Messwerte befolgt werden müssen:ST0 lesen → ST1 lesen → ST2 lesen schreib: Zur Festlegung des Vergleichswerts des Timers verwendet (wenn der Zählwert = Vergleichswert des Timers gilt, tritt ein Interrupt auf), muss die Schreibreihenfolge folgen:Schreibe ST2 → schreibe ST1 → schreibe ST0 Okay, erklären wir es in Kombination mit dem Quellcode: (1) Definieren Sie zunächst einen unsigned long variable (32-Bit) sleepTimer, der den aktuellen Zählwert des Sleeptimers empfängt: UnsigniertlangsleepTimer =0;
sleepTimer |= ST0; //Erhalten Sie den Zählwert des aktuellen Schlaftimers
sleepTimer |= (unsignedlang)ST1 <<8; sleepTimer |= (unsignedlang)ST2 <<16;
(2) Dann das erforderliche Zeitintervall hinzufügen: sleepTimer += ((nicht signiert)lang)sec * (unsigniert)lang)32768); //Plus die erforderliche Zeitdauer
Hier eine kleine Erklärung: Warum stehen 1er für 32768? Da der Timer unter 32,768 kHz arbeitet, benötigt er 1/32768 s für jedes 1, das zum Timer hinzugefügt wird; Fügt man 32768 hinzu, braucht man 1s; (3) Schließlich wird der Wert von sleepTimer als Vergleichswert des Timers verwendet: ST2 = (unsigniert)char(sleepTimer >>16); //Stellen Sie den Vergleichswert des Schlaftimers ein
ST1 = (unsigniert)char(sleepTimer >>8); ST0 = (nicht signiert)char)sleepTimer;
Auf diese Weise kannst du erfolgreich die Zeitperiode des Timers einstellen~ (Hinweis: Was die anderen Teile des Quellcodes betrifft, glaube ich, dass man in Kombination mit detaillierten Anmerkungen leicht nachvollziehen kann, und ich werde das hier nicht wiederholen.) (4) VersuchsergebnisseLäuft das Programm und beobachte LED1, das Phänomen ist:LED1 blinkt (also ein- > aus), blinkt nach 1 Sekunden erneut, blinkt nach 2 Sekunden erneut, bleibt dann aus, und dann drückt man S1, dann leuchtet LED1 auf. Das experimentelle Phänomen entspricht vollkommen der Erwartung, Over~
3. FazitOh~ Nachdem ich mir zwei Tage Freizeit genommen habe, habe ich endlich dieses Protokoll bekommen. Ich habe wirklich festgestellt, dass das Schreiben eines Blogs, besonders eines "leserfreundlichen" Blogbeitrags, tatsächlich eine körperliche Aufgabe ist: Strenge, Ästhetik, Logik... Es geht vor allem um Rücksicht. Jedes Mal, wenn ich den Code poste, denke ich, dass er zu lang ist, aber ich zögere, das Faltwerkzeug zu verwenden, das mit dem Bloggarten geliefert wird. Deshalb hat der Autor in diesem Blogbeitrag vorsichtig einige JQuery-Elemente hinzugefügt, um eine reibungslose Faltung des Codes zu erreichen, und es gibt immer noch ein kleines Gefühl der Erfolgsbereitschaft, hehe (JQuery-Anfänger, lach nicht über den Master~). Aber ich weiß nicht, ob das wirklich die Lesbarkeit des Artikels verbessert, und Leser und Freunde sind herzlich eingeladen, zu kommentieren :) Diesen Monat hat sich der Autor wirklich entschieden, im Bloggarten Fuß zu fassen, also habe ich viel Freizeit damit verbracht, Blogbeiträge zu schreiben. Als ich zum ersten Mal einen Blog schrieb, gab es zwar wenige Kommentare, aber die meisten Logs hatten eine Klickrate von über 500, was für mich eine kleine Ermutigung war! Es erfordert Mut, Inhalte über Mikrocontroller im Blog Garden zu veröffentlichen, aber ich werde dabei bleiben~ Die neun Blogbeiträge von Anfang bis heute konzentrieren sich auf die Verwendung grundlegender Hardwaremodule auf dem CC2430-Chip. Bisher haben wir im Grunde die meisten Peripheriegeräte des CC2430 durchgearbeitet, aber es gibt immer noch Dinge wie Flash-Zugriff, Zufallszahlengenerator, AES-Koprozessor, RF-Kommunikation usw., die bisher nicht behandelt wurden. Die Zigbee-Reise ist jedoch noch nicht vorbei, und der Autor beabsichtigt, diese Auslassungen im nächsten Thema (Implementierung des Z-Stack-Protokolls) selektiv auszufüllen. Im nächsten Blogbeitrag plane ich, Zigbees erste Reise mit einem etwas umfassenderen und umfangreicheren Experiment – dem "Temperaturüberwachungssystem" – zu beenden und zu erklären, wie man die zuvor gelernten Wissenspunkte umfassend anwenden kann. Tatsächlich ist es nicht qualifiziert, als " bezeichnet zu werdenErklärungAls Anfänger hofft der Autor nur, sich gegenseitig zu ermutigen und gemeinsam Fortschritte im Prozess der Promotion zu machen! </n; i++)
|