This article is a mirror article of machine translation, please click here to jump to the original article.

View: 9371|Reply: 0

Zigbee Journey (9): Several important basic CC2430 experiments - systematic sleep and interrupted wakefulness

[Copy link]
Posted on 10/30/2014 11:24:30 PM | | | |
1. Connecting the upper and lower levels

In this article, we will discuss the sleep function and wake-up method of CC2430. In actual use, the CC2430 node is generally powered by batteries, so the control of its power consumption is crucial.

The following is an excerpt from the CC2430 Chinese manual for the introduction of the CC2430's 4 power consumption modes:

As you can see from the table above, the CC2430 has a total of 4 power modes:PM0(fully awake),PM1(a little drowsy),PM2(half awake and half asleep),PM3(Sleeping very hard). The further back, the more functions are turned off, and the power consumption is lower and lower. The conversion relationship between them is as follows:

putPM1、PM2Wake upPM0, there are three ways: reset, external interruption, sleep timer interruption; But putPM3Wake upPM0, there are only two ways: reset, external interrupt (this is because inPM3All oscillators stopped working, and of course the sleep timer was turned off~)

Let's go through a small experiment to introduce how to enter sleep mode and how to wake upPM0state.

2. Systematic sleep and interrupted wake-up experiments(1) Introduction to the experimentsystem initialization, in PM0
→ enterPM1
→ Wake up by the sleep timer after 1sPM0
→ enterPM2
→ was awakened by the sleep timer after 2sPM0
→ enterPM3
→ Wait for the key S1 to be pressed, triggering an external interrupt and waking upPM0
(2) Program flow chart

(Note: The rounded box in the image above indicates the health status of the system)

