Denna artikel är en spegelartikel om maskinöversättning, klicka här för att hoppa till originalartikeln.

Utsikt: 9371|Svar: 0

Zigbee Journey (9): Flera viktiga grundläggande CC2430-experiment – systematisk sömn och avbruten vakenhet

[Kopiera länk]
Publicerad på 2014-10-30 23:24:30 | | | |
1. Att koppla ihop de övre och undre nivåerna

I denna artikel kommer vi att diskutera sömnfunktionen och uppvakningsmetoden för CC2430. Vid faktisk användning drivs CC2430-noden vanligtvis av batterier, så kontrollen av dess strömförbrukning är avgörande.

Följande är ett utdrag ur CC2430:s kinesiska manual för introduktionen av CC2430:s fyra strömanvändningslägen:

Som du kan se i tabellen ovan har CC2430 totalt 4 strömsätt:PM0(helt vaken),PM1(lite sömnig),PM2(halvvaken och halvsovande),PM3(Sover väldigt djupt). Ju längre bak, desto fler funktioner stängs av och strömförbrukningen blir allt lägre. Omvändelserelationen mellan dem är följande:

SättPM1、PM2VaknaPM0, det finns tre sätt: återställning, extern avbrott, avbrott från vilotimern; Men läggPM3VaknaPM0, det finns bara två sätt: återställning, extern avbrott (detta beror på att iPM3Alla oscillatorer slutade fungera, och självklart var vilotimern avstängd~)

Låt oss gå igenom ett litet experiment för att visa hur man går in i viloläge och hur man vaknarPM0staten.

2. Systematisk sömn och avbrutna uppvaknandeexperiment(1) Introduktion till experimentetSysteminitiering, iPM0
→ gå inPM1
→ Vakna av vilotimern efter 1 sekunderPM0
→ gå inPM2
→ väcktes av sömntimern efter två sekunderPM0
→ gå inPM3
→ Vänta på att tangenten S1 trycks in, vilket utlöser ett externt avbrott och vaknarPM0
(2) Programflödesschema

(Obs: Den rundade rutan i bilden ovan visar systemets hälsostatus)

