本文适用范围
ADK20.1~
问题/功能描述
如何实现长按开机功能
实现方案
实现机理描述,通过间隔检测sys_ctrl pio电平状态,在预设时间内维持在高电平状态,判断为开机,期间出现低电平则关机退出。
1.默认开机模式设置
+++ "b/earbud/workspace/QCC3040-AA_DEV-BRD-R2-AA/filesystems/subsys7_psflash.htf"
@@ -78,3 +78,5 @@ USR50 = [ 01 00 ]
# bit1 - WB
# bit2 - SWB
#USR81 = [ 03 00 ] # Uncomment to enable use of the test HFP Codec
+
+CUSTOMER2 = [7 00]
2.开机后,先读取开机模式这是由上次关机时指定,确定需要按键长按就进入按键检测状态,否则直接启动。方便测试一并写在main.c中
+typedef enum{
+ poweron_none,
+ poweron_normal,
+ poweron_charge,
+ poweron_battery,
+ poweron_temperature,
+ poweron_dfu,
+ poweron_other,
+
+ poweron_factory
+}POWERON_ENUM;
+
+#define POWERON_PSKEY 202
+#define POWERON_TIME (3*US_PER_SEC)
+#define POWERON_STEP (50*US_PER_MS)
+#define WAITING_TIME (5* US_PER_SEC)
+static POWERON_ENUM read_poweron_reason(void)
+{
+ uint16 temp;
+ PsRetrieve(POWERON_PSKEY,&temp,sizeof(temp));
+ return temp;
+}
+static void update_poweron_reason(POWERON_ENUM reason)
+{
+ uint16 temp = reason;
+ PsStore(POWERON_PSKEY,&temp,sizeof(uint16));
+}
+
3.按键检测处理,在main函数中实现,这里会间隔10ms左右轮询开机键电平状态,
本段代码在src/main.c main()函数中
int main(void)
{
OsInit();
TimestampEvent(TIMESTAMP_EVENT_BOOTED);
+
+#if ENABLE_POWERON_FEATURE
+ if(ChargerStatus()== NO_POWER && read_poweron_reason() == poweron_normal)
+ {
+ uint32 time = SystemClockGetTimerTime();
+ uint32 count = 0;
+ while(!PsuGetVregEn()){
+ if(count++ == POWERON_STEP)
+ {
+ if(SystemClockGetTimerTime()-time>=WAITING_TIME)
+ appPowerDoPowerOff();
+ count =0;
+ }
+ };
+
+ count=0;
+ time =SystemClockGetTimerTime() + POWERON_TIME;
+
+ while(TRUE)
+ {
+ if(count++ == POWERON_STEP)
+ {
+ uint32 tmp = SystemClockGetTimerTime();
+ if(tmp>=time)
+ {
+ DEBUG_LOG_ALWAYS("---STARTUP NOW----");
+ update_poweron_reason(poweron_none);
+ break;
+ }
+ else if(!PsuGetVregEn())
+ {
+ appPowerDoPowerOff();
+ }
+ count = 0;
+ }
+ }
+ }
+#endif
+
所贴代码只包含了开机部分,在各种关机或重启位置还需要另行添加保存关机原因,以便于开机时使用。
注意事项
1.对电平检测是间隔读取,理论上在间隔期间按键松开按下是默认为一直长按,这点需要注意。间隔时间不要太长,否则会出现多击开机问题。
2.代码只是一个原型旨在演示功能,用户可以再次基础上面进一步丰富完善。可将按键时长,开机按键pio都放到mib key里,在不改动源码前提适配不同产品定义。
3.应用前请做充分测试。
评论