51单片机的休眠模式

[复制链接]
340|2
 楼主 | 2018-6-29 22:56 | 显示全部楼层 |阅读模式
AT89S52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU
停止工作,允许RAM、定时器/计数器、串口、中断继续工
作。掉电保护方式下,RAM内容被保存,振荡器被冻结,
单片机一切工作停止,直到下一个中断或硬件复位为止。
单片机空闲与掉电模式2009-04-23 00:03特别对于电池供电系统来说,功耗是首要考虑的问题.我们知道单片机内部有一个电源管理
寄存器PCON,这个寄存器的最低两位,IDLPD这两位分别用来设定是否使单片机进入空闲模式和掉电模式。
1. 空闲模式
     当单片机进入空闲模式时,除CPU处于休眠状态外,其余硬件全部处于活动状态,芯片中程序未涉及到的数据存储器和特殊功寄存器中的数据在空闲模式期间都将保持原值。但假若定时器正在运行,那么计数器寄存器中的值还将会增加。单片机在空闲模式下可由任一个中断或硬件复位唤醒,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。
     让单片机进入空闲模式的目的通常是为了降低系统的功耗,举个很简单的例子,大家都用过数字万用表,在正常使用的时候表内部的单片机处于正常工作模式,当不用时,又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,它便会自
动将液晶显示关闭,以降低系统功耗,通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA7mA,进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。
2.   休眠模式
     当单片机进入掉电模式时,外部晶振停振、CPU、定时器、串行口全部停止工作,只有外部中断继续工作。使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。可将数字万用表调节到电流档,然后串接入电路中,观察单片机在正常工作模式、休眠模式、空闲模式下流过系统的总电流变化情况,经测试可发现结果如下:正常工作电流>空闲模式电流>休眠模式电流。
51进空闲模式
2007-10-24 14:36
进入空闲模式:PCON=0x01;     之前执行AUXR=0xFF;定义空闲模式下看门狗WDT不计数。
PCON:电源控制器及波特率选择寄存器
      字节地址=87H,不可位寻址
SMOD
-
-
POF
GF1
GF0
PD
IDL
      SMOD——波特率倍增位
      GF1[size=12.0000pt]、GF0——用户通用标记
      PD——掉电方式控制位,PD[size=12.0000pt]=1时进入掉电模式
      IDL——空闲方式控制位,IDL=1时进入空闲方式
      在AT89S51[size=12.0000pt]中PCON.4是电源断电标记位POF,上电是为1
PCON(电源控制寄存器)的有关位来设置实现控制:   
  当第0IDL1时,进入待机模式,此时单片机功耗很低,振荡器继续运行,可用中断来唤醒   
  当第1PD1时,进入掉电模式
在程序中执行下面指令就达目的:
setb idl  ;待机模式
setb pd  ;掉电模式



 楼主 | 2018-6-29 22:57 | 显示全部楼层
我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,IDL和PD这两位分别用来设定是否使单片机进入空闲模式和掉电模式。
1. 空闲模式
     当单片机进入空闲模式时,除CPU处于休眠状态外,其余硬件全部处于活动状态,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。但假若定时器正在运行,那么计数器寄存器中的值还将会增加。单片机在空闲模式下可由任一个中断或硬件复位唤醒,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。
     让单片机进入空闲模式的目的通常是为了降低系统的功耗,举个很简单的例子,大家都用过数字万用表,在正常使用的时候表内部的单片机处于正常工作模式,当不用时,又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,它便会自动将液晶显示关闭,以降低系统功耗,通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA~7mA,进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。
2.  休眠模式
     当单片机进入掉电模式时,外部晶振停振、CPU、定时器、串行口全部停止工作,只有外部中断继续工作。使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。
下面的例子演示单片机进入空闲和休眠模式,并且演示出从空闲和休眠模式中唤醒的过程。
     【例】:在TX-1C实验板上完成如下描述,开启两个外部中断,设置低电平触发中断,用定时器计数并且显示在数码管的前两位,当计到5时,使单片机进入空闲(休眠)模式,同时关闭定时器,当单片机响应外部中断后,从空闲(休眠)模式返回,同时开启定时器。
新建文件part3.4.1.c,程序代码如下:
  #include <reg52.h>      //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;  //申明U1锁存器的锁存端
