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