(3) Experimentell källkod och analys (Följande rutor kan klickas på~Headerfil och makrodefinition[url=] [/url]
/*
    Experimentell beskrivning: Experiment med avbruten väckningssömn, som introducerar vakenhet i tre sömnlägen
*/

#include
#define LED_ON 0
#define LED_OFF 1#defineled1 P1_0         
#defineled2 P1_1         
#defineled3 P1_2         
#defineled4 P1_3   [url=] [/url]

Delfunktioner[url=] [/url]
/*Systemklocksinitiering
-------------------------------------------------------
*/
tomrumxtal_init(tomrum)
{
  SOV &= ~0x04;            //Alla är drivna
  medan(! (SÖMN &0x40));     //Kristalloscillatorn är på och stabil
  CLKCON &= ~0x47;         //Välj en 32MHz kristalloscillator
  SÖMN |=0x04;
}


/*LED-initiering
-------------------------------------------------------
*/
tomrumled_init(tomrum)
{
  P1SEL =0x00;         //P1 är den normala I/O-porten
  P1DIR |=0x0F;         //P1.0 P1.1 P1.2 P1.3-utgång
  
  led1 = LED_OFF;         //Stäng av alla LED-lampor
  led2 = LED_OFF;
  led3 = LED_OFF;
  led4 = LED_OFF;
}


/*Extern avbrottsinitiering
-------------------------------------------------------
*/
tomrumio_init(tomrum)
{
    P0INP &= ~0X02;   //P0.1 har pull-up och pull-down

    EA =1;           //Total avbrott tillåten
   
    IEN1 |=  0X20;   //P0IE = 1, P0-avbrott aktiverar
   
    PICTL |=  0X09;   //P0.1 tillåter avbrott, drop edge-triggers
   
    P0IFG &= ~0x02;   //P0.1 Avbrottsmarkering clear0
}


/*Initiering av sömntimers avbrott
-------------------------------------------------------
*/
tomrumsleepTimer_init(tomrum)
{
  STIF=0;   //Sömntimerns avbrottsmarkering är klar 0
   
  STIE=1;   //Slå på sömntimern avbruten
   
  EA=1;     //Öppna den totala avbrottet
}


/*Ställ in det schemalagda intervallet för sömntimern
-------------------------------------------------------
*/
tomrumsetSleepTimer(osignerat(osignerat)intsec)
{
  osigneradLångsleepTimer =0;
  
  sleepTimer |= ST0;                     //Få räknevärdet för den aktuella vilotimern
  sleepTimer |= (osigneratLång)ST1 <<8;
  sleepTimer |= (osigneratLång)ST2 <<16;
  
  sleepTimer += ((osigneratLång)sec * (osigneratLång)32768);   //Plus den nödvändiga tidsperioden
  
  ST2 = (osigneratchar(sleepTimer >>16);   //Ställ in jämförelsevärdet för sömntimern
  ST1 = (osignerat)char(sleepTimer >>8);
  ST0 = (osigneratchar)sleepTimer;
}


/*Välj strömläge
-------------------------------------------------------
*/
tomrumPowerMode (osigneratcharläge)
{
  om(läge <4)
  {
    SOV &=0xfc;      //Rensa SLEEP.MODE till 0
    SLEEP |= läge;      //Välj strömläge
    PCON |=0x01;        //Aktivera detta strömläge
  }
}


/*Fördröjningsfunktion
-------------------------------------------------------
*/
tomrumFördröjning (osignerad)intn)
{
  osigneradinti,j;
  för(i=0; i<n; i++)
    för(j=0; j <1000; j++);
}
[url=] [/url]

Huvudfunktion[url=] [/url]
/*Huvudfunktion
-------------------------------------------------------
*/
tomrumhuvud(tomrum)
{
  xtal_init();         
  led_init();         
  
  //PM0-status, ljus på och fördröjning
  led1 = LED_ON;         //Ljusstyrka LED1 indikerar att systemet arbetar i PM0-läge
  Fördröjning(10);


  //PM1-tillstånd, lamporna släckta
  setSleepTimer(1);      //Ställ in tidsintervallet för sömntimern till 1 sekunder
  sleepTimer_init();     //Slå på sömntimern avbruten
  led1 = LED_OFF;
  PowerMode(1);         //Ställ in strömläget till PM1
  
  
//Efter 1s går PM1 in i PM0, tänds och fördröjer
  led1 = LED_ON;
  Fördröjning(50);
  
  //PM2, lamporna släckta
  setSleepTimer(2);      //Ställ in tidsintervallet för sömntimern till 2 sekunder
  led1 = LED_OFF;
  PowerMode(2);         //Ställ in strömläget till PM2


  
//Efter 2 sekunder går PM2 in i PM0, tänds och fördröjer
  led1=0;
  Fördröjning(50);
  
  //PM3, släck lampan  
  io_init();            //Initiera externa avbrott
  led1 = LED_OFF;
  PowerMode(3);         //Ställ in strömläget till PM3
  
  
//När ett externt avbrott inträffar går PM3 in i PM0 och lyser upp
  led1 = LED_ON;

  medan(1);
}
[url=] [/url]

Avbrottstjänstprocedurer[url=] [/url]
/*Extern avbrottstjänstprogram
-------------------------------------------------------
*/
#pragmavektor = P0INT_VECTOR
__interrupttomrumP0_ISR(tomrum)
{
  EA =0;                        //Porten är avbruten
  
  Fördröjning(50);

  om((P0IFG &0x02) >0)         //Nycklarna är avbrutna
  {
    P0IFG &= ~0x02;               //P0.1 Avbrottsmarkering clear0
  }
  P0IF =0;                       //P0-avbrottsmarkering clear0


  EA =1;                        //Öppen avbrott
}


/*Vilotimer avbryter serviceprogram
-------------------------------------------------------
*/
#pragmavektor= ST_VECTOR
__interrupttomrumsleepTimer_IRQ(tomrum)
{
  EA=0;     //Porten är avbruten
   
  STIF=0;   //Sömntimerns avbrottsmarkering är klar 0
  
  EA=1;     //Öppen avbrott
}
[url=] [/url]

Hur man använder en vilotimer för att väcka systemet kan sammanfattas så här:Avbryt Öppna vilotidsavbrott → ställ in vilotidsintervallet → ställ in strömläget

(Obs: "Sätt vilotidsintervallet" måste ske före "Ställ in strömläge", eftersom systemet inte fortsätter att köra programmet efter viloläge)

Nästa steg är att fokusera på delfunktionen som sätter sömntimerintervallet:setSleepTimer

Först och främst, en kort introduktion till sömntimern: den går på32,768kHzav24:e platsTimer, när systemet är igångUtöver PM3I alla strömläge kommer vilotimern att varaOavbruten drift

De register som används av sömntimers är:ST0ST1ST2。 Följande är en detaljerad introduktion till dess funktioner från CC2430 kinesiska manualen:

Det kan ses att deras funktioner omfattar två aspekter:Lässkriv

  Läs: Används för att läsa av räknevärdet på den aktuella timern, i vilken ordning mätningarna måste följas:Läs ST0 → Läs ST1 → Läs ST2

  skriv: Används för att sätta timerns jämförelsevärde (när timerns räkningvärde = jämförelsevärde uppstår ett avbrott), måste skrivordningen följa:Skriv ST2 → skriv ST1 → skriv ST0

Okej, låt oss förklara det i kombination med källkoden:

(1) Definiera först en osignerad lång variabel (32-bitars) sleepTimer för att ta emot det aktuella räknevärdet för sömntimern:

  osigneradLångsleepTimer =0;
  
  sleepTimer |= ST0;                     //Få räknevärdet för den aktuella vilotimern
  sleepTimer |= (osigneratLång)ST1 <<8;
  sleepTimer |= (osigneratLång)ST2 <<16;

(2) Lägg sedan till det önskade tidsintervallet:

  sleepTimer += ((osigneratLång)sec * (osigneratLång)32768);   //Plus den nödvändiga tidsperioden

Här är en liten förklaring:

Varför representerar 1:or 32768? Eftersom timern arbetar under 32,768 kHz tar den 1/32768 s för varje 1 som läggs till timern; Lägg till 32768, och du behöver 1s;

(3) Slutligen används värdet av sleepTimer som jämförelsevärdet för timern:

  ST2 = (osigneratchar(sleepTimer >>16);   //Ställ in jämförelsevärdet för sömntimern
  ST1 = (osignerat)char(sleepTimer >>8);
  ST0 = (osigneratchar)sleepTimer;

På så sätt kan du framgångsrikt ställa in tidsperioden för timern~

(Obs: När det gäller de andra delarna av källkoden tror jag att i kombination med detaljerade anteckningar kan du lätt förstå, och jag kommer inte att upprepa det här)

(4) Experimentella resultat
När programmet körs och LED1 observeras, är fenomenet:LED1 blinkar (dvs. på-> av 1 gång), blinkar igen efter 1 sekunder, blinkar igen efter 2 sekunder, förblir sedan avstängt, och trycker sedan på S1, LED1 tänds.
Det experimentella fenomenet är helt förenligt med förväntningen, Över~

3. Slutsats

Åh~ Efter att ha tagit två dagars fritid fick jag äntligen den här loggen. Jag upptäckte verkligen att skriva en blogg, särskilt ett "läsarvänligt" blogginlägg, verkligen är ett fysiskt jobb: stringens, estetik, logik... Det handlar helt om omtanke.

Varje gång jag lägger upp koden tycker jag att den är för lång, men jag är tveksam till att använda det vikbara verktyget som följer med bloggträdgården. Därför lade författaren i detta blogginlägg försiktigt till några JQuery-element för att uppnå smidig kodveckning, och det finns fortfarande en liten känsla av prestation, hehe (JQuery-nybörjare, skratta inte åt mästaren~). Men jag vet inte om detta verkligen förbättrar artikelns läsbarhet, och läsare och vänner är välkomna att kommentera :)

Den här månaden bestämde sig författaren verkligen för att slå rot i bloggens trädgård, så jag tillbringade mycket fritid med att skriva blogginlägg. När jag skrev en blogg för första gången, även om det fanns få kommentarer, hade de flesta loggarna en klickfrekvens på över 500, vilket var en liten uppmuntran för mig! Det krävs mod för att publicera innehåll om mikrokontrollers i bloggens trädgård, men jag kommer att hålla fast vid det~

De nio blogginläggen från början till idag fokuserar på användningen av grundläggande hårdvarumoduler på CC2430-chippet. Hittills har vi i princip gått igenom de flesta kringutrustningarna på CC2430, men det finns fortfarande saker som Flash-åtkomst, slumptalsgenerator, AES-koprocessor, RF-kommunikation med mera, som inte har berörts. Zigbee-resan är dock inte över, och författaren avser att selektivt fylla i dessa utelämnanden i nästa ämne (implementering av Z-Stack-protokollet).

I nästa blogginlägg planerar jag att avsluta Zigbees första resa med ett något mer omfattande och utökat experiment – "temperaturövervakningssystem", och förklara hur man heltäckande kan tillämpa de kunskapspunkter man lärt sig tidigare.

Faktum är att det inte är kvalificerat att kallas "FörklaringSom nybörjare hoppas författaren bara kunna uppmuntra varandra och göra framsteg tillsammans i processen att skriva en doktorsavhandling!


</n; i++)




Föregående:Zigbee Journey (8): Flera viktiga CC2430 grundläggande experiment – vakthundar
Nästa:Zigbee Journey (10): Omfattande experiment - Temperaturövervakningssystem baserat på CC2430
Friskrivning:
All programvara, programmeringsmaterial eller artiklar som publiceras av Code Farmer Network är endast för lärande- och forskningsändamål; Ovanstående innehåll får inte användas för kommersiella eller olagliga ändamål, annars kommer användarna att bära alla konsekvenser. Informationen på denna sida kommer från internet, och upphovsrättstvister har inget med denna sida att göra. Du måste helt radera ovanstående innehåll från din dator inom 24 timmar efter nedladdning. Om du gillar programmet, vänligen stöd äkta programvara, köp registrering och få bättre äkta tjänster. Om det finns något intrång, vänligen kontakta oss via e-post.

Mail To:help@itsvse.com