Chinaunix首页 | 论坛 | 博客
  • 博客访问: 262383
  • 博文数量: 65
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-29 21:49
个人简介

Flowers_World

文章分类

全部博文(65)

文章存档

2017年(7)

2016年(38)

2015年(14)

2014年(6)

我的朋友

分类: 嵌入式

2016-05-25 10:19:27

/*****************************************
//说明:PM1和PM2和PM0的切换,用睡眠定时器(因为睡眠定时器计时时间到后,响应睡眠定时器中断,电源模式会自动从PM1/PM2切换到PM0)。在PM3下,睡眠定时器不起作用,因为32K的晶振都关闭了,故从PM3切换到PM0,用的是外部IO中断。


“设置睡眠定时器的定时间隔”这一步一定要在“设置电源模式”之前,因为进入睡眠后系统就不会继续执行程序了。

读取睡眠定时器的当前计数值,顺序必须遵循:读ST0 → 读ST1 → 读ST2

写入睡眠定时器的比较值,顺序必须遵循:写ST2 → 写ST1 → 写ST0

当定时器的计数值=比较值时,产生中断)

*****************************************/

#include
#define uint unsigned int
#define uchar unsigned char
#define uint8 unsigned char
#define uint32 unsigned long
#define LED_ON 0
#define LED_OFF 1

#define gled P1_0
#define rled P1_1
#define crystal 0   //石英晶振
#define rc      1   //RC晶振
#define s1      P0_1

//延时函数
void delay(uint n)
{  
  uint i,j;  
  for(i=0;i<50;i++)
    for(j=0;j }

void initKey(void)
{
  P0SEL &= ~0X02; 
  P0DIR &= ~0X02;
  
  P0IEN |= 0X02;
  IEN1 |= 0X20;
  EA = 1;
}

void initled(void)
{  
  P1SEL &= ~0X03; //P1_0,P1_1接口设为通用接口模式  
  P1DIR |= 0X03;  //P1_0,P1_1接口设为输出模式  
  rled = 1;  
  gled = 1;
}

//设置主时钟
void set_main_clock(source)
{  
  if(source)  
  {    
    CLKCONCMD |= 0X40;          //选择16MHZ RCOSC为系统时钟源    
    while(!(CLKCONSTA & 0X40)); //等待时钟稳定
  }else
  {    
    CLKCONCMD &= ~0X40;         //选择32MHZ XOSC为系统时钟源    
    while(CLKCONSTA & 0X40);    //等待时钟稳定
  }
}

//设置系统低速时钟
void set_low_clock(source)
{  
  if(source)   
    CLKCONCMD |= 0X80;  //选择32KHZ RCOSC为低速时钟源    
  else    
    CLKCONCMD &= ~0X80; //选择32KHZ XOSC为低速时钟源
}

//初始化睡眠定时器
void init_sleep_timer(void)
{  
  ST2 = 0X00;  
  ST1 = 0X00;  
  ST0 = 0X00; //设置计数值  
  EA = 1;     //开中断  
  STIE = 1;   //使能睡眠定时器中断  
  STIF = 0;   //清除睡眠定时器中断标志
}

//led闪烁函数
void blink_led(void)

  gled = 1;
  uchar jj = 10;  
  while(jj--)  
  {    
    rled = !rled;    
    delay(10000);  
  }
  rled = 1;
  gled = 0;
}

//设置睡眠时间
void set_st_period(uint sec)
{  
  uint32 sleeptimer = 0;  
  //把ST2:ST1:ST0赋值给sleeptimer  
  sleeptimer |= (uint32)ST0;  
  sleeptimer |= ((uint32)ST1 << 8);  
  sleeptimer |= ((uint32)ST2 << 16);
  sleeptimer += ((uint32)sec * (uint32)32768);  //低速频率为32.768KHZ,故每秒定时器计数32768次 如果低速时钟为32K呢    
  
  //把加N秒的计数值赋给ST2:ST1:ST0  
  ST2 = (uint8)(sleeptimer >> 16);  
  ST1 = (uint8)(sleeptimer >> 8);  
  ST0 = (uint8)sleeptimer;
}


void set_powermode(uchar mode)
{
  uchar i;
  if(mode<4)
  {
    SLEEPCMD &= ~0X03;
    SLEEPCMD |= mode;
    for(i=0;i<4;i++);      
    PCON = 1;
  }
  else
    PCON = 0;
}

void main(void)
{  
  set_main_clock(crystal);  
  set_low_clock(crystal);  
  initled();

  init_sleep_timer(); 
  
  gled = LED_ON;
  delay(50000);
  
  //进入PM1模式 
  gled = LED_OFF;
  set_st_period(5);
  set_powermode(1);
  rled = LED_ON;
  
  delay(50000);
  
  //进入PM2模式
  rled = LED_OFF;
  set_st_period(5);
  set_powermode(2);
  gled = LED_ON;
  delay(50000);

  gled = LED_OFF;
  initKey(); //初始化按键
  set_powermode(3);
  rled = LED_ON;
  while(1);
}

//睡眠定时器中断函数
#pragma vector = ST_VECTOR
__interrupt void ST_ISR(void)
{  
  EA = 0;
  STIF = 0;     //标志清除  
  EA = 1;
}

//P0中断函数
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{  
  EA = 0;
  P0IF = 0;
  P0IFG &= ~0X02;
  set_powermode(4);     //只要响应了IO中断,就会从PM1/PM2/PM3恢复到PM0,故本句也可以取消。

  EA = 1;
}

阅读(1323) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~