sbit wela=P2^7;  //申明U2锁存器的锁存端
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar num;
void delayms(uint);
void display(uchar shi,uchar ge)  //显示子函数
{
    dula=1;
P0=table[shi];    //送十位段选数据
dula=0;
P0=0xff;  //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1;   //原来段选数据通过位选锁存器造成混乱
P0=0xfe;  //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[ge];  //送个位段选数据
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
}
void delayms(uint xms)   
{
uint i,j;
for(i=xms;i>0;i--)        //i=xms即延时约xms毫秒
  for(j=110;j>0;j--);
}
void main()
{
uchar a,b,num1;
TMOD=0x01; //设置定时器0为工作方式1(0000 0001)
TH0=(65536-50000)/256;     
TL0=(65536-50000)%256;
EA=1;
ET0=1;
EX0=1;
EX1=1;
TR0=1;
while(1)
{

  if(num>=20)
  {
   num=0;
   num1++;
   if(num1==6)
   {
    ET0=0;
    PCON=0x02; (或PCON=0x01;)
   }
   a=num1/10;
   b=num1%10;
  }
  display(a,b);
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
}
void ex_int0() interrupt 0
{
PCON=0;
ET0=1;
}
void ex_int1() interrupt 2
{
PCON=0;
ET0=1;
}
分析:
(1) EA=1;  开总中断
ET0=1;  开定时器0中断
EX0=1;  开外部中断0
EX1=1;   开外部中断1
TR0=1;  启动定时器0
(2)主程序中有“ET0=0;”下句是“PCON=0x02;”意思是在进入休眠模式之前要先把定时器关闭,这样方可一直等待外部中断的产生,如果不关闭定时器,定时器的中断同样也会唤醒单片机,使其退出休眠模式,这样我们便看不出进入休眠模式和返回的过程。
(3)void ex_int0() interrupt 0  
{
  PCON=0;
  ET0=1;
}
这是外部中断0服务程序,当进入外部中断服务程序后,首先将PCON中原先设定的休眠控制位清除(如果不清除,程序也可以正常运行,大家最好亲自做实验验证),接下来再重新开启定时器0。
(4)下载程序后,实验现象如下:数码管从“00”开始递增显示,到“05”后,再过一秒后,数码管变成只显示一个“5”,单片机进入休眠或空闲模式,用导线一端连接地,另一端接触P3.2或P3.3,数码管重新从“06”开始显示,递增下去。整个过程演示了单片机从正常工作模式进入休眠模式或空闲模式,然后再从休眠模式或空闲模式返回到正常工作模式。
(5)测试过程大家可将数字万用表调节到电流档,然后串接入电路中,观察单片机在正常工作模式、休眠模式、空闲模式下流过系统的总电流变化情况,经测试可发现结果如下:正常工作电流>空闲模式电流>休眠模式电流。

· STC51的休眠模式以及唤醒

2008-04-02

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://weiwenmo.blogbus.com/logs/34963305.html

    STC确实是块好芯片,性能好,功耗低环境适应能力强(不过据说潮湿环境下flash容易丢失)。STC51的休眠和唤醒功能已经在datasheet有示例代码了,因为pdf被加密了,所以不能复制。贴个代码,并且已经在STC12C5204上调试通过。


/* 中断唤醒测试程序 */
     
#include <STC51.h>
//#include <reg52.h>
#include <intrins.h>

#define SHUTDOWN_MASHINE() do {         \
        Is_Power_Down = 1;     \
        PCON = 0x02;      \
        _nop_();_nop_();_nop_();_nop_(); \
       } while (0);

void Rest_Soft(void)
{  
ISP_CONTR = 1 << 5;
}

sbit Begin_Led     = P1^0;  // 系统开始工作指示灯

unsigned char Is_Power_Down  = 0;  // 进入Power Down 之前,将其置为1,以供判断

sbit Is_Power_Down_Led_INT0  = P1^0;  // 掉电唤醒指示灯,在外部中断0中
sbit Not_Power_Down_Led_INT0 = P1^0;  // 不是掉电唤醒指示灯,在外部中断0中
sbit Is_Power_Down_Led_INT1  = P1^6;  // 掉电唤醒指示灯,在外部中断1中
sbit Not_Power_Down_Led_INT1 = P1^7;  // 不是掉电唤醒指示灯,在外部中断1中

sbit Power_Down_Wakeup_Pin_INT0 = P3^2;  // 掉电唤醒管脚,外部中断0
sbit Power_Down_Wakeup_Pin_INT1 = P3^3;  // 掉电唤醒管脚,外部中断1

sbit Normal_Work_Flashing_Led = P1^5;  // 系统处于正常工作状态指示灯

/*
sbit Begin_Led     = P1^0;  // 系统开始工作指示灯

unsigned char Is_Power_Down  = 0;  // 进入Power Down 之前,将其置为1,以供判断

sbit Is_Power_Down_Led_INT0  = P2^0;  // 掉电唤醒指示灯,在外部中断0中
sbit Not_Power_Down_Led_INT0 = P2^0;  // 不是掉电唤醒指示灯,在外部中断0中
sbit Is_Power_Down_Led_INT1  = P2^6;  // 掉电唤醒指示灯,在外部中断1中
sbit Not_Power_Down_Led_INT1 = P1^7;  // 不是掉电唤醒指示灯,在外部中断1中

sbit Power_Down_Wakeup_Pin_INT0 = P3^2;  // 掉电唤醒管脚,外部中断0
sbit Power_Down_Wakeup_Pin_INT1 = P3^3;  // 掉电唤醒管脚,外部中断1

sbit Normal_Work_Flashing_Led = P2^5;  // 系统处于正常工作状态指示灯
*/

