Voltage Detection - DLPS
当系统处于 IDLE 状态时,会自动进入 DLPS 状态。
当引脚 P2_4 输入电压满足 LPC 电压比较条件时会将系统从 DLPS 唤醒,同时触发 LPC 中断。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
更多信息请参考 快速入门。
硬件连线
连接 LPC 电压比较引脚 P2_4 和外部输入电压。
编译和下载
该示例的工程路径如下:
Project file: board\evb\io_sample\LPC\VoltageDetection_DLPS\mdk
Project file: board\evb\io_sample\LPC\VoltageDetection_DLPS\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译 APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下 reset 按键,开始运行。
测试验证
当 EVB 复位后,系统进入 DLPS 状态。在 Debug Analyzer 工具内打印相应信息。
DLPS ENTER
当 P2_4 检测到低于 2000mV 的电压输入时,系统被唤醒,退出 DLPS 状态。在 Debug Analyzer 工具内打印相应信息。
DLPS EXIT, wake up reason 0x200
系统被唤醒的同时会触发 LPC 中断,在 Debug Analyzer 工具内打印相应信息。
LPCOMP_Handler LPC AON
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\board\evb\io_sample\LPC\VolatgeDetection_DLPS
源码路径:
sdk\src\sample\io_sample\LPC\VolatgeDetection_DLPS
该工程的工程文件代码结构如下:
└── Project: voltage_detect_dlps
└── secure_only_app
└── include
├── app_define.h
└── rom_uuid.h
├── cmsis includes CMSIS header files and startup files
├── overlay_mgr.c
├── system_rtl876x.c
└── startup_rtl876x.s
├── lib includes all binary symbol files that user application is built on
├── rtl8752h_sdk.lib
├── gap_utils.lib
├── ROM.lib
└── adc.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl876x_rcc.c
├── rtl876x_pinmux.c
├── rtl876x_nvic.c
├── rtl876x_io_dlps.c
└── rtl876x_lpc.c
├── profile
└── app includes the ble_peripheral user application implementation
├── main.c
└── io_lpc.c
初始化
当 EVB 复位启动时,调用 main()
函数,将执行以下流程:
int main(void)
{
extern uint32_t random_seed_value;
srand(random_seed_value);
board_init();
driver_init();
pwr_mgr_init();
os_sched_start();
return 0;
}
其中与外设相关的初始化流程如下:
在
board_init
中,执行board_lpc_init
,该函数为 LPC 相关引脚的 PAD/PINMUX 设置,包含如下流程:配置 PAD:设置引脚、SW 模式、PowerOn、无内部上拉、输出失能。
配置 PINMUX:设置引脚为 IDLE 模式。
void board_lpc_init(void) { Pad_Config(LPC_CAPTURE_PIN, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_HIGH); Pinmux_Config(LPC_CAPTURE_PIN, IDLE_MODE); }
在
driver_init
中执行driver_lpc_init
,该函数为 LPC 外设的初始化,包含如下流程:设置 LPC 比较通道为 P2_4 引脚通道。
设置 LPC 电压检测极性为
LPC_Vin_Below_Vth
,即低于设置的电压阈值触发 LPC 比较。设置电压阈值为 2000mV。
使能 LPC 电压检测,配置 LPC 电压比较中断
LPC_INT_LPCOMP_VOL
。执行
LPC_WKCmd()
,使能 LPC 唤醒功能。执行
nvic_lpc_init
,配置并使能 LPC 的 IRQ 通道。
void driver_lpc_init(void) { DBG_DIRECT("driver_lpc_init"); LPC_DeInit(); LPC_InitTypeDef LPC_InitStruct; LPC_StructInit(&LPC_InitStruct); LPC_InitStruct.LPC_Channel = LPC_CAPTURE_CHANNEL; LPC_InitStruct.LPC_Edge = LPC_VOLTAGE_DETECT_EDGE; LPC_InitStruct.LPC_Threshold = LPC_VOLTAGE_DETECT_THRESHOLD; LPC_Init(&LPC_InitStruct); LPC_INTConfig(LPC_INT_LPCOMP_VOL, ENABLE); LPC_WKCmd(ENABLE); RTC_SystemWakeupConfig(ENABLE); LPC_Cmd(ENABLE); extern void nvic_lpc_init(void); nvic_lpc_init(); } void nvic_lpc_init(void) { /* Config LPC interrupt */ NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = LPCOMP_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 3; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); LPC_INTCmd(ENABLE); }
执行
pwr_mgr_init
,该函数为 DLPS 的电压模式设置,包含如下流程:注册用户进入 DLPS 回调函数
app_enter_dlps_config
,注册用户退出 DLPS 回调函数app_exit_dlps_config
。在
app_enter_dlps_config
内使能 LPC 电压比较中断LPC_INT_LPCOMP_VOL
。void app_enter_dlps_config(void) { DBG_DIRECT("DLPS ENTER"); LPC_INTConfig(LPC_INT_LPCOMP_VOL, ENABLE); }
在
app_exit_dlps_config
内打印 DLPS 唤醒信息,记录唤醒次数 +1。void app_exit_dlps_config(void) { allow_count ++; DBG_DIRECT("DLPS EXIT, wake up reason 0x%x", platform_pm_get_wakeup_reason()); }
注册硬件控制回调函数
DLPS_IO_EnterDlpsCb
和DLPS_IO_ExitDlpsCb
,进入 DLPS 会保存 CPU、PINMUX、Peripheral 等,退出 DLPS 会恢复 CPU、PINMUX、Peripheral 等。设置电源模式为 DLPS 模式。
void pwr_mgr_init(void) { dlps_check_cb_reg(app_dlps_check_cb); DLPS_IORegUserDlpsEnterCb(app_enter_dlps_config); DLPS_IORegUserDlpsExitCb(app_exit_dlps_config); DLPS_IORegister(); lps_mode_set(PLATFORM_DLPS_PFM); }
功能实现
执行
os_sched_start()
,开启任务调度。当 P2_4 检测到输入电压低于 2000mV 时,触发LPC_INT_LPCOMP_VOL
中断,进入中断处理函数LPCOMP_Handler
。判断中断标志位是否为
LPC_FLAG_LPCOMP_AON
。失能 LPC 中断。
void LPCOMP_Handler(void) { DBG_DIRECT("LPCOMP_Handler"); if (LPC_GetFlagStatus(LPC_FLAG_LPCOMP_AON) == SET) { DBG_DIRECT("LPC AON"); } LPC_INTConfig(LPC_INT_LPCOMP_VOL, DISABLE); }