|
1. Conexión entre los niveles superior e inferior En este artículo, hablaremos sobre la función de sueño y el método de despertar de CC2430. En el uso real, el nodo CC2430 suele funcionar con baterías, por lo que el control de su consumo de energía es crucial. A continuación se muestra un extracto del manual chino del CC2430 sobre la introducción de los 4 modos de consumo energético del CC2430:
Como puedes ver en la tabla anterior, el CC2430 tiene un total de 4 modos de potencia:PM0(completamente despierto),PM1(un poco somnolienta),PM2(medio despierto y medio dormido),PM3(Durmiendo muy profundamente). Cuanto más atrás, más funciones se desactivan y el consumo de energía es cada vez menor. La relación de conversión entre ellos es la siguiente:
putPM1、PM2DespiertaPM0, hay tres formas: reinicio, interrupción externa, interrupción del temporizador de sueño; Pero ponPM3DespiertaPM0, solo hay dos maneras: reinicio, interrupción externa (esto se debe a que enPM3Todos los osciladores dejaron de funcionar y, por supuesto, el temporizador de suspensión estaba apagado~) Vamos a hacer un pequeño experimento para introducir cómo entrar en modo de suspensión y cómo despertarsePM0estado. 2. Experimentos sistemáticos de sueño y despertar interrumpida(1) Introducción al experimentoInicialización del sistema, enPM0
→ entrarPM1
→ Despierta con el temporizador de sueño después de 1 segundoPM0
→ entrarPM2
→ despertaba el contador de sueño tras 2 segundosPM0
→ entrarPM3
→ Esperar a que se pulse la tecla S1, activando una interrupción externa y despertandoPM0
(2) Diagrama de flujo del programa
(Nota: La casilla redondeada en la imagen anterior indica el estado de salud del sistema)
(3) Código fuente experimental y análisis (Se pueden hacer clic en las siguientes casillas~)Encabezado y definición de macros[url=]
[/url]
/* Descripción experimental: Experimento de sueño interrumpido y despertar, que introduce la vigilia en tres modos de sueño
*/
#include #define LED_ON 0 #define LED_OFF 1#definelideró1 P1_0
#defineled2 P1_1
#defineLed3 P1_2
#defineled4 P1_3 [url=] [/url]
Subfunciones[url=] [/url]
/*Inicialización del reloj del sistema -------------------------------------------------------*/
Vacíoxtal_init(Vacío)
{ SUEÑO &= ~0x04; //Todos son alimentados
mientras(! (SUEÑO &0x40)); //El oscilador de cristal está encendido y estable
CLKCON &= ~0x47; //Elige un oscilador de cristal de 32MHz
SUEÑO |=0x04;
}
/*Inicialización de LED -------------------------------------------------------*/
Vacíoled_init(Vacío)
{ P1SEL =0x00; //P1 es el puerto normal de E/S
P1DIR |=0x0F; //P1.0 P1.1 P1.2 P1.3 salida
liderado1 = LED_OFF; //Apaga todos los LEDs
liderado2 = LED_OFF; liderado3 = LED_OFF; liderado4 = LED_OFF;
}
/*Inicialización de interrupciones externas -------------------------------------------------------*/
Vacíoio_init(Vacío)
{ P0INP &= ~0X02; //P0.1 tiene pull-up y pull-down
EA =1; //Interrupción total permitida
IEN1 |= 0X20; //P0IE = 1, P0 interrupciones habilitadas
PICTL |= 0X09; //P0.1 permite interrupciones, disparadores de borde descendente
P0IFG &= ~0x02; //P0.1 Marca de interrupción limpia0
}
/*Inicialización de interrupciones del temporizador de suspensión -------------------------------------------------------*/
VacíosleepTimer_init(Vacío)
{ STIF=0; //La marca de interrupción del temporizador de sueño está limpia 0
STIE=1; //Enciende el temporizador de suspensión interrumpido
EA=1; //Abre la interrupción total
}
/*Establece el intervalo programado para el temporizador de sueño -------------------------------------------------------*/
VacíosetSleepTimer(sin signarintsec)
{ sin firmarlargosleepTimer =0;
sleepTimer |= ST0; //Obtén el valor de conteo del cronómetro de sueño actual
sleepTimer |= (sin signolargo)ST1 <<8; sleepTimer |= (sin signolargo)ST2 <<16;
sleepTimer += ((sin signolargo)sec * (sin firmarlargo)32768); //Además de la duración del tiempo requerido
ST2 = (sin signochar(sleepTimer >>16); //Establece el valor de comparación del tiempo de sueño
ST1 = (sin signochar(sleepTimer >>8); ST0 = (sin signochar)sleepTimer;
}
/*Seleccionar Modo de Alimentación -------------------------------------------------------*/
VacíoPowerMode(sin signo)charmodo)
{
si(modo <4) { SUEÑO &=0xfc; //Borrar MODO SUSPENSIÓN a 0
SUSPENSIÓN |= modo; //Seleccionar Modo de Alimentación
PCON |=0x01; //Activa este modo de alimentación
}
}
/*Función de retardo -------------------------------------------------------*/
VacíoRetraso (sin firmarintn)
{ sin firmarinti,j;
para(i=0; i<n; i++)
para(j=0; j <1000; j++);
}
[url=] [/url]
Función principal[url=] [/url]
/*Función principal -------------------------------------------------------*/
Vacíomain(Vacío)
{ xtal_init(); led_init();
//Estado PM0, luz encendida y retraso
lideraba1 = LED_ON; //El LED1 de brillo indica que el sistema funciona en modo PM0
Retraso(10);
//Estado PM1, luces apagadas
setSleepTimer(1); //Establece el intervalo de tiempo del tiempo de sueño a 1 s
sleepTimer_init(); //Enciende el temporizador de suspensión interrumpido
liderado1 = LED_OFF; PowerMode(1); //Configura el modo de alimentación en PM1
//Después de 1s, PM1 entra en PM0, se ilumina y se retrasa
lideraba1 = LED_ON; Retraso(50);
//PM2, luces apagadas
setSleepTimer(2); //Pon el intervalo de tiempo del temporizador de sueño a 2 segundos
liderado1 = LED_OFF; PowerMode(2); //Configura el modo de alimentación en PM2
//Después de 2 segundos, PM2 entra en PM0, se ilumina y se retrasa
lideró1=0; Retraso(50);
//PM3, apaga las luces
io_init(); //Inicializar interrupciones externas
liderado1 = LED_OFF; PowerMode(3); //Configura el modo de alimentación en PM3
//Cuando ocurre una interrupción externa, PM3 entra en PM0 y se ilumina
lideraba1 = LED_ON;
mientras(1);
}
[url=] [/url]
Procedimientos de servicio de interrupción[url=] [/url]
/*Programa de servicio de interrupciones externas -------------------------------------------------------*/
#pragmavector = P0INT_VECTOR __interruptVacíoP0_ISR(Vacío)
{ EA =0; //La puerta se interrumpe
Retraso(50);
si((P0IFG &0x02) >0) //Las teclas se interrumpen
{ P0IFG &= ~0x02; //P0.1 Marca de interrupción limpia0
} P0IF =0; //Marca de interrupción P0 clear0
EA =1; //Interrupción abierta
}
/*El temporizador de suspensión interrumpe los programas de servicio -------------------------------------------------------*/
#pragmavector= ST_VECTOR __interruptVacíosleepTimer_IRQ(Vacío)
{ EA=0; //La puerta se interrumpe
STIF=0; //La marca de interrupción del temporizador de sueño está limpia 0
EA=1; //Interrupción abierta
}
[url=] [/url]
Cómo usar un temporizador de sueño para despertar el sistema se puede resumir de la siguiente manera:Abrir la interrupción del temporizador de suspensión → configurar el intervalo de tiempo del temporizador de sueño → establecer el modo de encendido (Nota: El paso "Establecer el intervalo del temporizador de suspensión" debe estar antes de "Establecer modo de encendido", porque el sistema no continuará ejecutando el programa tras entrar en suspensión) A continuación, centrémonos en la subfunción que establece el intervalo temporizador de sueño:setSleepTimer En primer lugar, una breve introducción al cronómetro de sueño: funciona32,768kHzde24º puestoTemporizador, cuando el sistema está en marchaAdemás de PM3En todos los modos de encendido, el temporizador de suspensión seráFuncionamiento ininterrumpido。 Los registros utilizados por los temporizadores de sueño son:ST0,ST1,ST2。 A continuación se presenta una introducción detallada a sus funciones del manual chino CC2430:
Se puede ver que sus funciones incluyen dos aspectos:Lee,escribe。 Lee: Usado para leer el valor de conteo del temporizador actual, el orden en que deben seguirse las lecturas:Lee ST0 → Lee ST1 → Lee ST2 escribe: Usado para establecer el valor de comparación del temporizador (cuando el valor de conteo = valor de comparación, ocurre una interrupción), el orden de escritura debe seguir:Escribe ST2 → escribe ST1 → escribe ST0 Vale, vamos a explicarlo en combinación con el código fuente: (1) Primero, definir un sleepTimer de variable larga sin signo (32 bits) para recibir el valor actual de conteo del temporizador de sueño: sin firmarlargosleepTimer =0;
sleepTimer |= ST0; //Obtén el valor de conteo del cronómetro de sueño actual
sleepTimer |= (sin signolargo)ST1 <<8; sleepTimer |= (sin signolargo)ST2 <<16;
(2) Luego añade el intervalo de tiempo requerido: sleepTimer += ((sin signolargo)sec * (sin firmarlargo)32768); //Además de la duración del tiempo requerido
Aquí va una pequeña explicación: ¿Por qué el 1s representa 32768? Como el temporizador funciona por debajo de 32,768kHz, tarda 1/32768 s por cada 1 añadido al temporizador; Añade 32768 y necesitarás 1s; (3) Finalmente, el valor de sleepTimer se utiliza como valor de comparación del temporizador: ST2 = (sin signochar(sleepTimer >>16); //Establece el valor de comparación del tiempo de sueño
ST1 = (sin signochar(sleepTimer >>8); ST0 = (sin signochar)sleepTimer;
De este modo, puedes establecer con éxito el periodo de tiempo del temporizador~ (Nota: En cuanto a las otras partes del código fuente, creo que combinadas con anotaciones detalladas se pueden entender fácilmente, y no lo repetiré aquí) (4) Resultados experimentalesEjecutando el programa, observando LED1, el fenómeno es:El LED1 parpadea (es decir, encendido-> apagado 1 vez), parpadea de nuevo tras 1 segundo, parpadea de nuevo tras 2 segundos, luego permanece apagado y después pulsa S1, LED1 se enciende. El fenómeno experimental es completamente coherente con la expectativa, Over~
3. ConclusiónOh~ Después de tomarme 2 días libres, por fin conseguí este registro. Realmente descubrí que escribir un blog, especialmente una entrada "amigable para el lector", es realmente un trabajo físico: rigor, estética, lógica... Todo se basa en la consideración. Cada vez que publico el código, pienso que es demasiado largo, pero me da reparo usar la herramienta plegable que viene con el jardín del blog. Por eso, en esta entrada del blog, el autor añadió tentativamente algunos elementos de JQuery para lograr un plegado fluido del código, y aún así hay una pequeña sensación de logro, jeje (JQuery novato, no te rías del maestro~). Pero no sé si esto realmente mejora la legibilidad del artículo, y lectores y amigos están invitados a comentar :) Este mes, la autora realmente decidió echar raíces en el jardín del blog, así que pasé mucho tiempo libre escribiendo entradas para el blog. Cuando escribí un blog por primera vez, aunque hubo pocos comentarios, la mayoría de los registros tenían una tasa de clics superior a 500, ¡lo cual fue un pequeño aliento para mí! Hace falta valor para publicar contenido sobre microcontroladores en el jardín de blogs, pero me mantendré firme~ Las nueve entradas del blog desde el principio hasta la actualidad se centran en el uso de módulos básicos de hardware en el chip CC2430. Hasta ahora, básicamente hemos revisado la mayoría de los periféricos del CC2430, pero aún hay cosas como el acceso Flash, el generador de números aleatorios, el coprocesador AES, la comunicación RF, etc., que no se han tocado. Sin embargo, el viaje con Zigbee no ha terminado, y el autor pretende cubrir selectivamente estas omisiones en el siguiente tema (implementación del protocolo Z-Stack). En la próxima entrada del blog, planeo terminar el primer viaje de Zigbee con un experimento algo más completo y extenso: el "sistema de monitorización de temperatura", y explicar cómo aplicar de forma exhaustiva los puntos de conocimiento aprendidos anteriormente. De hecho, no está calificado para llamarse "ExplicaciónComo principiante, el autor solo espera animarse mutuamente y avanzar juntos en el proceso de escribir un doctorado. </n; i++)
|