void Normal_Work_Flashing (void);
void INT_System_init (void);
void INT0_Routine (void);
void INT1_Routine (void);
   
void main (void)
{
unsigned char j = 0;
unsigned char wakeup_counter = 0;  // 中断唤醒次数变量初始为0

Begin_Led = 0;       // 系统开始工作指示灯
INT_System_init();      // 中断系统初始化

while (1)
{
  //P2 = -wakeup_counter;    // 中断唤醒次数显示,先将wakeup_counter取反
  wakeup_counter++;     // 中断唤醒次数显示
  
  for (j=0; j<50; j++)
  {
   Normal_Work_Flashing();   // 系统正常工作指示灯
  }
  
  SHUTDOWN_MASHINE();
  /*
  Is_Power_Down = 1;     // 进入Power Down 之前,将其置为1,以供判断
  PCON = 0x02;      // 执行完此句,单片机进入Power Down模式,外部时钟停止震荡
  
  _nop_();       // STC12系列掉电模式,外部中断唤醒后首先执行上句,然后才会进入中断服务程序
  _nop_();
  _nop_();       // 建议多加几个空操作指令NOP
  _nop_();       // 建议多加几个空操作指令NOP
  */
}
}
        
void INT_System_init(void)
{
//IT0 = 0;        /* 外部中断0,低电平触发中断 */
// IT0 = 1;        /* 外部中断0,下降沿触发中断 */
//EX0 = 1;        /* 允许外部中断0中断 */

IT1 = 0;        /* 外部中断1,低电平触发中断 */
// IT1 = 1;        /* 外部中断1,下降沿触发中断 */
EX1 = 1;        /* 允许外部中断1中断 */
EA  = 1;        /* 开总中断控制位 */
}

/*void INT0_Routine(void) interrupt 0
{
if (Is_Power_Down)      //Is_Power_Down == 1,掉电唤醒,在外部中断0中
{
  Is_Power_Down = 0;
  Is_Power_Down_Led_INT0 = 0;   // 点亮外部中断0掉电唤醒指示灯
  
  while (Power_Down_Wakeup_Pin_INT0 == 0)
  {
   //* 等待变高
  }
  Is_Power_Down_Led_INT0 = 1;   // 关闭外部中断0掉电唤醒指示灯
}
else
{
  Not_Power_Down_Led_INT0 = 0;
  while (Power_Down_Wakeup_Pin_INT0 == 0)
  {
   //* 等待变高
  }
  Not_Power_Down_Led_INT0 = 1;
}
}*/

void INT1_Routine(void) interrupt 2
{
unsigned int uiI;

if (Is_Power_Down)      //Is_Power_Down == 1,掉电唤醒,在外部中断1中
{
  Is_Power_Down = 0;
  Is_Power_Down_Led_INT1 = 0;   // 点亮外部中断1掉电唤醒指示灯
  
     for (uiI=0x1efff;uiI>0;--uiI)
  {
   if (INT1 == 1)
   {
    SHUTDOWN_MASHINE();
    return;
   }
  }

  //while (Power_Down_Wakeup_Pin_INT1 == 0)
  //{
   /* 等待变高 */
  //}

  Is_Power_Down_Led_INT1 = 1;   // 关闭外部中断1掉电唤醒指示灯

  Rest_Soft();
}
else
{
  Not_Power_Down_Led_INT1 = 0;
  
     /*for (uiI=0x1efff;uiI>0;--uiI)
  {
   if (INT1 == 1)
   {
   
    return;
   }
  }*/

  while (Power_Down_Wakeup_Pin_INT1 == 0)
  {
   /* 等待变高 */
  }

  Not_Power_Down_Led_INT1 = 1;

  SHUTDOWN_MASHINE();
}
}
      
void delay (void)
{
unsigned int j = 0;
unsigned int k = 0;

for (k=0; k<2; ++k)
{
  for (j=0; j<30000; ++j)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
}
        void Normal_Work_Flashing(void)
{
Normal_Work_Flashing_Led = 0;
delay();
Normal_Work_Flashing_Led = 1;
delay();
}
    在有些程序中,休眠唤醒后需要用到软复位,通过以下代码实现:
sfr ISP_CONTR = 0xE7;
ISP_CONTR = 1 << 5;
    stc12C52XX是目前(080323)尚未公布的一款型号,增加了些功能,例如外部掉电检测等。但是如果将原先用在STC12C54XX系列的程序用在这块芯片上会出现有些功能不能用的情况,例如软复位复位不了。需要注意的是新cpu的寄存器地址,软复位配置寄存器ISP_COUNTR的地址就由0xE7变为0xC7。
| 2018-7-2 08:42 | 显示全部楼层
非常实用的知识
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

关闭

热门推荐上一条 /5 下一条

快速回复 返回顶部 返回列表