(3) Experimental source code and analysis (The following boxes can be clicked~Header file and macro definition[url=] [/url]
/*
    Experimental description: Interrupted wake-up sleep experiment, which introduces wakefulness in three sleep modes
*/

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

Subfunctions[url=] [/url]
/*System clock initialization
-------------------------------------------------------
*/
voidxtal_init(void)
{
  SLEEP &= ~0x04;            //All are powered
  while(! (SLEEP &0x40));     //The crystal oscillator is on and steady
  CLKCON &= ~0x47;         //Choose a 32MHz crystal oscillator
  SLEEP |=0x04;
}


/*LED initialization
-------------------------------------------------------
*/
voidled_init(void)
{
  P1SEL  =0x00;         //P1 is the normal I/O port
  P1DIR |=0x0F;         //P1.0 P1.1 P1.2 P1.3 output
  
  led1 = LED_OFF;         //Turn off all LEDs
  led2 = LED_OFF;
  led3 = LED_OFF;
  led4 = LED_OFF;
}


/*External interrupt initialization
-------------------------------------------------------
*/
voidio_init(void)
{
    P0INP &= ~0X02;   //P0.1 has pull-up and pull-down

    EA =1;           //Total interruption allowed
   
    IEN1  |=  0X20;   //P0IE = 1, P0 interrupts enable
   
    PICTL |=  0X09;   //P0.1 allows interrupts, drop edge triggers
   
    P0IFG &= ~0x02;   //P0.1 Interrupt mark clear0
}


/*Sleep timer interrupt initialization
-------------------------------------------------------
*/
voidsleepTimer_init(void)
{
  STIF=0;   //The sleep timer interrupt mark is clear 0
   
  STIE=1;   //Turn on the sleep timer interrupted
   
  EA=1;     //Open the total interruption
}


/*Set the scheduled interval for the sleep timer
-------------------------------------------------------
*/
voidsetSleepTimer(unsignedintsec)
{
  unsignedlongsleepTimer =0;
  
  sleepTimer |= ST0;                     //Get the count value of the current sleep timer
  sleepTimer |= (unsignedlong)ST1 <<8;
  sleepTimer |= (unsignedlong)ST2 <<16;
  
  sleepTimer += ((unsignedlong)sec * (unsignedlong)32768);   //Plus the required timing duration
  
  ST2 = (unsignedchar)(sleepTimer >>16);   //Set the comparison value of the sleep timer
  ST1 = (unsignedchar)(sleepTimer >>8);
  ST0 = (unsignedchar)sleepTimer;
}


/*Select Power Mode
-------------------------------------------------------
*/
voidPowerMode(unsignedcharmode)
{
  if(mode <4)
  {
    SLEEP &=0xfc;      //Clear SLEEP.MODE to 0
    SLEEP |= mode;      //Select Power Mode
    PCON |=0x01;        //Enable this power mode
  }
}


/*Delay function
-------------------------------------------------------
*/
voidDelay(unsignedintn)
{
  unsignedinti,j;
  for(i=0; i<n; i++)
    for(j=0; j <1000; j++);
}
[url=] [/url]

main function[url=] [/url]
/*main function
-------------------------------------------------------
*/
voidmain(void)
{
  xtal_init();         
  led_init();         
  
  //PM0 status, light on and delay
  led1 = LED_ON;         //Brightness LED1 indicates that the system is working in PM0 mode
  Delay(10);


  //PM1 state, lights off
  setSleepTimer(1);      //Set the time interval of the sleep timer to 1s
  sleepTimer_init();     //Turn on the sleep timer interrupted
  led1 = LED_OFF;
  PowerMode(1);         //Set the power mode to PM1
  
  
//After 1s, PM1 enters PM0, lights up and delays
  led1 = LED_ON;
  Delay(50);
  
  //PM2, lights off
  setSleepTimer(2);      //Set the time interval for the sleep timer to 2s
  led1 = LED_OFF;
  PowerMode(2);         //Set the power mode to PM2


  
//After 2s, PM2 enters PM0, lights up and delays
  led1=0;
  Delay(50);
  
  //PM3, lights out  
  io_init();            //Initialize external interrupts
  led1 = LED_OFF;
  PowerMode(3);         //Set the power mode to PM3
  
  
//When an external interruption occurs, PM3 enters PM0 and lights up
  led1 = LED_ON;

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

Interrupt service procedures[url=] [/url]
/*External interrupt service program
-------------------------------------------------------
*/
#pragmavector = P0INT_VECTOR
__interruptvoidP0_ISR(void)
{
  EA =0;                        //The gate is interrupted
  
  Delay(50);

  if((P0IFG &0x02) >0)         //The keys are interrupted
  {
    P0IFG &= ~0x02;               //P0.1 Interrupt mark clear0
  }
  P0IF =0;                       //P0 interrupt mark clear0


  EA =1;                        //Open interruption
}


/*Sleep timer interrupts service programs
-------------------------------------------------------
*/
#pragmavector= ST_VECTOR
__interruptvoidsleepTimer_IRQ(void)
{
  EA=0;     //The gate is interrupted
   
  STIF=0;   //The sleep timer interrupt mark is clear 0
  
  EA=1;     //Open interruption
}
[url=] [/url]

How to use a sleep timer to wake up the system can be summarized as follows:Open Sleep Timer Interrupt → Set the Sleep Timer's Timing Interval → Set the Power Mode

(Note: "Set the Sleep Timer Interval" step must be before "Set Power Mode", because the system will not continue to execute the program after entering sleep)

Next, let's focus on the subfunction that sets the sleep timer interval:setSleepTimer

First of all, a brief introduction to the sleep timer: it runs on32.768kHzof24th placeTimer, when the system is runningIn addition to PM3In all power modes, the sleep timer will beUninterrupted operation

The registers used by sleep timers are:ST0ST1ST2。 The following is a detailed introduction to its functions from the CC2430 Chinese manual:

It can be seen that their functions include two aspects:Readwrite

  Read: Used to read the count value of the current timer, the order in which the readings must be followed:Read ST0 → Read ST1 → Read ST2

  write: Used to set the timer's comparison value (when the timer's count value = comparison value, an interrupt occurs), the writing order must follow:Write ST2 → write ST1 → write ST0

OK, let's explain it in combination with the source code:

(1) First, define an unsigned long variable (32-bit) sleepTimer to receive the current count value of the sleep timer:

  unsignedlongsleepTimer =0;
  
  sleepTimer |= ST0;                     //Get the count value of the current sleep timer
  sleepTimer |= (unsignedlong)ST1 <<8;
  sleepTimer |= (unsignedlong)ST2 <<16;

(2) Then add the required time interval:

  sleepTimer += ((unsignedlong)sec * (unsignedlong)32768);   //Plus the required timing duration

Here's a little explanation:

Why does 1s represent 32768? Because the timer is working below 32.768kHz, it takes 1/32768 s for every 1 added to the timer; Add 32768, and you will need 1s;

(3) Finally, the value of sleepTimer is used as the comparison value of the timer:

  ST2 = (unsignedchar)(sleepTimer >>16);   //Set the comparison value of the sleep timer
  ST1 = (unsignedchar)(sleepTimer >>8);
  ST0 = (unsignedchar)sleepTimer;

In this way, you can successfully set the timing period of the timer~

(Note: As for the other parts of the source code, I believe that combined with detailed annotations, you can easily understand, and I will not repeat it here)

(4) Experimental results
Running program, observing LED1, the phenomenon is:LED1 flashes (i.e., on-> off 1 time), flashes again after 1s, flashes again after 2s, then remains off, and then presses S1, LED1 lights up.
The experimental phenomenon is completely consistent with the expectation, Over~

3. Conclusion

Oh~ After taking 2 days of spare time, I finally got this log. I really found that writing a blog, especially a "reader-friendly" blog post, is indeed a physical job: rigor, aesthetics, logic... It's all about consideration.

Each time I post the code, I think it's too long, but I'm reluctant to use the folding tool that comes with the blog garden. Therefore, in this blog post, the author tentatively added some JQuery elements to achieve smooth folding of the code, and there is still a small sense of accomplishment, hehe (JQuery rookie, don't laugh at the master~). But I don't know if this really enhances the readability of the article, and readers and friends are welcome to comment:)

This month, the author really decided to take root in the blog garden, so I spent a lot of spare time writing blog posts. When I wrote a blog for the first time, although there were few comments, most of the logs had a click-through rate of more than 500, which was a small encouragement to me! It does take courage to publish content about microcontrollers in the blog garden, but I will stick to it~

The nine blog posts from the beginning to the present focus on the use of basic hardware modules on the CC2430 chip. So far, we have basically gone through most of the peripherals on the CC2430, but there are still things such as Flash access, random number generator, AES coprocessor, RF communication, etc., which have not been touched upon. However, the Zigbee journey is not over, and the author intends to selectively fill in these omissions in the next topic (implementation of the Z-Stack protocol).

In the next blog post, I plan to end Zigbee's first trip with a slightly more comprehensive and extended experiment - "temperature monitoring system", and explain how to comprehensively apply the knowledge points learned earlier.

In fact, it is not qualified to be called "ExplanationAs a beginner, the author only hopes to encourage each other and make progress together in the process of writing a doctorate!


</n; i++)




Previous:Zigbee Journey (8): Several important CC2430 basic experiments - watchdogs
Next:Zigbee Journey (10): Comprehensive Experiment - Temperature Monitoring System Based on CC2430
Disclaimer:
All software, programming materials or articles published by Code Farmer Network are only for learning and research purposes; The above content shall not be used for commercial or illegal purposes, otherwise, users shall bear all consequences. The information on this site comes from the Internet, and copyright disputes have nothing to do with this site. You must completely delete the above content from your computer within 24 hours of downloading. If you like the program, please support genuine software, purchase registration, and get better genuine services. If there is any infringement, please contact us by email.

Mail To:help@itsvse.com