一直以来,树莓派关机要么直接拔掉电源,要么登陆后执行shutdown命令关机。这两种方式,第一种简单粗暴,但是断电对树莓派的SD伤害非常大。第二种方式比较安全,但是很麻烦。树莓派其实支持物理按键开关机,介绍如下。
一、实现方式
在/boot/config.txt 文件末尾添加一行代码:
dtoverlay=gpio-shutdown
保存,然后重启树莓派,在树莓派的GPIO3(BCM3)和GND引脚之间接一个按键。这时按下按键树莓派就关机了,再按一下按键,树莓派开机。

二、实现的原理
在树莓派的/boot/overlays/文件下,包含了大量的设备树,使得树莓派的内核支持大量的硬件配置,前提是要开启才行。 开启的方式也比较简单,只需要在/boot/config.txt文件中添加或者删除相应的命令即可。树莓派的/boot/config.txt文件相当于电脑的BIOS。 这里只看/boot/overlays/README中和本文相关的内容。
树莓派系统/boot/overlays/README文件中关于关机是这么描述的:
Name: gpio-shutdown
Info: Initiates a shutdown when GPIO pin changes. The given GPIO pin
is configured as an input key that generates KEY_POWER events.
This event is handled by systemd-logind by initiating a
shutdown. Systemd versions older than 225 need an udev rule
enable listening to the input device:
ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \
SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
ATTRS{keys}=="116", TAG+="power-switch"
This overlay only handles shutdown. After shutdown, the system
can be powered up again by driving GPIO3 low. The default
configuration uses GPIO3 with a pullup, so if you connect a
button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
you get a shutdown and power-up button.
Load: dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin GPIO pin to trigger on (default 3)
active_low When this is 1 (active low), a falling
edge generates a key down event and a
rising edge generates a key up event.
When this is 0 (active high), this is
reversed. The default is 1 (active low).
gpio_pull Desired pull-up/down state (off, down, up)
Default is "up".
Note that the default pin (GPIO3) has an
external pullup.
大概翻译以下:
在/boot/config.txt文件中添加“dtoverlay = gpio-shutdown”时,当GPIO引脚的电平状态发生变化时关闭树莓派,此时给定的GPIO引脚被配置为KEY_POWER事件的输入键,即不断的监控连接到GPIO引脚的按键是否被按下。
树莓派关机后,树莓派系统可以通过将GPIO3驱动为低电平再次开机。 因此如果连接了GPIO3和GND之间的按钮(40引脚接头连接器上的引脚5和6),你就获得了关机和开机按钮。
即添加代码后,树莓派的GPIO3会不断的检测电平状态,如果检测到GPIO3变为低电平(GPIO3连接到GND时),树莓派就会关机,关机后再次将GPIO3变为低电平,则树莓派会开机。 这样在树莓派的GPIO3和GPND之间连接一个按键,就能够实现树莓派的开关机功能。
dtoverlay=gpio-shutdown
注:该功能(开关机)的实现与I2C有部分冲突,要使用GPIO3实现开关机,则必须关闭I2C功能,如不关闭,则只能实现开机功能,而关机功能失效。如需在启用I2C的情况下一键实现开关机,则可以使用gpio_pin=17,即GPIO_0(物理引脚PIN11)做关机键,GPIO3做开机键,简单说就是GPIO3和GPIO17在开关侧并线,两键共地即可。修改如下:sudo nano /boot/config.txt
dtoverlay=gpio-shutdown
dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up

即添加代码后,树莓派的GPIO3会不断的检测电平状态,如果检测到GPIO3变为低电平(GPIO3连接到GND时),树莓派就会关机,关机后再次将GPIO3变为低电平,则树莓派会开机。 这样在树莓派的GPIO3和GPND之间连接一个按键,就能够实现树莓派的开关机功能。 还可以按照以下格式进行自定义配置:
dtoverlay = gpio-shutdown,<param> = <val>
其中的 parm 和 val 的值可以选择的配置有:
gpio_pin 打开触发功能的GPIO引脚(默认3)
active_low 当它为1(低电平有效)时,下降边缘生成按下事
件,并且上升沿会产生按键上升事件。
当它是0(高电平有效)时,
这时和1的状态相反。默认值为1(低电平有效)。
gpio_pull 所需的上拉/下拉状态(关闭,下拉,上拉)
默认为“上拉”。
请注意,默认引脚(GPIO3)具有一个
外部上拉。
Python实现
t = open("/boot/config.txt","a")
line_on = "dtoverlay=gpio-shutdown" # 调用文件的 readline()方法
t.writelines(line_on+'\n')
line_off = "dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up"
t.writelines(line_off+'\n')
t.close()