本帖最后由 luobeihai 于 2023-12-7 22:22 编辑
#申请原创# @21小跑堂
1. 前言
说明:本文介绍的软开关电路,并不是开关电源里面的软开关概念,而是系统供电的开关,结合MCU等控制芯片,控制系统供电的开启或关断。
在某些电子产品的场合,我们经常会需要用到按键长按进行开机,然后按键长按进行关机,或者按键长按之后有触摸屏的可以弹出关机菜单,然后进行关机的操作。这个操作的过程就是软开关电路在控制的。
比如说可穿戴的手环设备,就有一个按键可以长按开机,这时松开了开机键之后也不会掉电。开机之后,长按按键,如果有 UI 界面的话,可以弹出关机选项,然后选择关机,又或者 MCU 检测到长按,直接输出控制,关断系统的供电。开机之后,进行关机的操作,就是由这个软开关电路进行控制的。
2. 硬件设计
根据上面的介绍,软开关并不能都只依靠软件来完成,因为当系统电源处于关闭状态时,MCU都还没有供电,此时就只能通过按下开关键,然后等待MCU上电后进行电源的控制,当软件运行起来之后,就算开关键松开了,也可以控制住电源不会掉电。
总结起来,软开关电路的设计需要下面一些条件:
根据上面总结的几个条件,下面我分享一个基于 APM32F411 MCU 控制的一个软开关电路的设计。
2.1 电路原理图
软开关电路设计的思路有很多,我的设计想法是控制电源芯片的 EN (使能)脚,控制使能脚的供电开关,从而控制电源芯片输出电压,给到整个系统进行供电。
下图就是软开关电路的总体电路图:
总体介绍:
2.2 原理分析
软开关电路控制部分,主要位于左下角的电路。下面我分几种状态,对该电路如何实现了软开关功能进行详细分析。
1)系统关机,SW1按键未按下
当系统处于掉电状态,而且此时 SW1 按键也没有按下,而且控制 NMOS 管 Q3 的栅极控制信号 SYS_POWER_LOCK 此时也是处于低电平的状态,所以 NMOS 管 Q3 关闭。所以,Q2 的 PMOS 管此时的G极(栅极)和S极(源极)电位相等, 即 Q2管 的 Vgs = 0V,也就是说 Q2 管是关闭的,所以 VIN 电压不可能输入到电源芯片的 SPX3819 的使能脚,也就不可能有 3.3V 的输出给整个系统供电,所以此时系统没有供电。
此状态下的等效电路图如下:
2)系统关机,SW1按键按下
当系统处于掉电状态,但是SW1按键按下时,此时的 PMOS 管 Q2 的栅极电压就是二极管 D3 1N5819 的管压降电压,我这里就算它有 0.7V 好了,那么也就是说 Q2 的栅极电位是 Vg = 0.7V,而此时 Q2 的源极电压是 VIN(电源输入电压,3.7V或者5V)。 所以 Vgs = -4.3V,Q2 导通,也就是有电压输入到 SPX3819 芯片的使能脚,从而有3.3V电源给整个系统供电。
所以,按下SW1按键,系统开机。
此时的等效电路如下:
3)系统开机,SYS_POWER_LOCK控制信号输出高电平,SW1按键松开
SW1下,有电源给整个整个系统供电之后,此时MCU软件运行,然后马上对 SYS_POWER_LOCK 控制信号,输出高电平,控制 NMOS 管 Q3 导通。
然后这时,用户松开 SW1 按键,但是由于此时 Q3 导通,所以 Q2 管的栅极(G极)电压基本接近 GND (取决于Q3的管压降)。所以,Q2 管依然保持导通的状态,系统供电正常。
此时的等效电路图如下:
4)系统开机,SW1按键按下
当系统已经开机后,此时已经有了3.3V给整个系统供电了。这时再按下SW1按键,又或者是松开 SW1 按键,已经不会再影响系统的电源的开关了,因为此时已经通过 MCU 控制 Q3 NMOS 管导通了,系统的电源会一直保持导通状态。
而此时按下的 SW1 按键,已经可以作为一个普通按键给 MCU 进行识别了,比如是按下状态,是长按状态等,MCU都可以识别。反正此时可以作为一个普通的用户按键使用。
此时的等效电路图如下:
此处需要注意的就是 D2 1N5819 二极管的管压降大小,需要查看MCU数据手册的低电平阈值标准,如果管压降太大,按键按下 MCU 可能也会不认为是低电平。
5)系统开机之后,SYS_POWER_LOCK控制信号输出低电平
系统开机之后,如果 MCU 检测到 SW1 按键的长按状态(又或者有触摸界面的,可以通过触摸界面关闭系统电源),那么 SYS_POWER_LOCK 就输出低电平,此时 Q3 就不导通了。然后这时用户松开 SW1 按键,系统就彻底的断电了,就回到了最前面介绍初始状态 —— 系统断电,SW1按键松开的情况了。
3. 软件设计
软开关电路的设计,相比于硬件而言,软件其实是更简单的,无非就是通过 MCU 控制 SYS_POWER_LOCK 信号的高或者低就可以了。系统开机之后,如果还需要通过检测按键进行关机的,那么还需要检测 SW1 按键的代码。
下面是基于 APM32F411 控制软开关的简单代码示例。
1、控制 SYS_POWER_LOCK 信号代码,从而控制系统的供电开关。 void power_control_gpio_config(void)
{
GPIO_Config_T gpioConfigStruct;
/* Enable GPIO clock */
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);
gpioConfigStruct.pin = GPIO_PIN_15;
gpioConfigStruct.mode = GPIO_MODE_OUT;
gpioConfigStruct.speed = GPIO_SPEED_100MHz;
gpioConfigStruct.otype = GPIO_OTYPE_PP;
gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
GPIO_Config(GPIOA, &gpioConfigStruct);
GPIO_ResetBit(GPIOA, GPIO_PIN_15);
}
/* 系统开机 */
void power_enable(void)
{
GPIO_SetBit(GPIOA, GPIO_PIN_15);
}
/* 系统关机 */
void power_disable(void)
{
GPIO_ResetBit(GPIOA, GPIO_PIN_15);
}
2、检测按键 SW1 按下或者长按的代码,从而决定是否执行关机动作。 static struct Button key1;
static struct Button key2;
static struct Button key3;
void key_gpio_config(void)
{
GPIO_Config_T gpioConfigStruct;
/* Enable GPIO clock */
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
/* KEY1/2/3 : PB0/1/2 */
gpioConfigStruct.mode = GPIO_MODE_IN;
gpioConfigStruct.pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;
gpioConfigStruct.pupd = GPIO_PUPD_UP;
GPIO_Config(GPIOB, &gpioConfigStruct);
}
uint8_t read_key_gpio(uint8_t key_id)
{
uint8_t temp = 1;
switch(key_id)
{
case 0:
temp = GPIO_ReadInputBit(GPIOB, GPIO_PIN_0);
break;
case 1:
temp = GPIO_ReadInputBit(GPIOB, GPIO_PIN_1);
break;
case 2:
temp = GPIO_ReadInputBit(GPIOB, GPIO_PIN_2);
break;
default:
temp = 1;
break;
}
return temp;
}
void key1_callback(void *button)
{
uint32_t btn_event_val;
btn_event_val = get_button_event((struct Button *)button);
switch(btn_event_val)
{
case PRESS_DOWN:
printf("************* key1 press down! *************\n");
break;
case PRESS_UP:
printf("************* key1 press up! *************\n");
break;
case PRESS_REPEAT:
printf("************* key1 press repeat! *************\n");
break;
case SINGLE_CLICK:
printf("************* key1 single click! *************\n");
break;
case DOUBLE_CLICK:
printf("************* key1 double click! *************\n");
break;
case LONG_PRESS_START:
printf("************* key1 long press start! *************\n");
LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
LCD_ShowString(60,LCD_H/2,(uint8_t*)"Shutdown",WHITE,BLACK,32,1); // LCD输出关机提示
delay_ms(1500);
power_disable(); // 检测到按键长按,系统关机
//while (1);
break;
case LONG_PRESS_HOLD:
printf("************* key1 long press hold! *************\n");
break;
}
}
void multi_button_register(void)
{
button_init(&key1, read_key_gpio, 0, KEY1_ID);
button_init(&key2, read_key_gpio, 0, KEY2_ID);
button_init(&key3, read_key_gpio, 0, KEY3_ID);
button_attach(&key1, (PressEvent)PRESS_UP, (BtnCallback)key1_callback);
button_attach(&key1, (PressEvent)LONG_PRESS_START, (BtnCallback)key1_callback);
button_start(&key1);
}
4. 效果演示
本来想演示一下做出来的效果,但是还不知道怎么上传视频,后面再补充吧。
以上介绍的软开关电路,我已经把对应的实物电路做出来了,而且经过了测试验证,测试没有发现什么问题,可以正常使用。
不过上面的分析也不一定正确,或者电路有什么缺陷我还没注意到,如果有错误的地方大家一起讨论。
下面是补充的演示效果图:
首先是系统关机状态,然后长按按键开机,然后 MCU 上电运行程序,屏幕输出开机界面提示,并且 MCU 输出控制信号锁住电源,让系统一直保持供电。这时再松开按键,整个系统的供电依然正常。
开机之后,再长按按键,MCU 检测到按键的长按状态,就会执行关机的操作,然后 LCD 界面输出关机提示,用户看到 LCD 已经提示关机了,这时就松开按键,这时整个系统就断电了。
|
一文给二姨解惑啦,原来设备上的软开关是这么来的,通过合理的硬件设计和软件设计,达到长按开关机的效果。非常使用的技能。(申请蓝v可获得更高打赏哦~https://bbs.21ic.com/qplugin.php?id=vda)