/*我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,
IDL和PD这两位分别用来设定是否使单片机进入空闲模式和掉电模式。
1. 空闲模式
当单片机进入空闲模式时,除CPU处于休眠状态外,
其余硬件全部处于活动状态,
芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。
但假若定时器正在运行,那么计数器寄存器中的值还将会增加。
单片机在空闲模式下可由任一个中断或硬件复位唤醒,需要注意的是,
使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。
让单片机进入空闲模式的目的通常是为了降低系统的功耗,
举个很简单的例子,大家都用过数字万用表,
在正常使用的时候表内部的单片机处于正常工作模式,当不用时,
又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,
它便会自动将液晶显示关闭,以降低系统功耗,
通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。
以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA~7mA,
进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。
2. 休眠模式
当单片机进入掉电模式时,外部晶振停振、CPU、定时器、
串行口全部停止工作,只有外部中断继续工作。
使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,
芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。
可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,
需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,
当使用硬件复位唤醒单片机时,程序将从头开始执行。
下面的例子演示单片机进入空闲和休眠模式,
并且演示出从空闲和休眠模式中唤醒的过程。
*/
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^6 ;
sbit RW = P2^5 ;
sbit EN = P2^7 ;
sbit STA7 = P0^7;
uint num,num1;
void delayms(uint);
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
/**
* 等待繁忙标志
*/
void wait(void)
{
P0 = 0xFF;
do
{
RS = 0;
RW = 1;
EN = 0;
EN = 1;
}while (STA7 == 1);
EN = 0;
}
/**
* 写数据
*/
void w_dat(uint dat)
{
wait();
EN = 0;
P0 = dat;
RS = 1;
RW = 0;
EN = 1;
EN = 0;
}
/**
* 写命令
*/
void w_cmd(uint cmd)
{
wait();
EN = 0;
P0 = cmd;
RS = 0;
RW = 0;
EN = 1;
EN = 0;
}
/**
* 发送字符串到LCD
*/
void write_zfc(uchar *p)//定义一个带指针的函数?(字符串)
{
while(*p!=0)//不能用";"
w_dat(*p++);
}
/**
* 初始化1602
*/
void Init_LCD1602(void)
{
w_cmd(0x38); // 16*2显示,5*7点阵,8位数据接口
w_cmd(0x0C); // 显示器开、光标开、光标允许闪烁
w_cmd(0x06); // 文字不动,光标自动右移
w_cmd(0x01); // 清屏
}
void main()
{
Init_LCD1602(); //LCD1602初始化
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)//20个定时为一秒钟
{
num=0;
num1++;
w_cmd(0xC0);//LCD1602显示地址为第一排第一个
write_zfc("NUM1:");
w_dat(num1/1000+0x30);
w_dat(num1%1000/100+0x30);
w_dat(num1%100/10+0x30);
w_dat(num1%10+0x30);
if(num1==6)//UNM==6时进入空闲或休眠模式
{
ET0=0;
PCON=0x02; //(或PCON=0x01;)
}
if(num1>20)//大于20秒就从头记数,又会进入UNM==6时进入空闲或休眠模式
{
num1=0;
}
}
w_cmd(0x80);//LCD1602显示地址为第一排第一个
write_zfc("NUM:");
w_dat(num/1000+0x30);
w_dat(num%1000/100+0x30);
w_dat(num%100/10+0x30);
w_dat(num%10+0x30);
}
}
void timer0() interrupt 1//定时器0 用来产生秒信号
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
}
void ex_int0() interrupt 0//外部中断P3.2 进行PCON=0;唤醒单片机 CPU
{
PCON=0;
ET0=1;
}
void ex_int1() interrupt 2//外部中断P3.3 进行PCON=0;唤醒单片机 CPU
{
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,(或者直接按下板子上的int0键),
数码管重新从“06”开始显示,递增下去。
整个过程演示了单片机从正常工作模式进入休眠模式或空闲模式,
然后再从休眠模式或空闲模式返回到正常工作模式。
(5)测试过程大家可将数字万用表调节到电流档,然后串接入电路中,
观察单片机在正常工作模式、休眠模式、空闲模式下流过系统的总电流变化情况,
经测试可发现结果如下:正常工作电流>空闲模式电流>休眠模式电流。
*/
全部资料51hei下载地址:
1602显并STC89空闲和休眠模式OK.zip
(40.95 KB, 下载次数: 20)
|