STM32_WGY/User/rtc_wakeup.c

742 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "includes.h"
#include "drv_dtu.h"
#include "drv_gps.h"
RTC_HandleTypeDef hrtc;
// 当前工作模式
uint8_t Wakeup_workMode = WORK_MODE_NORMAL;
// 电量极低标志
uint8_t bat_veryLow = 0;
// 休眠标识
volatile uint8_t Wakeup_Sleeping = 0;
// 实际启动时间和INITIAL_YEAR相差的秒数当GPS定位或GPRS连接基站以后设置
volatile uint32_t RTC_offsetSeconds = 0;
// 获取日期时间输出格式为Nuvoton芯片格式
void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *sRTC)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
sRTC->u32Year = sDate.Year + RTC_YEAR2000;
sRTC->u32Month = sDate.Month;
sRTC->u32Day = sDate.Date;
if(sDate.WeekDay == RTC_WEEKDAY_SUNDAY)
sRTC->u32DayOfWeek = 0;
else
sRTC->u32DayOfWeek = sDate.WeekDay;
sRTC->u32Hour = sTime.Hours;
sRTC->u32Minute = sTime.Minutes;
sRTC->u32Second = sTime.Seconds;
sRTC->u32TimeScale = RTC_CLOCK_24;
}
// 设置日期时间输入格式为Nuvoton芯片格式
void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *sRTC)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
sDate.Year = sRTC->u32Year - RTC_YEAR2000;
sDate.Month = sRTC->u32Month;
sDate.Date = sRTC->u32Day;
if(sRTC->u32DayOfWeek == RTC_SUNDAY)
sDate.WeekDay = RTC_WEEKDAY_SUNDAY;
else
sDate.WeekDay = sRTC->u32DayOfWeek;
sTime.Hours = sRTC->u32Hour;
sTime.Minutes = sRTC->u32Minute;
sTime.Seconds = sRTC->u32Second;
sTime.SubSeconds = 0;
sTime.TimeFormat = RTC_HOURFORMAT_24;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
}
void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *sRTC)
{
uint8_t try_count = 3;
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours = sRTC->u32Hour;
sAlarm.AlarmTime.Minutes = sRTC->u32Minute;
sAlarm.AlarmTime.Seconds = sRTC->u32Second;
sAlarm.AlarmTime.SubSeconds = 0;
sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT_24;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = sRTC->u32Day;
sAlarm.Alarm = RTC_ALARM_A;
while(try_count--)
{
if(HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) == HAL_OK)
break;
delay_ms(10);
}
}
void RTC_SetAlarmDateAndTime_B(S_RTC_TIME_DATA_T *sRTC)
{
uint8_t try_count = 3;
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours = sRTC->u32Hour;
sAlarm.AlarmTime.Minutes = sRTC->u32Minute;
sAlarm.AlarmTime.Seconds = sRTC->u32Second;
sAlarm.AlarmTime.SubSeconds = 0;
sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT_24;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = sRTC->u32Day;
sAlarm.Alarm = RTC_ALARM_B;
while(try_count--)
{
if(HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) == HAL_OK)
break;
delay_ms(10);
}
}
void Wakeup_ShowTime(char *preStr, S_RTC_TIME_DATA_T *pRTC)
{
S_RTC_TIME_DATA_T sRTC;
uint32_t totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, pRTC->u32Year, pRTC->u32Month, pRTC->u32Day,
pRTC->u32Hour, pRTC->u32Minute, pRTC->u32Second);
totalSeconds += RTC_offsetSeconds;
Wakeup_CalcUTCTime(totalSeconds, &sRTC);
printf("\n%s%04d-%02d-%02d %02d:%02d:%02d\n", preStr, sRTC.u32Year, sRTC.u32Month,
sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
}
// 判断是否闰年
uint8_t IsLeapYear(uint16_t year)
{
if(year % 4)
return 0;
if(year % 100 == 0 && year % 400)
return 0;
return 1;
}
// 计算从某年开始以来经过的秒数
uint32_t Calc_SecondsFromYear(uint16_t startYear, uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
{
uint32_t totalSeconds = 0ul;
uint16_t i;
// 计算整年的
for(i = startYear; i < year; i++)
{
totalSeconds += 31536000ul; // 365 * 86400
if(IsLeapYear(i)) // 闰年+1天
totalSeconds += 86400ul;
}
// 计算整月的
for(i = 1; i < mon; i++)
{
totalSeconds += 2678400ul; // 31 * 86400
if(i == 4 || i == 6 || i == 9 || i == 11)
totalSeconds -= 86400ul;
else if(i == 2)
{
totalSeconds -= 259200ul; // 3 * 86400
if(IsLeapYear(year)) // 闰年+1天
totalSeconds += 86400ul;
}
}
// 计算整天的
totalSeconds += (day - 1) * 86400ul;
// 计算时分秒的
totalSeconds += hour * 3600ul;
totalSeconds += min * 60ul;
totalSeconds += sec;
return totalSeconds;
}
uint16_t get_year_days(uint16_t year)
{
if(IsLeapYear(year))
return 366;
return 365;
}
uint16_t get_month_days(uint16_t year, uint8_t month)
{
if(month == 4 || month == 6 || month == 9 || month == 11)
return 30;
if(month == 2)
{
if(IsLeapYear(year))
return 29;
return 28;
}
return 31;
}
// 将从INITIAL_YEAR开始的描述转换成年月日
void Wakeup_CalcUTCTime(uint32_t totalSeconds, S_RTC_TIME_DATA_T *pRTC)
{
uint32_t totalDays, days;
// 计算下次唤醒的年、月、日
pRTC->u32Year = INITIAL_YEAR;
pRTC->u32Month = 1;
pRTC->u32Day = 1;
totalDays = totalSeconds / 86400ul;
while(totalDays >= 1)
{
// 计算整年的
days = get_year_days(pRTC->u32Year);
if(totalDays >= days)
{
pRTC->u32Year++;
totalDays -= days;
continue;
}
// 计算整月的
days = get_month_days(pRTC->u32Year, pRTC->u32Month);
if(totalDays >= days)
{
pRTC->u32Month++;
totalDays -= days;
continue;
}
// 计算整天
pRTC->u32Day += totalDays;
break;
}
// 计算下次唤醒的时、分、秒
totalSeconds %= 86400ul;
pRTC->u32Hour = totalSeconds / 3600ul;
totalSeconds %= 3600;
pRTC->u32Minute = totalSeconds / 60ul;
totalSeconds %= 60ul;
pRTC->u32Second = totalSeconds;
}
uint32_t Wakeup_CalcPeriod(uint8_t charging)
{
uint32_t period = 300;
if(dcBuff.configData.intervalTrans > 0 && period > dcBuff.configData.intervalTrans)
period = dcBuff.configData.intervalTrans;
if(dcBuff.configData.intervalSample > 0 && period > dcBuff.configData.intervalSample)
period = dcBuff.configData.intervalSample;
// 无外供电采集频率不能快于1分钟
if((!VCC_POWER_STATUS() || (dcBuff.configDisplay.op_USE_SOLAR && dcBuff.dtuData.batVoltage <= 4500)) && period < 60)
period = 60;
if(dcBuff.configDisplay.op_ANTI_OVERFILL && Charge_Enabled && period > 10)
period = 10;
if(Manual_Charing && period > 10)
period = 10;
if(charging && period > 60)
period = 60;
// 在外供电时1分钟
if(VCC_POWER_STATUS() && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500) && period > 60)
period = 60;
return period;
}
// 计算下次唤醒的时间
void Wakeup_CalcWakeupTime(S_RTC_TIME_DATA_T *pRTC, uint8_t charging)
{
uint32_t period = Wakeup_CalcPeriod(charging);
// 先计算从初始时间以来的秒数
uint32_t totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, pRTC->u32Year, pRTC->u32Month, pRTC->u32Day,
pRTC->u32Hour, pRTC->u32Minute, pRTC->u32Second);
// 多路切换显示
//if(MeterNeedRoll() && period > 10)
if(period<30)
period = 30;
// 计算下次唤醒时间的秒数
// 将这个秒数对齐到唤醒周期的倍数
// 这是因为:每次复位以后虽然时间是继续的,但闹钟需要重新设置
uint32_t sec = totalSeconds + period;
sec -= sec % period;
// 防止闹钟时间太近
if(sec <= totalSeconds + 2)
totalSeconds = sec + period;
else
totalSeconds = sec;
// 计算下次唤醒的年、月、日
Wakeup_CalcUTCTime(totalSeconds, pRTC);
}
// 计算下次唤醒的时间
void Wakeup_CalcWakeupTime_B(S_RTC_TIME_DATA_T *pRTC)
{
// 先计算从初始时间以来的秒数
uint32_t totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, pRTC->u32Year, pRTC->u32Month, pRTC->u32Day,
pRTC->u32Hour, pRTC->u32Minute, pRTC->u32Second);
// 计算下次唤醒时间的秒数
totalSeconds += 15;
// 计算下次唤醒的年、月、日
Wakeup_CalcUTCTime(totalSeconds, pRTC);
}
// 设定下次闹钟唤醒时间
void Wakeup_SetAlarm(uint8_t charging)
{
S_RTC_TIME_DATA_T sRTC;
// 设定下次闹钟唤醒时间
RTC_GetDateAndTime(&sRTC);
// 显示当前时间
Wakeup_ShowTime("RTC time is: ", &sRTC);
Wakeup_CalcWakeupTime(&sRTC, charging);
RTC_SetAlarmDateAndTime(&sRTC);
// 显示唤醒时间
Wakeup_ShowTime("***********************************************\nWakeup time is: ", &sRTC);
}
// 设定下次闹钟唤醒时间
void Wakeup_SetAlarm_B()
{
S_RTC_TIME_DATA_T sRTC;
// 设定下次闹钟唤醒时间
RTC_GetDateAndTime(&sRTC);
Wakeup_CalcWakeupTime_B(&sRTC);
RTC_SetAlarmDateAndTime_B(&sRTC);
}
/**
* @brief Alarm A callback.
* @param hrtc RTC handle
* @retval None
*/
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
S_RTC_TIME_DATA_T sRTC;
static uint32_t gpsSeconds = 0;
static uint32_t rollTime = 0;
static uint32_t semTime = 0;
uint32_t totalSeconds;
uint32_t period = Wakeup_CalcPeriod(dcBuff.sampleData.charging);
BaseType_t xHigherPriorityTaskWoken;
if(Wakeup_Sleeping)
{
SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
delay_ms(10);
Vcc_Enable();
delay_ms(40);
printf("\n\nWake up by RTC.\n\n");
}
// 获取当前时间
RTC_GetDateAndTime(&sRTC);
// 计算自上次gps定位以来的时间
totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// 如果超过6个发送周期最小2小时最大1天未发送成功复位
if((totalSeconds >= DTU_succTime + 7200 && totalSeconds >= DTU_succTime + dcBuff.configData.intervalTrans * 6) || totalSeconds >= DTU_succTime + 86400)
{
if(!dcBuff.configDisplay.op_LOCAL_DISP)
NVIC_SystemReset();
}
// // 每隔24小时定位一次(3秒的容错
// if(totalSeconds + 3 >= gpsSeconds + 86400ul)
// {
// // 重新定位
// GPS_Located = 0;
// GPS_Locate = 1;
// // 重新计时
// gpsSeconds = totalSeconds;
// }
if(totalSeconds >= semTime + period)
{
semTime = totalSeconds;
if(Wakeup_Sleeping)
DTU_semSync = 1;
else
DTU_semGPRS = 1;
}
Wakeup_Sleeping = 0;
// 切换多路滚动显示序号: 3秒容错
if(MeterInMeterPage() && MeterNeedRoll() && totalSeconds + 3 >= rollTime + 10)
{
rollTime = totalSeconds;
MeterRoll();
xSemaphoreGiveFromISR(Key_Semaphore, &xHigherPriorityTaskWoken); //Form_Refresh(); //这个函数未做互斥,有可能冲突
}
// 设定下次闹钟唤醒时间
Wakeup_SetAlarm(dcBuff.sampleData.charging);
}
/**
* @brief Alarm B callback.
* @param hrtc RTC handle
* @retval None
*/
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{
DTU_CheckSleep();
}
// 充电唤醒中断
void Vcc_Power_Handler(void)
{
// // 控制电流输出开关
// DAC7311_Open();
//
// if(Wakeup_Sleeping)
// {
// SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
// delay_ms(10);
//
// Vcc_Enable();
// delay_ms(40);
// Wakeup_Sleeping = 0;
//
// // 判断是否为低电平,排除干扰
// if(!VCC_POWER_STATUS())
// {
// printf("\nWakeup by DISTURB ...\n");
// // 由干扰引起的中断,发信号休眠
// return;
// }
// printf("\n\nWake up by POWER.\n\n");
//
// // 采集数据
// Sample_NotifyFromISR();
// }
// // Modbus输出打开
// VCC_RS485_ON();
}
void Wakeup_Init()
{
// LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
// // 充电唤醒引脚
// LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
// /**/
// LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTE, LL_SYSCFG_EXTI_LINE7);
// /**/
// EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_7;
// EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
// EXTI_InitStruct.LineCommand = ENABLE;
// EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
// EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
// LL_EXTI_Init(&EXTI_InitStruct);
// /**/
// LL_GPIO_SetPinPull(GPIOE, LL_GPIO_PIN_7, LL_GPIO_PULL_NO);
// /**/
// LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_7, LL_GPIO_MODE_INPUT);
}
void Wakeup_InitializeTime(S_RTC_TIME_DATA_T *pRTC)
{
pRTC->u32Year = INITIAL_YEAR;
pRTC->u32Month = 1;
pRTC->u32Day = 1;
pRTC->u32DayOfWeek = RTC_WEEKDAY_FRIDAY;
pRTC->u32Hour = 0;
pRTC->u32Minute = 0;
pRTC->u32Second = 0;
pRTC->u32TimeScale = RTC_CLOCK_24;
}
void Wakeup_Open()
{
S_RTC_TIME_DATA_T sRTC;
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
// hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* Set RTC date and time */
Wakeup_InitializeTime(&sRTC);
RTC_SetDateAndTime(&sRTC);
printf("\n*******************************\n");
printf("system reseted ...\n");
// 设定下次闹钟唤醒时间
Wakeup_SetAlarm(dcBuff.sampleData.charging);
// NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
// NVIC_EnableIRQ(EXTI9_5_IRQn);
// if(VCC_POWER_STATUS())
// {
// // Modbus输出打开
// VCC_RS485_ON();
// }
}
// 检查是否进入掉电模式
void Wakeup_Powerdown()
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
uint32_t curr_time;
S_RTC_TIME_DATA_T sRTC;
static uint8_t last_PowerStatus = 0;
uint8_t powerStatus;
//#if 0
// // 模拟充电和放电每隔10分钟切换一次
// if(dcBuff.configDisplay.op_SEND_GPS_DATA)
// {
// RTC_GetDateAndTime(&sRTC);
// curr_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
// sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// powerStatus = (curr_time / 600 % 2 == 0);
// }
// else
//#endif
// {
// // 记录关电的时间
// powerStatus = VCC_POWER_STATUS();
// }
printf("\nEnter to Power-Down0 ......\n");
if(last_PowerStatus != powerStatus && !powerStatus)
{
RTC_GetDateAndTime(&sRTC);
Poweroff_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
}
last_PowerStatus = powerStatus;
printf("\nPoweroff_time= %d\n",Poweroff_time);
//
// // 如果是槽车,且有外部供电,不休眠
// if(powerStatus && dcBuff.configDisplay.op_SEND_GPS_DATA)
// return;
// // 定位未成功且未超时,不允许休眠
// if(!dcBuff.configDisplay.op_SEND_GPS_DATA && Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPS_Waiting)
// return;
// // 采集任务未完成,不允许休眠
// if(Sample_Busy() || Config_Vacuum_Request)
// return;
// // 槽车刚断电的时候延迟20分钟再休眠
// if(dcBuff.configDisplay.op_SEND_GPS_DATA)
// {
// // 正常模式的情况下,延迟休眠
// if(!powerStatus && Wakeup_GetWorkMode() == WORK_MODE_NORMAL)
// {
// // 获取当前时间
// RTC_GetDateAndTime(&sRTC);
// curr_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
// sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
// if(Poweroff_time > 0 && curr_time >= Poweroff_time && curr_time < Poweroff_time + 1200)
//// if(Poweroff_time > 0 && curr_time >= Poweroff_time && curr_time < Poweroff_time + 60)
// {
// if((curr_time - Poweroff_time) % 10 == 0)
// printf("\ndelay sleep time: %d\n", curr_time - Poweroff_time);
// return;
// }
// }
// }
//
// 关闭DTU
// if(Wakeup_GetWorkMode() != WORK_MODE_NORMAL || LCD_Disabled)
// {
// if(dcBuff.dtuData.networked)
// DTU_Sleep();
// else
// DTU_PowerOff();
// }
// 如果显示屏在操作,不休眠
//if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && !LCD_Disabled)
if(!LCD_Disabled)
return;
// // 如果防过充电磁阀处于动作状态,不休眠
// if(dcBuff.configDisplay.op_ANTI_OVERFILL)
// {
// if(IS_CHARGE_ENABLE_HIGH() || IS_CHARGE_DISABLE_HIGH())
// return;
// }
// // 如果声光报警且外供电,不休眠
// if(dcBuff.configDisplay.op_ALARM_OUTPUT)
// {
// if(powerStatus)
// return;
// }
//
// // 有外部供电且电池电压大于4.5v),不休眠
// if(powerStatus && (!dcBuff.configDisplay.op_USE_SOLAR || dcBuff.dtuData.batVoltage > 4500))
// return;
//
// // 如果RF未关闭不休眠
// if(IS_VCC_RF_ON())
// return;
//
// // Modbus输出关闭
// VCC_RS485_OFF();
// 禁止按键功能
NVIC_DisableIRQ(EXTI3_IRQn);
NVIC_DisableIRQ(EXTI4_IRQn);
NVIC_DisableIRQ(EXTI9_5_IRQn);
printf("\nEnter to Power-Down3 ......\n");
// 防止休眠意外(不喂狗)
Watchdog_Feed();
Wakeup_Sleeping = 1;
VCC_SFLASH_FRAM_OFF();
Vcc_Disable();
// 允许按键唤醒,先清除中断标志
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3);
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4);
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
NVIC_EnableIRQ(EXTI3_IRQn);
NVIC_EnableIRQ(EXTI4_IRQn);
NVIC_EnableIRQ(EXTI9_5_IRQn);
// 设置唤醒以后的时钟源
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
// 禁止Systick否则不能休眠
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
// Wakeup_Sleeping在唤醒中断里面清零如果未清零则说明休眠失败
do
{
/* Enter STOP 2 mode */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
}while(Wakeup_Sleeping);
// // 罐箱或槽车版,允许加速度中断
// if(dcBuff.configDisplay.op_BOX_VER || dcBuff.configDisplay.op_SEND_GPS_DATA)
// {
// // 读取运动状态
// Accelero_ReadStatus(LL_GPIO_IsInputPinSet(GPIOD, LL_GPIO_PIN_10));
// // 恢复加速度中断
// EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_10;
// EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
// EXTI_InitStruct.LineCommand = ENABLE;
// EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
// EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
// LL_EXTI_Init(&EXTI_InitStruct);
// }
delay_ms(20);
}
// 读取工作模式
uint8_t Wakeup_GetWorkMode()
{
return Wakeup_workMode;
}
// 设置工作模式
void Wakeup_SetWorkMode()
{
// 默认为正常工作模式
uint8_t mode = WORK_MODE_NORMAL;
// 放电状态
if(!VCC_POWER_STATUS())
{
// 进入电池保护模式
if(bat_veryLow)
mode = WORK_MODE_PROTECT;
// 进入充电提示模式
else if(dcBuff.dtuData.batLow)
mode = WORK_MODE_CHARGE;
}
printf("\nchange work mode from %d to %d\n", Wakeup_workMode, mode);
// 电池保护模式
if(mode == WORK_MODE_PROTECT)
{
// 关闭DTU和传感器供电
DTU_PowerOff();
// VCC_SENSOR_24V_OFF();
// 保存模式
Wakeup_workMode = mode;
return;
}
// 解除电池保护模式
if(Wakeup_workMode == WORK_MODE_PROTECT)
{
}
// 充电提示模式
if(mode == WORK_MODE_CHARGE)
{
// 关闭DTU和传感器供电
DTU_PowerOff();
// VCC_SENSOR_24V_OFF();
}
else
{
// VCC_SENSOR_24V_ON();
}
// 保存模式
Wakeup_workMode = mode;
}