|
1. Conectando os níveis superior e inferior Neste artigo, discutiremos a função do sono e o método de acordar do CC2430. No uso real, o nó CC2430 geralmente é alimentado por baterias, então o controle do consumo de energia é crucial. A seguir, um trecho do manual chinês do CC2430 para a introdução dos 4 modos de consumo de energia do CC2430:
Como você pode ver na tabela acima, o CC2430 possui um total de 4 modos de energia:PM0(totalmente acordado),PM1(um pouco sonolento),PM2(meio acordado e meio dormindo),PM3(Dormindo muito pesado). Quanto mais atrás, mais funções são desativadas e o consumo de energia fica cada vez menor. A relação de conversão entre eles é a seguinte:
ColoquePM1、PM2AcordarPM0, existem três maneiras: reset, interrupção externa, interrupção do temporizador de sono; Mas coloquePM3AcordarPM0, existem apenas duas maneiras: reset, interrupção externa (isso porque emPM3Todos os osciladores pararam de funcionar, e claro que o temporizador de sono foi desligado~) Vamos fazer um pequeno experimento para introduzir como entrar no modo de sono e como acordarPM0State. 2. Experimentos de sono sistemático e acordar interrompido(1) Introdução ao experimentoInicialização do sistema, emPM0
→ entrarPM1
→ Acordar pelo temporizador de sono após 1sPM0
→ entrarPM2
→ foi acordado pelo temporizador de sono após 2 segundosPM0
→ entrarPM3
→ Espere a tecla S1 ser pressionada, acionando uma interrupção externa e acordandoPM0
(2) Fluxograma de programas
(Nota: A caixa arredondada na imagem acima indica o estado de saúde do sistema)
(3) Código-fonte experimental e análise (As seguintes caixas podem ser clicadas~)Definição de arquivo de cabeçalho e macro[url=]
[/url]
/* Descrição experimental: Experimento de sono acordado interrompido, que introduz a vigília em três modos de sono
*/
#include #define LED_ON 0 #define LED_OFF 1#defineliderou1 P1_0
#defineLed2 P1_1
#defineLed3 P1_2
#defineliderou4 P1_3 [url=] [/url]
Subfunções[url=] [/url]
/*Inicialização do clock do sistema -------------------------------------------------------*/
vazioxtal_init(vazio)
{ SONO &= ~0x04; //Todos são movidos
enquanto(! (SONO &0x40)); //O oscilador de cristal está ligado e estável
CLKCON &= ~0x47; //Escolha um oscilador de cristal de 32MHz
SONO |=0x04;
}
/*Inicialização de LED -------------------------------------------------------*/
vazioled_init(vazio)
{ P1SEL =0x00; //P1 é a porta normal de E/S
P1DIR |=0x0F; //Saída P1.0 P1.1 P1.2 P1.3
liderado1 = LED_OFF; //Desligue todos os LEDs
liderou2 = LED_OFF; liderado3 = LED_OFF; liderado4 = LED_OFF;
}
/*Inicialização de interrupção externa -------------------------------------------------------*/
vazioio_init(vazio)
{ P0INP &= ~0X02; //P0.1 tem pull-up e pull-down
EA =1; //Interrupção total permitida
IEN1 |= 0X20; //P0IE = 1, P0 interrupções ativadas
PICTL |= 0X09; //P0.1 permite interrupções, gatilhos de borda caída
P0IFG &= ~0x02; //P0.1 Marca de interrupção limpa0
}
/*Inicialização da interrupção do temporizador de sono -------------------------------------------------------*/
vaziosleepTimer_init(vazio)
{ STIF=0; //A marca de interrupção do temporizador de sono está limpa 0
STIE=1; //Ligue o temporizador de sono interrompido
EA=1; //Abra a interrupção total
}
/*Defina o intervalo programado para o temporizador de sono -------------------------------------------------------*/
vaziosetSleepTimer(unsignedintsec)
{ sem assinaturaLongasSleepTimer =0;
sleepTimeter |= ST0; //Obtenha o valor de contagem do temporizador de sono atual
sleepTimer |= (sem sinalLongas)ST1 <<8; sleepTimer |= (sem sinalLongas)ST2 <<16;
sleepTimer += ((sem sinalLongas)sec * (não assinadoLongas)32768); //Além da duração do tempo exigido
ST2 = (sem sinalChar(sleepTimer >>16); //Defina o valor de comparação do temporizador de sono
ST1 = (sem sinalChar(sleepTimer >>8); ST0 = (sem sinalChar)sleepTimer;
}
/*Selecionar Modo de Energia -------------------------------------------------------*/
vazioPowerMode(sem sinal)Charmodo)
{
se(modo <4) { SONO &=0xfc; //Limpar o MODO SLEEP para 0
SLEEP |= modo; //Selecionar Modo de Energia
PCON |=0x01; //Ative esse modo de energia
}
}
/*Função de atraso -------------------------------------------------------*/
vazioAtraso (não assinadointn)
{ sem assinaturainti,j;
para(i=0; i<n; i++)
para(j=0; j <1000; j++);
}
[url=] [/url]
Função principal[url=] [/url]
/*Função principal -------------------------------------------------------*/
vaziomain(vazio)
{ xtal_init(); led_init();
//Status PM0, luz acesa e atraso
liderou1 = LED_ON; //LED1 de brilho indica que o sistema está funcionando em modo PM0
Atraso(10);
//Estado PM1, luzes apagadas
setSleepTimer(1); //Defina o intervalo de tempo do temporizador de sono para 1s
sleepTimer_init(); //Ligue o temporizador de sono interrompido
liderado1 = LED_OFF; PowerMode(1); //Defina o modo de energia para PM1
//Depois de 1s, PM1 entra em PM0, acende-se e demora
liderou1 = LED_ON; Atraso(50);
//PM2, luzes apagadas
setSleepTimer(2); //Defina o intervalo de tempo do temporizador de sono para 2 segundos
liderado1 = LED_OFF; PowerMode(2); //Defina o modo de energia para PM2
//Após 2 segundos, o PM2 entra no PM0, acende-se e atrasa-se
liderou1=0; Atraso(50);
//PM3, apaguem as luzes
io_init(); //Inicializar interrupções externas
liderado1 = LED_OFF; PowerMode(3); //Defina o modo de energia para PM3
//Quando ocorre uma interrupção externa, o PM3 entra em PM0 e acende-se
liderou1 = LED_ON;
enquanto(1);
}
[url=] [/url]
Procedimentos de serviço de interrupção[url=] [/url]
/*Programa de serviço de interrupção externa -------------------------------------------------------*/
#pragmavetor = P0INT_VECTOR __interruptvazioP0_ISR(vazio)
{ EA =0; //O portão é interrompido
Atraso(50);
se((P0IFG &0x02) >0) //As teclas são interrompidas
{ P0IFG &= ~0x02; //P0.1 Marca de interrupção limpa0
} P0SE =0; //Marca de interrupção P0 limpa0
EA =1; //Interrupção aberta
}
/*Temporizador de sono interrompe programas de serviço -------------------------------------------------------*/
#pragmavetor= ST_VECTOR __interruptvaziosleepTimer_IRQ(vazio)
{ EA=0; //O portão é interrompido
STIF=0; //A marca de interrupção do temporizador de sono está limpa 0
EA=1; //Interrupção aberta
}
[url=] [/url]
Como usar um temporizador de sono para acordar o sistema pode ser resumido da seguinte forma:Abrir a Interrupção do Timer de Sono → definir o intervalo de tempo do temporizador → definir o modo de energia (Nota: O passo "Definir o Intervalo do Temporizador de Suspensão" deve ser antes de "Definir o Modo de Energia", porque o sistema não continuará executando o programa após entrar em suspensão) Em seguida, vamos focar na subfunção que define o intervalo do temporizador de sono:setSleepTimer Primeiramente, uma breve introdução ao temporizador de sono: ele funciona32,768kHzde24º lugarTemporizador, quando o sistema está rodandoAlém do PM3Em todos os modos de energia, o temporizador de suspensão seráOperação ininterrupta。 Os registradores usados por temporizadores de sono são:ST0,ST1,ST2。 A seguir está uma introdução detalhada às suas funções a partir do manual chinês CC2430:
Pode-se ver que suas funções incluem dois aspectos:Leia,Escreva。 Leia: Usado para ler o valor de contagem do temporizador atual, a ordem em que as leituras devem ser seguidas:Leia ST0 → Leia ST1 → Leia ST2 Escreva: Usado para definir o valor de comparação do temporizador (quando o valor de contagem = valor de comparação, ocorre uma interrupção), a ordem de escrita deve seguir:Escreva ST2 → escreva ST1 → escreva ST0 OK, vamos explicar isso em combinação com o código-fonte: (1) Primeiro, defina um sleepTimer de variável longa sem sinal (32 bits) para receber o valor atual de contagem do timer de sono: sem assinaturaLongasSleepTimer =0;
sleepTimeter |= ST0; //Obtenha o valor de contagem do temporizador de sono atual
sleepTimer |= (sem sinalLongas)ST1 <<8; sleepTimer |= (sem sinalLongas)ST2 <<16;
(2) Então adicione o intervalo de tempo necessário: sleepTimer += ((sem sinalLongas)sec * (não assinadoLongas)32768); //Além da duração do tempo exigido
Aqui vai uma pequena explicação: Por que o 1s representa 32768? Como o temporizador está funcionando abaixo de 32,768kHz, leva 1/32768 s para cada 1 adicionado ao temporizador; Some 32768, e você vai precisar de 1s; (3) Finalmente, o valor do sleepTimer é usado como valor de comparação do temporizador: ST2 = (sem sinalChar(sleepTimer >>16); //Defina o valor de comparação do temporizador de sono
ST1 = (sem sinalChar(sleepTimer >>8); ST0 = (sem sinalChar)sleepTimer;
Dessa forma, você pode definir com sucesso o período de tempo do temporizador~ (Nota: Quanto às outras partes do código-fonte, acredito que, combinadas com anotações detalhadas, você pode entender facilmente, e não vou repetir aqui) (4) Resultados experimentaisExecutando o programa, observando LED1, o fenômeno é:LED1 pisca (ou seja, ligado e > desligado 1 vez), pisca novamente após 1 segundo, pisca novamente após 2 segundos, permanece desligado e então pressiona S1, LED1 acende. O fenômeno experimental é completamente consistente com a expectativa, Over~
3. ConclusãoOh~ Depois de tirar 2 dias de tempo livre, finalmente consegui esse registro. Descobri que escrever um blog, especialmente um post "amigável para o leitor", é realmente um trabalho físico: rigor, estética, lógica... Tudo se resume à consideração. Cada vez que posto o código, acho que está longo demais, mas fico relutante em usar a ferramenta dobrável que vem com o blog garden. Portanto, neste post do blog, o autor adicionou provisoriamente alguns elementos JQuery para conseguir uma dobra suave do código, e ainda há uma pequena sensação de realização, hehe (JQuery novato, não ria do mestre~). Mas não sei se isso realmente melhora a legibilidade do artigo, e leitores e amigos são bem-vindos para comentar :) Neste mês, a autora realmente decidiu criar raízes no jardim do blog, então passei muito tempo livre escrevendo posts no blog. Quando escrevi um blog pela primeira vez, embora houvesse poucos comentários, a maioria dos registros tinha uma taxa de cliques superior a 500, o que foi um pequeno incentivo para mim! É preciso coragem para publicar conteúdo sobre microcontroladores no jardim do blog, mas vou me manter firme~ Os nove posts do blog desde o início até o presente focam no uso de módulos básicos de hardware no chip CC2430. Até agora, basicamente já passamos pela maioria dos periféricos do CC2430, mas ainda há coisas como acesso em flash, gerador de números aleatórios, coprocesador AES, comunicação RF, etc., que não foram abordadas. No entanto, a jornada do Zigbee não terminou, e o autor pretende preencher seletivamente essas omissões no próximo tópico (implementação do protocolo Z-Stack). No próximo post do blog, pretendo encerrar a primeira viagem de Zigbee com um experimento um pouco mais abrangente e extenso – "sistema de monitoramento de temperatura" – e explicar como aplicar de forma abrangente os pontos de conhecimento aprendidos anteriormente. Na verdade, não é qualificado para ser chamado de "ExplicaçãoComo iniciante, o autor só espera incentivar uns aos outros e progredir juntos no processo de escrever um doutorado! </n; i++)
|