329008861 发表于 2024-3-21 11:59:02

关于STC8A8K64D4省电模式不能唤醒求教

#include "stc8a8k64d4.h"

#define   MAIN_Fosc       45000000   //定义主时钟

#define Timer0_Reload   (MAIN_Fosc / 1000)      //Timer 0 中断频率, 1000次/秒

#defineBacklightDelayDefaultValue 10

#define LCD_LED P50


int time1s = 0;
int BacklightDelay;


//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-3-9
// 备注:
//========================================================================
void delay1ms(u16 ms)
{
    u16 i;
    do
    {
      i = MAIN_Fosc / 10000;
      while(--i);   //10T per loop
    }
    while(--ms);
}

void GPIO_Init()
{
    LCD_LED = 0;
    P0M0 = 0x80;
    P0M1 = 0x66; //P01、P02、P05、P06模拟输入 P07推挽输出
    P1M0 = 0x01;
    P1M1 = 0x08; //P13模拟输入 P10推挽输出
    P2M1 = 0x00;
    P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;
    P3M0 = 0x00;   //设置为准双向口
    P4M0 = 0x00;
    P4M1 = 0x00; //P43推挽输出
    P5M0 = 0x01;
    P5M1 = 0x00; //P50推挽输出,设置为准双向口
    P6M1 = 0x00;
    P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;
    P7M0 = 0x00;   //设置为准双向口
}

//========================================================================
// 函数: void   Timer0_init(void)
// 描述: timer0初始化函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void    Timer0_init(void)
{
    TR0 = 0;    //停止计数

#if (Timer0_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
#error "Timer0设置的中断过快!"

#elif ((Timer0_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
    ET0 = 1;    //允许中断
    //PT0 = 1;    //高优先级中断
    TMOD &= ~0x03;
    TMOD |= 0;//工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
    //TMOD |=0x04;//对外计数或分频
    TMOD &= ~0x04;//定时
    //INT_CLKO |=0x01;//输出时钟
    INTCLKO &= ~0x01;//不输出时钟

#if (Timer0_Reload < 65536UL)
    AUXR |=0x80;//1T mode
    TH0 = (u8)((65536UL - Timer0_Reload) / 256);
    TL0 = (u8)((65536UL - Timer0_Reload) % 256);
#else
    AUXR &= ~0x80;//12T mode
    TH0 = (u8)((65536UL - Timer0_Reload / 12) / 256);
    TL0 = (u8)((65536UL - Timer0_Reload / 12) % 256);
#endif

    TR0 = 1;    //开始运行
                EA =1;
#else
#error "Timer0设置的中断过慢!"
#endif
}



//========================================================================
// 函数: void   SetWakeUpTime(u16 SetTime)
// 描述: 唤醒定时器设置时间值函数。
// 参数: SetTime: 要设置的时间值(睡眠的时间), 单位为ms.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-7-15
// 备注:
//========================================================================
void    SetWakeUpTime(u16 SetTime)
{
      if(SetTime >= 16000)      SetTime = 15999;      //限制最大值
      SetTime = (u16)(((u32)SetTime * 32768) / 16000);      //重装值 = Fwkt/16 * SetTime/1000 = Fwkt * SetTime / 16000
      if(SetTime > 0)      SetTime--;
      WKTCL = (u8)SetTime;
      WKTCH = (u8)(SetTime >> 8) | 0x80;
}

/******************** 主函数 **************************/
void main(void)
{
    GPIO_Init();


    BacklightDelay = BacklightDelayDefaultValue;

    Timer0_init();

    LCD_LED = 1;;//点亮背光

    while(1)
    {


      if(BacklightDelay)
      {
                if(!LCD_LED)
                {
                        LCD_LED = 1;
                }
      }
      else
      {
                if(LCD_LED)
                {
                        LCD_LED = 0;
                }

                SetWakeUpTime(10000);      //时间值 ms, 小于16000
                while(!P32);      //等待外中断为高电平
                delay1ms(10);      //delay 10ms
                IE0= 0;                //外中断0标志位
                IT0 = 1;                //INT0 下降沿中断               
                EX0 = 1;                //INT0 Enable
                EA= 1;                //Enable all interrupt
                                       
                PCON |= 0x02;      //Sleep
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                EX0 = 0;                //INT0 Disable
                BacklightDelay = BacklightDelayDefaultValue;
      }

    }
}

