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(); }}