1、出现原因:因为修改了开机UI的逻辑,导致了上述标题的问题(跑马灯跑完松开按键之后再按还会启动问题)。
2、原来的逻辑:
void fun_poweron_mode()
{
bLED_horse_en = 0;
fun_R_horse_led_init();
while (gWorkMode == Em_Dev_PowerOn_Mode)
{
if(bTimeBase_Onetime == 1){ //0.8192ms
bTimeBase_Onetime = 0;
GCC_CLRWDT();
if(fun_detect_charge() == Em_Charge)
gWorkMode = Em_Dev_Charge_Mode;
fun_poweron_led();
fun_key_scan();
fun_key_powerOn_deal();
fun_key_LED();
}
}
}
void fun_poweron_led()
{
if(bLED_horse_en == 0)
return;
if(fun_R_horse_led() == 4){
if((gKeyClickTimes == 0) && (gKey == Em_NO_Key) && (gWorkMode == Em_Dev_PowerOn_Mode))
gWorkMode = Em_Dev_Work_Mode;
}
}
void fun_key_powerOn_deal()
{
switch (gKey)
{
case Em_Key_long:
// gWorkMode = Em_Dev_Work_Mode;
bLED_horse_en = 1; //set to display poweron led,when led done,set Em_Dev_Work_Mode
EN_POWER = 1;
break;
case Em_Key_Produce_Aging:
gWorkMode = Em_Dev_Aging_Mode;
gAging_life_mode = 0;
EN_POWER = 1;
break;
case Em_Key_LIFE_Aging:
gWorkMode = Em_Dev_Aging_Mode;
gAging_life_mode = 1;
EN_POWER = 1;
break;
default:
break;
}
gKey = Em_NO_Key;
}
如上图,逻辑是
1:一开始跑马灯标志位bLED_horse_en置为0。
2:进入上电模式while循环。
3:上电模式下先进行按键扫描(key_scan),检测到我们的手按下超过设置的长按时间间隔以后(Em_Key_Long),EN_POWER(EN脚被拉高)以及跑马灯标志位设为1
4:EN脚拉高意味着之后我们不用再用手按下,电平会保持住我们手按下时的状态。
5:等再一次进入上电模式while循环,检测到跑马灯标志位为1,进入跑马灯函数,当跑马灯亮到第四个的时候,进入工作模式,同时EN脚保持拉高状态。
3、修改开机UI后的逻辑:
void fun_poweron_mode()
{
bLED_horse_en = 0;
fun_R_horse_led_init();
while (gWorkMode == Em_Dev_PowerOn_Mode)
{
if(bTimeBase_Onetime == 1){ //0.8192ms
bTimeBase_Onetime = 0;
GCC_CLRWDT();
if(fun_detect_charge() == Em_Charge)
gWorkMode = Em_Dev_Charge_Mode;
fun_poweron_led();
fun_key_scan();
fun_key_powerOn_deal();
if(KEY1_PRESS_DOWN() == 1)
{
fun_key_LED();
}
else
{
LEDall_OFF_bit();
LED_battery_off();
}
}
}
}
void fun_key_LED()
{
if(gTime_08ms_Cnt < 250)
gTime_08ms_Cnt++;
if(gTime_08ms_Cnt > 150)
{
LED15_light();
fun_R_horse_led();
}
}
void fun_R_horse_led()
{
gLedCount++;
switch (gLedState)
{
case 0:
bLED1 = 1;
if(gLedCount >= POWERON_LEDSPEED){
gLedCount = 0;
gLedState++;
}
break;
case 1:
bLED2 = 1;
if(gLedCount >= POWERON_LEDSPEED){
gLedCount = 0;
gLedState++;
}
break;
case 2:
bLED3 = 1;
if(gLedCount >= POWERON_LEDSPEED){
gLedCount = 0;
gLedState++;
}
break;
case 3:
bLED4 = 1;
if(gLedCount >= POWERON_LEDSPEED){
gLedCount = 0;
gLedState++;
}
break;
case 4:
bLED5 = 1;
if(gLedCount >= POWERON_LEDSPEED){
gLedCount = 0;
// gLedState++;
gLedState = 0;
gWorkMode = Em_Dev_Work_Mode;
}
break;
default:
break;
}
// return gLedState;
}
与原来的开机模式作比较,这次的逻辑不是先检测到长按在开机,而是当你按下的那一瞬间识别到短按,然后你不能松开,继续让fun_R_horse_led()函数进行,然后直接进入工作模式,同时因为识别到短按不能松开,按键扫描函数也检测到我这个是长按,EN脚会拉高。
这么做能够达到业务的需求,但是却埋下了一个隐患。
照着上述代码的逻辑:第一次短按你进入上电模式,先进行一次初始化,然后开始进入while循环,一开始按键扫描到你是短按,进入跑马灯函数,跑马灯函数会先亮灯,然后等待一段POWERON_LEDSPEED时间,才清掉状态标志位和进入工作模式。那么就有一种情况,当你识别到短按,然后经过一系列POWERON_LEDSPEED时间,bLED5亮起来了,但是不等它的时间大于POWERON_LEDSPEED就松开按键,此时状态标志位没有清零,同时这么长的时间满足了按键扫描函数的长按要求,并且把EN脚拉高了,EN脚拉高就代表你松开按键的时候,机器还在供电处于上电模式,一直在进行while (gWorkMode == Em_Dev_PowerOn_Mode),这个时候你在按下去,识别到短按,进入跑马灯函数switch结构,因为状态标志位没有清零,所以先直接亮五档灯,然后在时间大于POWERON_LEDSPEED后,清掉状态位,进入工作模式,亮一档灯。
4、完善以后的逻辑:
将EN脚在工作模式拉高,不在上电模式识别到长按拉高,这样在识别到长按时我松开按键,就不会一直处于上电模式下,而是会重新进入上电模式初始化。
void fun_key_powerOn_deal()
{
switch (gKey)
{
case Em_Key_long:
// gWorkMode = Em_Dev_Work_Mode;
bLED_horse_en = 1; //set to display poweron led,when led done,set Em_Dev_Work_Mode
break;
case Em_Key_Produce_Aging:
gWorkMode = Em_Dev_Aging_Mode;
gAging_life_mode = 0;
EN_POWER = 1;
break;
case Em_Key_LIFE_Aging:
gWorkMode = Em_Dev_Aging_Mode;
gAging_life_mode = 1;
EN_POWER = 1;
break;
default:
break;
}
gKey = Em_NO_Key;
}
void fun_work_mode()
{
ucGear_level = Em_GEAR1;
Fun_set_rmp();
Motor_Start();
fun_batteryLevel_detect_init();
EN_POWER = 1;
while (gWorkMode == Em_Dev_Work_Mode)
5、总结:
这次我理解了EN脚的一些作用,不在把它当作一个抽象的概念,EN脚在上电模式置起来就会一直处于上电模式。