172 lines
6.6 KiB
C
Executable File
172 lines
6.6 KiB
C
Executable File
#include "../main/SystemInclude.h"
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 执行休眠之前,调用此函数选择具体的休眠模式
|
||
* @param mode: 休眠模式,可选值:
|
||
* - PWR_MODE_SLEEP: 睡眠模式(内核停止,外设运行)
|
||
* - PWR_MODE_DEEP_SLEEP_1: 深度休眠1(时钟停止,不启用低功耗LDO)
|
||
* - PWR_MODE_DEEP_SLEEP_2: 深度休眠2(时钟停止,启用低功耗LDO)
|
||
* - PWR_MODE_SNOOZE: ADC小睡模式(ADC独立工作)
|
||
* - PWR_MODE_SHUTDOWN: 关断模式(数字域掉电)
|
||
* @note 首先调用 LHL_PWR_SetPowerMode 配置电源模式,
|
||
* 然后执行 WFI 指令进入休眠。唤醒后自动恢复时钟,
|
||
* 并调用 ExitLowPowerModeRecoverySysState() 进行唤醒后处理。
|
||
* @example EnterLowPowerModeWFI(PWR_MODE_DEEP_SLEEP_2);
|
||
**/
|
||
void EnterLowPowerModeWFI(PWR_POWERMODE_t mode)
|
||
{
|
||
delay_ms(800);
|
||
LHL_PWR_SetPowerMode(mode);
|
||
LHL_PWR_EnterSleep();/*自带 Restore Clocks */
|
||
// 唤醒后从此处继续 → 自动恢复
|
||
//重新配置时钟 恢复外设 通知各模块已唤醒
|
||
|
||
ExitLowPowerModeRecoverySysState();
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*=============================================================================*/
|
||
|
||
__LPM_STA_TypeDef lpmState;
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 低功耗模式处理函数(由主循环调用)
|
||
* @note 判断 lpmState.mcuModeSleeping 标志,若为1则进入低功耗流程。
|
||
* 先配置 GPIO0.1 为外部中断唤醒源(串口唤醒),再调用用户可重写的
|
||
* SetupLowPowertoWakeupByHandwareTrigger() 配置其他硬件触发唤醒源,
|
||
* 最后根据 lpmState.lpm_mode 选择具体休眠模式并调用 EnterLowPowerModeWFI。
|
||
* 唤醒后自动从 WFI 返回,不在此函数内做额外处理。
|
||
* @example lpmState.lpm_mode = PWR_MODE_DEEP_SLEEP_2;
|
||
* lpmState.mcuModeSleeping = 1;
|
||
* LowPowerModeProcess();
|
||
**/
|
||
void LowPowerModeProcess(void)
|
||
{
|
||
if (lpmState.mcuModeSleeping==0) return ; //判断是否要进入低功耗
|
||
|
||
//进入低功耗
|
||
lpmState.mcuModeSleeping = 0 ;
|
||
/*使用 UART Rx引脚 外部中断唤醒---------------------------------------------- */
|
||
GPIO_EXTI_Init(GPIO0,GPIO_PIN_1,EXTI_LINE_1,EXTI0_1_IRQn);//默认将GPIO0.1设为唤醒源
|
||
|
||
SetupLowPowertoWakeupByHandwareTrigger();//睡眠前设置。设置中断源唤醒,使用前必须确定该中断可以触发
|
||
|
||
switch(lpmState.lpm_mode)
|
||
{
|
||
case PWR_MODE_DEEP_SLEEP_2 : EnterLowPowerModeWFI(PWR_MODE_DEEP_SLEEP_2); break ; //深度休眠2
|
||
case PWR_MODE_SNOOZE : EnterLowPowerModeWFI(PWR_MODE_SNOOZE); break ; //ADC小睡模式
|
||
case PWR_MODE_DEEP_SLEEP_1 : EnterLowPowerModeWFI(PWR_MODE_DEEP_SLEEP_1); break ; //深度休眠1
|
||
case PWR_MODE_SLEEP : EnterLowPowerModeWFI(PWR_MODE_SLEEP); break ; //普通休眠
|
||
case PWR_MODE_SHUTDOWN : EnterLowPowerModeWFI(PWR_MODE_SHUTDOWN); break ; //关断模式
|
||
default : EnterLowPowerModeWFI(PWR_MODE_SLEEP); break ;
|
||
}
|
||
}
|
||
|
||
// /**------------------------------------------------------------------------
|
||
// * @brief 配置SNOOZE模式DMA唤醒源
|
||
// * @param ch: 0=使用ADC0的DMA通道唤醒, 1=使用ADC1的DMA通道唤醒
|
||
// * @note 寄存器定义: SNOOZE_SRC_EXIT [2]
|
||
// * 0: 使用搬运ADC0的DMA通道中断作为唤醒core的源
|
||
// * 1: 使用搬运ADC1的DMA通道中断作为唤醒core的源
|
||
//**/
|
||
//void ADC_Set_SNOOZE_DMA_Wakeup(ADC_ID_t ADCx )
|
||
//{
|
||
// uint32_t reg_val = pADC->DMA_MODE;
|
||
//
|
||
//// LHL_ADC_DMACmd(ADCx, ENABLE); //dma_adc 初始化已经使能
|
||
// reg_val &= ~ADC_SUBSYS_USER_DMA_MODE_SNOOZE_EXIT_SRC_Msk; // 清bit2
|
||
// reg_val |= (((uint32_t)ADCx - 1)<< ADC_SUBSYS_USER_DMA_MODE_SNOOZE_EXIT_SRC_Pos);
|
||
// pADC->DMA_MODE = reg_val;
|
||
//}
|
||
|
||
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 进入低功耗前的硬件触发唤醒源配置(弱函数,可重写)
|
||
* @note 该函数为弱定义,用户可在应用程序中重新实现以自定义唤醒源。
|
||
* 默认实现中配置了:
|
||
* - LPTIM2 启动(用于触发 ADC,但未连接 XLINK)
|
||
* - RTC 闹钟设置为 1 秒后触发,并连接 XLINK 到 ADC 触发
|
||
* - ADC 初始化为硬件触发单次转换模式
|
||
* - 使能 ADC 的 EXTI 线(EXTI_LINE_12)作为唤醒源
|
||
* @example 无(由系统调用)
|
||
**/
|
||
__weak void SetupLowPowertoWakeupByHandwareTrigger(void)
|
||
{
|
||
/*ADC唤醒-----SNOOZE模式有效================================================*/
|
||
|
||
/* 1. LPTIM 设置 */
|
||
StartLPTimer2(32768); //设置LPTimer触发adc转换周期 = 4s 16384 65535 启动需要时间,先进行,否则首次触发会失败
|
||
// /* 2. 配置XLINK,连接LPTIM到ADC硬件触发 */
|
||
// XLINK_LPTIM_To_ADC_Trigger(LPTIM2, ADC_0);
|
||
// /* 3. 设置 LPTIM2作为ADC硬件触发源*/
|
||
// MODIFY_REG(pPWR->CR, PWR_CR_ADC_MSYS_TSEL_Msk, (3U << PWR_CR_ADC_MSYS_TSEL_Pos));
|
||
|
||
/* 1. RTC设置 */
|
||
StartRTC_AlarmAfterSeconds(1);//设置 N 秒后闹钟
|
||
LHL_RTC_ITConfig(RTC_IT_ALRIE, DISABLE);//禁用RTC闹钟中断 (使能会自动配置 EXTI_LINE_9 作为唤醒源)
|
||
// 2. 设置 RTC ALARM作为ADC硬件触发源
|
||
MODIFY_REG(pPWR->CR, PWR_CR_ADC_MSYS_TSEL_Msk, (0U << PWR_CR_ADC_MSYS_TSEL_Pos));
|
||
/* 3. 配置XLINK,连接RTC ALARM到ADC硬件触发 */
|
||
XLINK_RTC_ALARM_To_ADC_Trigger(ADC_0);
|
||
|
||
/* 4. ADC 设置 :硬件触发+单次转换 */
|
||
ADC_REF_Init(REF_INTERNAL_2P5V, REF_INTERNAL_2P5V);
|
||
ADC_Init_For_LowerPower(ADC_0, ADC_SPS_5, GAIN32, ADC0_AIN0, ADC0_AIN1);
|
||
|
||
/* 5. 设置唤醒源 */
|
||
// LPTIM_EXTI_Init(LPTIM2);//将LPTimer2设为唤醒源 EXTI_LINE_11
|
||
ADC_EXTI_Init();//将ADC设为唤醒源 EXTI_LINE_12
|
||
|
||
}
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 退出低功耗后的系统恢复处理(弱函数,可重写)
|
||
* @note 该函数为弱定义,用户可重写以定制唤醒后的操作。
|
||
* 默认实现中:
|
||
* - 清除 EXTI 中断标志位
|
||
* - 恢复 UART 功能(重新初始化并启动 DMA 接收)
|
||
* - 读取一次 ADC 值并打印唤醒次数、唤醒源和 ADC 值
|
||
* - 默认设置下次仍进入 SNOOZE 模式(lpmState 相应设置)
|
||
* @example 无(由 EnterLowPowerModeWFI 自动调用)
|
||
**/
|
||
__weak void ExitLowPowerModeRecoverySysState(void)
|
||
{
|
||
lpmState.mcuModeSleeping = 0 ;//唤醒mcu并将标志位复位
|
||
|
||
static u16 wakeupcount = 0 ,wakeupsource;
|
||
wakeupcount++ ;
|
||
wakeupsource = pEXTI->PR ;//中断唤醒源标志 pEXTI->EMR //事件唤醒源标志位
|
||
pEXTI->PR = 0xFFFF;//清除唤醒源标志位
|
||
|
||
/* 唤醒后处理 */
|
||
//1. UART----------------------------------------------------
|
||
NVIC_DisableIRQ(EXTI0_1_IRQn); //须禁用uart rx的外部中断
|
||
MainUartInit(baudRateVaule[baudRate]);//将引脚设置回串口功能
|
||
StartDMAForRxdMainUartData();//开始串口DMA传输
|
||
// TEST_PIN_TOGGLE();
|
||
//2. ADC----------------------------------------------------
|
||
//判断阈值等----
|
||
u16 adc_buffer = ADC_ReadData(ADC_0);//直接读取不使用中断
|
||
// if(adc_buffer > 42768 ) lpmState.mcuModeSleeping = 0 ;//退出睡眠
|
||
lpmState.lpm_mode = PWR_MODE_SNOOZE ;
|
||
lpmState.mcuModeSleeping = 1 ;//默认再次睡眠
|
||
|
||
printf(" \n ---唤醒次数 = %d ; 唤醒源 = %d 当前ADC值 = %d \n" ,wakeupcount , wakeupsource ,adc_buffer);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|