增加深度睡眠、停止、待机三种低功耗模式,借助看门狗唤醒
This commit is contained in:
parent
e560a40b15
commit
e3c576d191
32
RTC.cpp
32
RTC.cpp
|
@ -284,27 +284,32 @@ int HardRTC::Sleep(int ms)
|
|||
RTC_AlarmStructInit(&alr);
|
||||
|
||||
int second = ms / 1000;
|
||||
int minute = second / 60;
|
||||
|
||||
RTC_AlarmCmd( RTC_Alarm_A, DISABLE ); /* Disable the Alarm A */
|
||||
alr.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
|
||||
alr.RTC_AlarmTime.RTC_Hours = second / 60 / 60;
|
||||
alr.RTC_AlarmTime.RTC_Minutes = (second / 60) % 60;
|
||||
alr.RTC_AlarmTime.RTC_Seconds = second % 60;
|
||||
// 关闭警报
|
||||
RTC_AlarmCmd( RTC_Alarm_A, DISABLE );
|
||||
alr.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
|
||||
alr.RTC_AlarmTime.RTC_Hours = minute / 60;
|
||||
alr.RTC_AlarmTime.RTC_Minutes = minute % 60;
|
||||
alr.RTC_AlarmTime.RTC_Seconds = second % 60;
|
||||
|
||||
/* Set the Alarm A */
|
||||
alr.RTC_AlarmDateWeekDay = 0x31;
|
||||
alr.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
|
||||
// 设置警报
|
||||
alr.RTC_AlarmDateWeekDay = 31;
|
||||
alr.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
|
||||
alr.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
|
||||
|
||||
RTC_SetAlarm( RTC_Format_BIN, RTC_Alarm_A, &alr ); /* Configure the RTC Alarm A register */
|
||||
RTC_SetAlarm( RTC_Format_BIN, RTC_Alarm_A, &alr );
|
||||
|
||||
RTC_ITConfig( RTC_IT_ALRA, ENABLE ); /* Enable the RTC Alarm A Interrupt */
|
||||
// 打开警报中断
|
||||
RTC_ITConfig( RTC_IT_ALRA, ENABLE );
|
||||
|
||||
RTC_AlarmCmd( RTC_Alarm_A, ENABLE ); /* Enable the alarm A */
|
||||
// 打开警报
|
||||
RTC_AlarmCmd( RTC_Alarm_A, ENABLE );
|
||||
#endif
|
||||
/* Wait until last write operation on RTC registers has finished */
|
||||
// 等待写入操作完成
|
||||
RTC_WaitForLastTask2();
|
||||
|
||||
Sys.Trace(1);
|
||||
// 进入低功耗模式
|
||||
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
|
||||
|
||||
|
@ -370,6 +375,7 @@ void AlarmHandler(ushort num, void* param)
|
|||
{
|
||||
SmartIRQ irq;
|
||||
|
||||
Sys.Trace(4);
|
||||
HardRTC* rtc = (HardRTC*)param;
|
||||
|
||||
if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
|
||||
|
@ -384,7 +390,7 @@ void AlarmHandler(ushort num, void* param)
|
|||
SYSCLKConfig_STOP();
|
||||
rtc->LoadTicks();
|
||||
|
||||
//debug_printf("离开低功耗模式\r\n");
|
||||
debug_printf("离开低功耗模式\r\n");
|
||||
}
|
||||
|
||||
HardRTC* HardRTC::Instance()
|
||||
|
|
27
Sys.cpp
27
Sys.cpp
|
@ -432,6 +432,33 @@ bool TSys::SetTaskPeriod(uint taskid, int period)
|
|||
|
||||
void TSys::Reset() { NVIC_SystemReset(); }
|
||||
|
||||
#include "WatchDog.h"
|
||||
|
||||
void TSys::Stop(uint msTime)
|
||||
{
|
||||
debug_printf("TSys::Stop Time=%d \r\n", msTime);
|
||||
|
||||
if(!msTime) msTime = 0xFFFF;
|
||||
WatchDog::Start(msTime);
|
||||
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
|
||||
}
|
||||
|
||||
void TSys::DeepSleep(uint msTime)
|
||||
{
|
||||
debug_printf("TSys::DeepSleep Time=%d \r\n", msTime);
|
||||
|
||||
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
|
||||
}
|
||||
|
||||
void TSys::Standby(uint msTime)
|
||||
{
|
||||
debug_printf("TSys::Standby Time=%d \r\n", msTime);
|
||||
|
||||
if(!msTime) msTime = 0xFFFF;
|
||||
WatchDog::Start(msTime);
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
void TSys::Start()
|
||||
{
|
||||
Started = true;
|
||||
|
|
4
Sys.h
4
Sys.h
|
@ -121,6 +121,10 @@ public:
|
|||
|
||||
bool Started;
|
||||
void Start(); // 开始系统大循环
|
||||
|
||||
void Stop(uint msTime = 0);
|
||||
void DeepSleep(uint msTime = 0);
|
||||
void Standby(uint msTime = 0);
|
||||
};
|
||||
|
||||
extern TSys Sys; //创建一个全局的Sys对象 会在main函数之前执行构造函数(!!!!!)
|
||||
|
|
97
WatchDog.cpp
97
WatchDog.cpp
|
@ -59,13 +59,8 @@ WatchDog::~WatchDog()
|
|||
ConfigMax();
|
||||
}
|
||||
|
||||
bool WatchDog::Config(uint ms)
|
||||
void OpenWatchDog()
|
||||
{
|
||||
if(ms == 0)
|
||||
{
|
||||
debug_printf("WatchDog msTimeout %dms must larger than 0ms\r\n", ms);
|
||||
return false;
|
||||
}
|
||||
RCC_LSICmd(ENABLE);
|
||||
/* 检查系统是否从IWDG重置恢复 */
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
|
||||
|
@ -75,6 +70,49 @@ bool WatchDog::Config(uint ms)
|
|||
}
|
||||
/* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
}
|
||||
|
||||
void SetWatchDog(byte pre, uint reload)
|
||||
{
|
||||
IWDG_SetPrescaler(pre);
|
||||
/*if(ms < (0x0FFF * 32 / 40))
|
||||
{
|
||||
// IWDG计数器时钟: LSI/32=40KHz/32=1250Hz,每周期0.8ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IWDG计数器时钟: LSI/64=40KHz/64=625Hz,每周期0.4ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_64);
|
||||
|
||||
// 直接除以2,后面不用重复计算
|
||||
ms >>= 2;
|
||||
}*/
|
||||
|
||||
/* 设置计数器重载值为超时时间
|
||||
Counter Reload Value = ms / 1000 / IWDG计数器时钟周期
|
||||
= ms / 1000 / (1/(LSI/mul))
|
||||
= ms * LSI / (mul * 1000)
|
||||
= ms * 40k / (mul * 1000)
|
||||
= ms * 40 / mul
|
||||
*/
|
||||
IWDG_SetReload(reload);
|
||||
|
||||
/* 重载 IWDG 计数器 */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* 打开 IWDG (LSI将由硬件打开) */
|
||||
IWDG_Enable();
|
||||
}
|
||||
|
||||
bool WatchDog::Config(uint ms)
|
||||
{
|
||||
if(ms == 0)
|
||||
{
|
||||
debug_printf("WatchDog msTimeout %dms must larger than 0ms\r\n", ms);
|
||||
return false;
|
||||
}
|
||||
OpenWatchDog();
|
||||
|
||||
byte pre = IWDG_Prescaler_4;
|
||||
int mul = 4;
|
||||
|
@ -103,20 +141,6 @@ bool WatchDog::Config(uint ms)
|
|||
debug_printf("WatchDog msTimeout must smaller than %dms\r\n", 0x0FFF * 256 / 40);
|
||||
return false;
|
||||
}
|
||||
IWDG_SetPrescaler(pre);
|
||||
/*if(ms < (0x0FFF * 32 / 40))
|
||||
{
|
||||
// IWDG计数器时钟: LSI/32=40KHz/32=1250Hz,每周期0.8ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IWDG计数器时钟: LSI/64=40KHz/64=625Hz,每周期0.4ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_64);
|
||||
|
||||
// 直接除以2,后面不用重复计算
|
||||
ms >>= 2;
|
||||
}*/
|
||||
|
||||
/* 设置计数器重载值为超时时间
|
||||
Counter Reload Value = ms / 1000 / IWDG计数器时钟周期
|
||||
|
@ -125,13 +149,7 @@ bool WatchDog::Config(uint ms)
|
|||
= ms * 40k / (mul * 1000)
|
||||
= ms * 40 / mul
|
||||
*/
|
||||
IWDG_SetReload(ms * 40 / mul);
|
||||
|
||||
/* 重载 IWDG 计数器 */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* 打开 IWDG (LSI将由硬件打开) */
|
||||
IWDG_Enable();
|
||||
SetWatchDog(pre, ms * 40 / mul);
|
||||
|
||||
Timeout = ms;
|
||||
|
||||
|
@ -140,13 +158,11 @@ bool WatchDog::Config(uint ms)
|
|||
|
||||
void WatchDog::ConfigMax()
|
||||
{
|
||||
/* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
OpenWatchDog();
|
||||
|
||||
// 独立看门狗无法关闭
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_256);
|
||||
IWDG_SetReload(0x0FFF);
|
||||
IWDG_ReloadCounter();
|
||||
SetWatchDog(IWDG_Prescaler_256, 0x0FFF);
|
||||
|
||||
Timeout = 0x0FFF * 256 / 40;
|
||||
}
|
||||
|
||||
void WatchDog::Feed()
|
||||
|
@ -163,11 +179,16 @@ void FeedDogTask(void* param)
|
|||
void WatchDog::Start(uint ms, uint msFeed)
|
||||
{
|
||||
static WatchDog dog;
|
||||
dog.Config(ms);
|
||||
static uint tid = 0;
|
||||
|
||||
// 减小一点,避免来不及喂狗
|
||||
//int us = msFeed * 1000;
|
||||
if(ms > 0x0FFF)
|
||||
dog.ConfigMax();
|
||||
else
|
||||
dog.Config(ms);
|
||||
|
||||
debug_printf("WatchDog::Start ");
|
||||
Sys.AddTask(FeedDogTask, &dog, msFeed, msFeed, "看门狗");
|
||||
if(!tid && msFeed > 0 && msFeed <= 26000)
|
||||
{
|
||||
debug_printf("WatchDog::Start ");
|
||||
tid = Sys.AddTask(FeedDogTask, &dog, msFeed, msFeed, "看门狗");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue