一、前言
C8051F340单片机包含一个可编程低频内部振荡器,该振荡器的标称频率为80KHz。该低频振荡器电路包含一个分频器,分频数由寄存器 OSCLCN 中的 OSCLD 位设定,OSCLF 位可用于调节该振荡器的输出频率。
本文模拟单片机进入休眠模式,只有低频振荡器和定时器0
二、程序展示
1、头文件部分
#include <c8051F340.h>
#define SLEEP_TIME 10000 //睡眠时间
#define BLINK_TIME 1000 //闪烁时间
void OSC_Init (void);
void PORT_Init (void);
void lowPowerSleep (unsigned int);
void configMCU_Sleep (void);
void configMCU_Wake (void);
void delay (unsigned int);
void T0_ISR (void);
sbit LED = P2^3;
2、主程序部分
void main (void)
{
PCA0MD &= ~0x40;
PCA0MD = 0x00;
OSC_Init();
PORT_Init();
EA = 1; //开中断
while(1)
{
lowPowerSleep(SLEEP_TIME);
LED = 1;
delay(1000);
LED = 0;
}
}
3、端口初始化程序
void Port_Init ()
{
P2MDOUT = 0x08; //设置P2.3推挽输出
XBR1 |= 0x40;
}
4、振荡器初始程序
void OSC_Init ()
{
OSCICN = 0x83; //内部24.5M允许
}
5、idle睡眠程序
void lowPowerSleep (unsigned int time)
{
unsigned char restoreIE;
unsigned char restoreEIE1;
EA = 0; // 关闭中断
restoreIE = IE; // 保存IE寄存器
restoreEIE1 = EIE1; // 保存EIE1寄存器
IE = 0x00; //关闭所有中断
EIE1 = 0x00; //关闭外部中断
configMCU_Sleep (); //配置为睡眠模式
TCON &= ~0x30; //停止T0,清标志
TMOD &= ~0x0F;
TMOD |= 0x01; // T0 16为计时器
CKCON |= 0x04; // T0使用系统时钟
time = -time;
TL0 = (unsigned char)(time & 0x00FF);
TH0 = (unsigned char)(time >> 8);
IE |= 0x82;
OSCLCN = 0x80; // 设置低频模式 10Hz
CLKSEL = 0x04; // 切换到低频模式
OSCICN = 0x00; //停止内部振荡器省电
TCON |= 0x10; // 允许 T0
PCON |= 0x01; //省电模式
PCON = PCON;
configMCU_Wake (); //唤醒程序
EIE1 = restoreEIE1; // 恢复外部中断
IE = restoreIE; // 恢复中断
EA = 1; // 允许中断
}
6、单片机睡眠程序
void configMCU_Sleep (void)
{
XBR1 &= ~0xC0 // 设置推挽输出
SCON0 &= ~0x10; //禁止串口
TCON &= ~0x40; //禁止T1
TMR2CN &= ~0x04; // 禁止T2
VDM0CN &= ~0x80; // 禁止电压监控
}
7、单片机唤醒程序
void configMCU_Wake (void)
{
VDM0CN |= 0x80; //允许电压监控
XBR1 |= 0x40;
}
8、延时程序
void delay (unsigned int time)
{
TCON &= ~0x30; //停止T0,清标志
TMOD &= ~0x0F;
TMOD |= 0x01; // T0 16位模式
CKCON |= 0x04; // T0使用系统时钟
time = -time;
TL0 = (unsigned char)(time & 0x00FF);
TH0 = (unsigned char)(time >> 8);
OSCLCN = 0x80; //设置低频 10 kHz
CLKSEL = 0x04; //选择低频
TCON |= 0x10; //允许T0
while (!TF0); //等到TOF置位
TCON &= ~0x30; //清T0标志
OSCICN = 0x83; // 允许24.5M时钟
CLKSEL = 0x00; // 使用内部时钟
}
9、定时器0中断程序
void T0_ISR (void) interrupt 1
{
OSCICN = 0x83; // 允许内部24.5 MHz 时钟
while ((OSCICN & 0x40) == 0); // 查询等待
CLKSEL = 0x00; // 使用内部时钟
TCON &= ~0x10; // 停止定时器0
IE &= ~0x02; // 禁止T0中断
}