STOP休眠模式
#include "stm32f10x_conf.h"
#include "bsp_include.h"
uint8_t GeneralAwakeFlag = 0; //退出休眠标志
Sleep_Struct SleepStruct;
//*************************************************进入STOP休眠后RTC唤醒配置
static void RTC_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSICmd(ENABLE); /*使用内部40K振荡器*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // 配置内部时钟
RCC_RTCCLKCmd(ENABLE); /*使能RTC*/
RTC_WaitForSynchro(); /*等待时钟同步*/
RTC_WaitForLastTask(); /*等待写操作完成*/
RTC_SetPrescaler(40000); /*1秒计数*/
RTC_WaitForLastTask();
}
static void RTC_Alarm_EXTI_Config(uint16_t sec)
{/*配置RTC闹钟事件到中断17*/
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
RTC_SetAlarm(RTC_GetCounter()+sec);/*设置N秒后唤醒*/
RTC_WaitForLastTask();
}
static void RTC_Alarm_NVIC_Config(void)
{/*配置RTC闹钟中断*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RTC_ITConfig(RTC_IT_ALR, ENABLE);/*使能中断*/
RTC_WaitForLastTask();
}
void RTC_IRQHandler(void)
{// RTC中断
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
RTC_ClearITPendingBit(RTC_IT_SEC);
RTC_WaitForLastTask();
}
}
void RTCAlarm_IRQHandler(void)
{// RTC告警中断
if(RTC_GetFlagStatus(RTC_IT_ALR))
{
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_WaitForLastTask();
EXTI_ClearITPendingBit(EXTI_Line17);/*清除闹钟中断*/
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
PWR_ClearFlag(PWR_FLAG_WU);/*清除唤醒标志*/
}
}
}
//*************************************************RTC唤醒配置
//static void LowPower_InStandby(void)
//{/*进入待机模式,待机模式下唤醒,程序复位运行*/
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
// RTC_Configuration(); /*配置RTC时钟*/
// RTC_Alarm_EXTI_Config(10); /*配置闹钟唤醒*/
// //PWR_WakeUpPinCmd(ENABLE); /*使能WAKEUP脚唤醒*/
// IWDG_Config(); /*使用独立看门狗唤醒*/
// PWR_EnterSTANDBYMode(); /*进入待机模式*/
//}
//中断配置,只需要配置唤醒的中断
static void Wake_EXTI_Intit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 设置中断向量表是在RAM中或是flash中,并指出器偏移量 */
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
#ifdef USER_BOOTLOADER
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2000); // 中断向量偏移
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// PA0 充电唤醒中断配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;//GPIO_Mode_AIN GPIO_Mode_IN_FLOATING
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//EXTI_Mode_Event EXTI_Mode_Interrupt
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line0);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// PA1 通信唤醒口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;//GPIO_Mode_AIN GPIO_Mode_IN_FLOATING
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//EXTI_Mode_Event EXTI_Mode_Interrupt
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// RTC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//休眠前管脚关闭或开启
void ALL_GPIO_Sleep_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//预充
RCC_APB2PeriphClockCmd(PRECHARGE_APB,ENABLE);
GPIO_InitStructure.GPIO_Pin = PRECHARGE_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(PRECHARGE_PORT, &GPIO_InitStructure);
Relay_PreChargeOff(0);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOF, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/*放电mos控制*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIOA->BSRR = GPIO_Pin_10;// 打开放电mos
// 单片机给运放供电
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIOB->BSRR = GPIO_Pin_3;// 打开放电mos
}
#if INSERT_DOG_ENABLE /*使用内部看门狗*/
/**
* @brief 独立看门狗配置
* @param NONE
* @retval NONE
*/
void WatchDog_Config(void)
{ /*看门狗配置*/
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
;
}
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_256); /*设置为秒超时复位*/
IWDG_SetReload(0xfff);
while (IWDG_GetFlagStatus(IWDG_FLAG_PVU) == RESET)
{
;
}
IWDG_Enable();
}
#endif
//休眠设置
void InsertLowpowerInit(void)
{
uint8_t ReadBackWatchdogFlag;
ReadBackWatchdogFlag = ReadLowPowerFlag();
if (ReadBackWatchdogFlag == LowPowerFlagValue)
{// 进入深度休眠
EnableInterrupt(); /*硬件初始化完成后开总中断*/
Re_LowPower_SEEP();
}
else
{
WatchDog_Config();
}
}
/******************************ADC通道配置**********************************/
#define ADC1_DR_Address ((uint32_t)0x4001244C) /*!<ADC数据寄存器地址*/
#define ADC_CHANN_INUSE_NUM 1 /*!<ADC通道使用数*/
static uint16_t ADCValueBuf[ADC_CHANN_INUSE_NUM]; /*!<采集数据缓存*/
static const uint8_t TempChnnaIndex[]={0};
static const uint8_t Sel_ADC_Chann[ADC_CHANN_INUSE_NUM]=
{
ADC_Channel_6//,ADC_Channel_7,
};/*!<温度采集通道*/
/**
* @brief ADC采集通道引脚配置
* @param NONE
* @retval NONE
*/
uint8_t EnterLowPower = 0; // 进入普通休眠标志
static void ADC_ChannelPin_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /*模拟输入*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//|GPIO_Pin_7; /*PA7*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**
* @brief ADC模块初始化
* @param NONE
* @retval NONE
*/
void ADC_Mode_Init()
{
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /*打开ADC时钟*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; /*通道扫描模式*/
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ENABLE; /*连续转换模式*/
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /*数据右对齐*/
ADC_InitStructure.ADC_NbrOfChannel = ADC_CHANN_INUSE_NUM; /*通道个数*/
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, Sel_ADC_Chann[0], 1, ADC_SampleTime_239Cycles5);
ADC_Cmd(ADC1, ENABLE); /*打开ADC*/
ADC_StartCalibration(ADC1); /*启动ADC校准*/
while(ADC_GetCalibrationStatus(ADC1)); /*等待校准完成*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*开始ADC数据采集*/
}
/**
* @brief ADC模块初始化
* @param NONE
* @retval NONE
*/
static void ADC_Module_Init(void)
{
ADC_ChannelPin_Config();
ADC_Mode_Init();
}
// 延时
static void _Delay_Nms_My(uint16_t Nms)
{
uint16_t i=0,j=0;
while(i<Nms)
{
i++;
#if SYSTEMCLOCK_24M
j=4800;/*系统时钟24M*/
#else
//j=1600;/*系统时钟8M*/
j = 800;
#endif
while(j)
{
j--;
}
}
}
// 获取ADC采集数据
u16 Get_Adc(u8 ch)
{
u16 dat = 0;
_Delay_Nms_My(200);
dat = ADC_GetConversionValue(ADC1);
return dat; //返回最近一次ADC1规则组的转换结果
}
static RegisterGroup BQ940RegDat; /*!<寄存器数据*/
static uint8_t BQ940_ChipFunctionConfig(void)
{
uint8_t res = TRUE;
BQ940RegDat.SysCtrl1.Byte = 0;/*控制寄存器数据清零*/
BQ940RegDat.SysCtrl2.Byte = 0;/*控制寄存器数据清零*/
BQ940RegDat.SysCtrl1.Bits.ADC_EN = 0;/*不使能ADC*/
BQ940RegDat.SysCtrl2.Bits.DSG_ON = 1; // 放电mos打开
BQ940RegDat.SysCtrl2.Bits.CC_EN = 0;/*使能电流采集*/
BQ940RegDat.SysCtrl1.Byte = BQ940_WriteRegDat(REG_SYS_CTRL1,BQ940RegDat.SysCtrl1.Byte);
BQ940RegDat.SysCtrl2.Byte = BQ940_WriteRegDat(REG_SYS_CTRL2,BQ940RegDat.SysCtrl2.Byte);
return res;
}
static uint8_t SleepCnt = 0;
void Re_LowPower(void)
{
uint8_t i;
uint8_t sleep_cnt = 0;
uint8_t SaveInsertWdg;
float adc_val = 0;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
#if INSERT_DOG_ENABLE/*使用内部看门狗*/
SaveInsertWdg = SleepFlagClear;
#endif
ALL_GPIO_Sleep_Init(); // 进入休眠一脚配置
ADC_Cmd(ADC1, DISABLE);
DMA_Cmd(DMA1_Channel1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE); /*关闭ADC时钟*/
while(1)
{
Wake_EXTI_Intit();
SleepStruct.sleep_flag = 1;
/* RTC唤醒配置 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
RTC_Alarm_NVIC_Config();
RTC_Configuration(); /*配置RTC时钟*/
RTC_Alarm_EXTI_Config(5); /*配置闹钟唤醒*/
FeedInsertWatchDog();
SysTick->CTRL = 0x00; // 需要关闭滴答定时器,否则中断会唤醒
SysTick->VAL = 0x00;
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);// 进入休眠
//------------------------------------通信中断关闭
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//EXTI_Mode_Event EXTI_Mode_Interrupt
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line0);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&NVIC_InitStructure);
//------------------------------------通信中断关闭
/* 休眠唤醒计数 */
SleepCnt++;
if(SleepCnt>84)// 根据看门狗定时唤醒时间定
{// 计数唤醒
NVIC_SystemReset();
return;
}
ADC_Module_Init();
adc_val = Get_Adc(0);
adc_val = adc_val*0.8056640625; // 测得电压
if( (adc_val > 800) // 检测到有电流,唤醒78
||(SleepStruct.sleep_flag == 0)
)
{// 电压大于400 = 0.4v
NVIC_SystemReset();
return;
}
}
}
/*
*休眠模式:停止模式(普通休眠)
*/
void LowPower(void)
{
uint8_t SaveInsertWdg;
if(GetSystemRunTimer()>10000)
{
Cap_SaveSocDat(); // 数据保存
}
BQ940_Power_Manage(BQ940_SLEEP_CMD); // 940关闭
#if INSERT_DOG_ENABLE
WriteSleepFlag(SleepFlagValue);
SaveInsertWdg = SleepFlagValue;
SleepStruct.sleep_flag = 1;
#endif
Re_LowPower();
}
STANDBY休眠模式
/*
* 深度休眠
*/
void LowPower_SEEP(void)
{
uint8_t SaveInsertWdg;
if(GetSystemRunTimer()>10000)
{
Cap_SaveSocDat(); // 数据保存
}
BQ940_Power_Manage(BQ940_SLEEP_CMD); // 关闭940
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
#if INSERT_DOG_ENABLE /*使用内部看门狗*/
SaveInsertWdg = SleepFlagValue;
WriteLowPowerFlag(SaveInsertWdg);
#endif
PWR_WakeUpPinCmd(ENABLE); /*使能WAKEUP脚唤醒*/
_Delay_Nms(500);
FeedWatchDog(); // 喂狗
NVIC_SystemReset(); // 复位
PWR_EnterSTANDBYMode(); /*进入待机模式*/
}
void Re_LowPower_SEEP(void)
{
WriteLowPowerFlag(LowPowerFlagClear); // 清除进入休眠标志位
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
PWR_WakeUpPinCmd(ENABLE); /*使能WAKEUP脚唤醒*/
_Delay_Nms(100);
PWR_EnterSTANDBYMode(); /*进入待机模式*/
}
//休眠设置
void InsertLowpowerInit(void)
{
uint8_t ReadBackWatchdogFlag;
ReadBackWatchdogFlag = ReadLowPowerFlag(); // 获取进入休眠标志位
if (ReadBackWatchdogFlag == LowPowerFlagValue)
{// 进入深度休眠
EnableInterrupt(); /*硬件初始化完成后开总中断*/
Re_LowPower_SEEP();
}
else
{
WatchDog_Config();
}
}