/********************* INT0中断函数 *************************/
void INT0_int (void) interrupt 0                //进中断时已经清除标志
{

}
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述:timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2015-1-12
//========================================================================
void timer0_int(void) interrupt 1
{
   time1s++;
   if (time1s>=1000)
   {
      time1s=0;
      if(BacklightDelay)
         BacklightDelay--;

   }
}

329008861 发表于 2024-3-21 12:05:41

要实现的功能就是10s钟后关闭背光,10秒钟后掉电唤醒背光,唤醒10秒,或者外部按键唤醒10秒,然后再次进入休眠状态。烧录板子调试的时候发现10秒钟后能进入睡眠状态,但是10秒钟后掉电唤醒不能正常唤醒,电流下降的1ma以下;如果这个时候用外部触发唤醒,电流上升到6ma,但是10秒钟后不会再次进入睡眠状态(电流还是6ma)。

329008861 发表于 2024-3-21 12:23:42

如果屏蔽掉外部中断唤醒,程序能正常10秒钟亮屏然后进入睡眠,10秒后唤醒,正常循环工作

神农鼎 发表于 2024-3-21 12:25:22

10秒,唤醒,用带RTC功能的 STC8H8K64U






神农鼎 发表于 2024-3-21 12:30:47


另外刚看到,你跑的是 40MHz








329008861 发表于 2024-3-21 12:30:59

神农鼎 发表于 2024-3-21 12:25
10秒,唤醒,用带RTC功能的 STC8H8K64U

我需要的不是准确的10秒唤醒,1到10秒都可以;现在遇到的问题是掉电唤醒定时器和外部中断唤醒一起用到时候,程序就跑飞了

神农鼎 发表于 2024-3-21 12:32:14

#define   MAIN_Fosc       45000000   //定义主时钟



1, 将上面的等待时间设到最长时间
2, 将下面的 NOP 等待时间设到最长时间

                PCON |= 0x02;      //Sleep
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();

                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();

                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();


                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();

329008861 发表于 2024-3-21 14:21:39

神农鼎 发表于 2024-3-21 12:32
#define   MAIN_Fosc       45000000   //定义主时钟



PCON |= 0x02;      //Sleep
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                              
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                                       
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                                       
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                                       
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                                       
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
                              
EX0 = 0;                //INT0 Disable
BacklightDelay = 3;//BacklightDelayDefaultValue; 新修改的地方


加了几个空操作后,确实是掉电唤醒定时器和外部中断都能唤醒,但是出现了新的问题:通过掉电唤醒定时器唤醒系统时,再次进入睡眠的时间是3秒;通过外部中断唤醒系统时,再次进入睡眠的时间是10秒,也就是说系统没进行到BacklightDelay = 3;这一步,直接是重新运行了。不知道我表达是否清楚了,这是怎么回事呢?

329008861 发表于 2024-3-21 14:45:40

329008861 发表于 2024-3-21 14:21
PCON |= 0x02;      //Sleep
_nop_();
_nop_();


/********************* INT0中断函数 *************************/
void INT0_int (void) interrupt 0                //进中断时已经清除标志
{
_nop_();
_nop_();
_nop_();
............
}
在外部中断里加了一堆空操作后程序正常运行了,感谢大神的解答

xxxevery 发表于 2024-3-21 15:35:06

看来中断唤醒后要给点时间让设备回复正常
页: [1] 2
查看完整版本: 关于STC8A8K64D4省电模式不能唤醒求教