|
1. Reliant les niveaux supérieur et inférieur Dans cet article, nous allons discuter de la fonction de sommeil et de la méthode d’éveil de CC2430. En usage réel, le nœud CC2430 est généralement alimenté par des batteries, donc le contrôle de sa consommation d’énergie est crucial. Voici un extrait du manuel chinois du CC2430 pour l’introduction des 4 modes de consommation d’énergie du CC2430 :
Comme vous pouvez le voir dans le tableau ci-dessus, le CC2430 dispose d’un total de 4 modes de puissance :PM0(complètement éveillé),PM1(un peu somnolent),PM2(à moitié réveillé et à moitié endormi),PM3(Dormir très fort). Plus on recule, plus les fonctions sont désactivées, et la consommation d’énergie diminue. La relation de conversion entre eux est la suivante :
putPM1、PM2Réveillez-vousPM0, il existe trois façons : réinitialisation, interruption externe, interruption du minuteur de sommeil ; Mais mettez-lePM3Réveillez-vousPM0, il n’y a que deux façons : réinitialiser, interruption externe (cela s’explique par le fait que dansPM3Tous les oscillateurs ont cessé de fonctionner, et bien sûr le minuteur de veille a été éteint~) Faisons une petite expérience pour expliquer comment entrer en mode veille et comment se réveillerPM0État. 2. Expériences de sommeil systématique et de réveil interrompu(1) Introduction à l’expérienceInitialisation système, dansPM0
→ entrerPM1
→ Réveillez-vous avec le minuteur de sommeil après 1 secondePM0
→ entrerPM2
→ a été réveillé par le minuteur de sommeil après 2 secondesPM0
→ entrerPM3
→ Attendez que la touche S1 soit pressée, déclenchant une interruption externe et réveillantPM0
(2) Organigramme de programme
(Note : La case arrondie sur l’image ci-dessus indique l’état de santé du système)
(3) Code source expérimental et analyse (Les cases suivantes peuvent être cliquées~)Définition de fichier d’en-tête et de macro[url=]
[/url]
/* Description expérimentale : Expérience de sommeil interrompu réveil, qui introduit l’éveil dans trois modes de sommeil
*/
#include #define LED_ON 0 #define LED_OFF 1#definemené1 P1_0
#defineLed2 P1_1
#defineLed3 P1_2
#defineLead4 P1_3 [url=] [/url]
Sous-fonctions[url=] [/url]
/*Initialisation de l’horloge système -------------------------------------------------------*/
vidextal_init(vide)
{ SOMMEIL &= ~0x04; //Tous sont alimentés
tandis que(! (SOMMEIL &0x40)); //L’oscillateur à cristal est allumé et stable
CLKCON &= ~0x47; //Choisissez un oscillateur à cristal de 32 MHz
SOMMEIL |=0x04;
}
/*Initialisation des LED -------------------------------------------------------*/
videled_init(vide)
{ P1SEL =0x00; //P1 est le port d’E/S normal
P1DIR |=0x0F; //Sortie P1.0 P1.1 P1.2 P1.3
mené1 = LED_OFF ; //Éteignez toutes les LED
mené2 = LED_OFF ; mené3 = LED_OFF ; mené4 = LED_OFF ;
}
/*Initialisation d’interruption externe -------------------------------------------------------*/
videio_init(vide)
{ P0INP &= ~0X02; //P0.1 comporte un pull-up et un pull-down
EA =1; //Interruption totale autorisée
IEN1 |= 0X20; //P0IE = 1, P0 interruptions activées
PICTL |= 0X09; //P0.1 permet les interruptions, les déclencheurs à bord de chute
P0IFG &= ~0x02; //P0.1 Marque d’interruption clear0
}
/*Initialisation de l’interruption du minuteur de veille -------------------------------------------------------*/
videsleepTimer_init(vide)
{ STIF=0; //Le marqueur d’interruption du minuteur de sommeil est clair 0
STIE=1; //Allumez le minuteur de veille interrompu
EA=1; //Ouvrir l’interruption totale
}
/*Réglez l’intervalle programmé pour le minuteur de sommeil -------------------------------------------------------*/
videsetSleepTimer(non signéintsec)
{ non signélongSleepTimer =0;
sleepTimer |= ST0 ; //Obtenez la valeur de comptage du minuteur de sommeil actuel
sleepTimer |= (non signélong)ST1 <<8; sleepTimer |= (non signélong)ST2 <<16;
sleepTimer += ((non signélong)sec * (non signélong)32768); //Plus la durée de chronométrage requise
ST2 = (non signéChar(sleepTimer >>16); //Définissez la valeur de comparaison du minuteur de sommeil
ST1 = (non signéChar(sleepTimer >>8); ST0 = (non signéChar)sleepTimer ;
}
/*Sélectionner le mode d’alimentation -------------------------------------------------------*/
videPowerMode(non signéCharmode)
{
si(mode <4) { SOMMEIL &=0xfc; //Effacer SLEEP.MODE à 0
SOMMEIL |= mode ; //Sélectionner le mode d’alimentation
PCON |=0x01; //Activez ce mode d’alimentation
}
}
/*Fonction de délai -------------------------------------------------------*/
videDélai (non signéintn)
{ non signéinti,j ;
pour(i=0; i<n ; i++)
pour(j=0; j <1000; j++) ;
}
[url=] [/url]
Fonction principale[url=] [/url]
/*Fonction principale -------------------------------------------------------*/
videmain(vide)
{ xtal_init() ; led_init() ;
//État PM0, lumière allumée et délai
mené1 = LED_ON ; //LED de luminosité 1 indique que le système fonctionne en mode PM0
Délai (10);
//État PM1, lumières éteintes
setSleepTimer(1); //Réglez l’intervalle de temps du minuteur de sommeil à 1 seconde
sleepTimer_init() ; //Allumez le minuteur de veille interrompu
mené1 = LED_OFF ; PowerMode(1); //Réglez le mode d’alimentation sur PM1
//Après 1 seconde, PM1 entre en PM0, s’allume et retarde
mené1 = LED_ON ; Délai (50);
//PM2, lumières éteintes
setSleepTimer(2); //Réglez l’intervalle de temps pour le minuteur de sommeil à 2 secondes
mené1 = LED_OFF ; PowerMode(2); //Réglez le mode alimentation sur PM2
//Après 2 secondes, PM2 entre en PM0, s’allume et retarde
mené1=0; Délai (50);
//PM3, extinction des feux
io_init() ; //Initialisation des interruptions externes
mené1 = LED_OFF ; PowerMode(3); //Réglez le mode d’alimentation sur PM3
//Lorsqu’une interruption externe survient, PM3 entre en PM0 et s’allume
mené1 = LED_ON ;
tandis que(1);
}
[url=] [/url]
Procédures de service d’interruption[url=] [/url]
/*Programme de service d’interruption externe -------------------------------------------------------*/
#pragmavecteur = P0INT_VECTOR __interruptvideP0_ISR(vide)
{ EA =0; //La porte est interrompue
Délai (50);
si((P0IFG &0x02) >0) //Les touches sont interrompues
{ P0IFG &= ~0x02; //P0.1 Marque d’interruption clear0
} P0IF =0; //Marque d’interruption P0 clear0
EA =1; //Interruption ouverte
}
/*Le minuteur de veille interrompt les programmes de service -------------------------------------------------------*/
#pragmavecteur = ST_VECTOR __interruptvidesleepTimer_IRQ(vide)
{ EA=0; //La porte est interrompue
STIF=0; //Le marqueur d’interruption du minuteur de sommeil est clair 0
EA=1; //Interruption ouverte
}
[url=] [/url]
Comment utiliser un minuteur de sommeil pour réveiller le système peut se résumer ainsi :Ouvrir l’interruption du minuteur de veille → régler l’intervalle de timing du minuteur de sommeil → régler le mode alimentation (Note : l’étape « Définir l’intervalle du minuteur de veille » doit être avant « Définir le mode alimentation », car le système ne continuera pas à exécuter le programme après être entré en veille) Ensuite, concentrons-nous sur la sous-fonction qui fixe l’intervalle de minuterie de sommeil :setSleepTimer Tout d’abord, une brève introduction au minuteur de sommeil : il fonctionne32,768kHzde24e placeMinuteur, lorsque le système tourneEn plus de PM3Dans tous les modes d’alimentation, le minuteur de veille seraFonctionnement ininterrompu。 Les registres utilisés par les minuteurs de sommeil sont :ST0,ST1,ST2。 Voici une introduction détaillée à ses fonctions tirée du manuel chinois CC2430 :
On peut voir que leurs fonctions incluent deux aspects :Lire,Écrire。 Lire: Utilisé pour lire la valeur de comptage du minuteur courant, l’ordre dans lequel les lectures doivent être suivies :Lisez ST0 → lisez ST1 → lisez ST2 Écrire: Utilisé pour définir la valeur de comparaison du minuteur (lorsque la valeur du compte = valeur de comparaison, une interruption se produit), l’ordre d’écriture doit suivre :Écrire ST2 → écrire ST1 → écrire ST0 OK, expliquons cela en combinaison avec le code source : (1) D’abord, définir un timeTimer de sommeil à variable longue non signée (32 bits) pour recevoir la valeur de comptage actuelle du timer de sommeil : non signélongSleepTimer =0;
sleepTimer |= ST0 ; //Obtenez la valeur de comptage du minuteur de sommeil actuel
sleepTimer |= (non signélong)ST1 <<8; sleepTimer |= (non signélong)ST2 <<16;
(2) Ajoutez ensuite l’intervalle de temps requis : sleepTimer += ((non signélong)sec * (non signélong)32768); //Plus la durée de chronométrage requise
Voici une petite explication : Pourquoi 1s représente-t-il 32768 ? Comme le minuteur fonctionne en dessous de 32,768 kHz, il faut 1/32768 s pour chaque 1 ajouté au minuteur ; Ajoutez 32768, et vous aurez besoin de 1 ; (3) Enfin, la valeur de sleepTimer est utilisée comme valeur de comparaison du minuteur : ST2 = (non signéChar(sleepTimer >>16); //Définissez la valeur de comparaison du minuteur de sommeil
ST1 = (non signéChar(sleepTimer >>8); ST0 = (non signéChar)sleepTimer ;
De cette façon, vous pouvez définir avec succès la période temporelle du minuteur~ (Note : Quant aux autres parties du code source, je crois qu’avec des annotations détaillées, vous pouvez facilement comprendre, et je ne le répéterai pas ici) (4) Résultats expérimentauxEn exécutant le programme, en observant LED1, le phénomène est :LED1 clignote (c’est-à-dire allumé-> éteint 1 fois), clignote à nouveau après 1 seconde, clignote à nouveau après 2 secondes, puis reste éteint, puis appuie sur S1, LED1 s’allume. Le phénomène expérimental est tout à fait cohérent avec l’attente : Terminé~
3. ConclusionOh~ Après avoir pris deux jours de temps libre, j’ai enfin reçu ce journal. J’ai vraiment découvert que rédiger un blog, surtout un article « convivial pour les lecteurs », est en effet un travail physique : rigueur, esthétique, logique... Tout est une question de considération. Chaque fois que je publie le code, je trouve qu’il est trop long, mais j’hésite à utiliser l’outil pliant fourni avec le blog garden. Ainsi, dans cet article de blog, l’auteur a ajouté timidement quelques éléments JQuery pour obtenir un pliage fluide du code, et il y a encore un petit sentiment d’accomplissement, hehe (JQuery rookie, ne riez pas du maître~). Mais je ne sais pas si cela améliore vraiment la lisibilité de l’article, et lecteurs et amis sont invités à commenter :) Ce mois-ci, l’auteure a vraiment décidé de s’implanter dans le jardin du blog, alors j’ai passé beaucoup de temps libre à écrire des articles de blog. Lorsque j’ai écrit un blog pour la première fois, bien qu’il y ait eu peu de commentaires, la plupart des logs affichaient un taux de clics de plus de 500, ce qui m’a un peu encouragé ! Il faut du courage pour publier du contenu sur les microcontrôleurs dans le jardin des blogs, mais je m’y tiendra~ Les neuf articles de blog, du début à aujourd’hui, se concentrent sur l’utilisation de modules matériels de base sur la puce CC2430. Jusqu’à présent, nous avons essentiellement passé en revue la plupart des périphériques du CC2430, mais il reste encore des éléments comme l’accès Flash, le générateur de nombres aléatoires, le coprocesseur AES, la communication RF, etc., qui n’ont pas été abordés. Cependant, le parcours Zigbee n’est pas terminé, et l’auteur a l’intention de combler sélectivement ces omissions dans le prochain sujet (implémentation du protocole Z-Stack). Dans le prochain article de blog, je prévois de conclure le premier voyage de Zigbee par une expérience un peu plus complète et approfondie – le « système de surveillance de la température », et d’expliquer comment appliquer de manière exhaustive les points de connaissance appris plus tôt. En fait, il n’est pas qualifié pour être appelé «ExplicationEn tant que débutant, l’auteur espère seulement s’encourager mutuellement et progresser ensemble dans le processus d’écriture d’un doctorat ! </n ; i++)
|