五向按键深度剖析:从触点原理到 Pico 状态判断,附 MicroPython 工程代码
1.五向按键基本知识
五向按键是一种常见的输入设备,通常用于电子产品的控制界面,如遥控器、游戏手柄和移动设备,其内部包含五个触点,中心有一个公用触点,周围则分布着多个固定触点。其原理是通过活动触点簧片与公用触点和周边固定触点的连接,实现多种状态的切换。当操作杆移动时,活动触点簧片与相应触点接触,从而形成电路连接。


五向按键就像一个按键,但实际上它包含五个不同的按键状态,通过不同方向的按压,用户可以在多个功能之间切换。这里,我们将五向按键的公用触点(COM 端)连接到 +5V 电源上。当没有任何一个按键按下时,测量到的任意一个按键的电压为 0V,因为所有触点处于开路状态,不会有电流流动;而当按下任意一个按键时,那个按键的活动触点簧片将与公用触点连接,形成闭合电路,此时测量到的对应按键电压将上升到电源电压(5V)。
2.应用实验
在以下程序中,我们使用树莓派 Pico 的 GPIO 引脚读取和处理一个五向摇杆(包含 7 个按键)输入的状态,并在按键被按下时打印相关的按键信息,这里,我们需要将 风雅一号板-通用兼容扩展板 插入到 风雅一号板-LCD屏幕人机交互板 上,并且打开 SWITCH3 拨码开关上所有选项,实物连接图如下所示:

五向按键连接情况如下表所示,其中五向按键的共用端(COM 端)连接到 +3V3 电源:
| 五向按键引脚 | 树莓派 Pico 引脚 | 说明 |
|---|---|---|
| COM (公共端) | 3V3(OUT) |
公共电源端,接 Pico 的 3.3V 电源输出 |
| UP | GPIO20 |
上方向按键输入 |
| DOWN | GPIO18 |
下方向按键输入 |
| LEFT | GPIO16 |
左方向按键输入 |
| RIGHT | GPIO19 |
右方向按键输入 |
| MID (确认键) | GPIO17 |
中间按键输入 |
示例代码如下,在配套资料的文件夹:elegance-devkit v1\Demo\06 GPIO_5DJoystick 中:
# Python env : MicroPython v1.23.0
# -*- coding: utf-8 -*-
# @Time : 2025/1/2 下午2:10
# @Author : 李清水
# @File : main.py
# @Description : GPIO类实验,5D摇杆实验
# ======================================== 导入相关模块 =========================================
# 导入硬件相关模块
from machine import Pin
# 导入时间相关模块
import time
# ======================================== 全局变量 ============================================
# ======================================== 功能函数 ============================================
# ======================================== 自定义类 ============================================
# 自定义五向按键类
class DirectionalButton:
"""
一个用于处理五向按键的类。
该类封装了五向按键的功能,包括 UP、DOWN、LEFT、RIGHT、MID、SET 和 RST 按键的检测。
每个按键通过配置对应的 GPIO 引脚来监听按键按下和释放事件。按键的状态会存储在 `button_state` 字典中。
按键状态发生变化时,内部会触发中断处理函数来更新状态。提供的方法包括获取特定按键的状态、重置所有按键状态等。
Attributes:
up_pin (Pin): 用于 UP 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
down_pin (Pin): 用于 DOWN 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
left_pin (Pin): 用于 LEFT 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
right_pin (Pin): 用于 RIGHT 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
mid_pin (Pin): 用于 MID 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
set_pin (Pin): 用于 SET 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
rst_pin (Pin): 用于 RST 按键的 GPIO 引脚对象,初始化时会设置为输入模式并启用下拉电阻。
button_state (dict): 按键状态字典,记录每个按键的当前状态。字典中键名为按键名,值为按键的状态(True 为按下,False 为未按下)。
Methods:
get_button_state(button): 获取指定按键的当前状态,返回 True 表示按下,False 表示未按下。
reset_all(): 重置所有按键的状态,将所有按键标志设置为 False(未按下)。
_handle_button(pin): 按键中断处理函数,根据按键的引脚设置按键的状态。
"""
def __init__(self, up_pin: int, down_pin: int, left_pin: int, right_pin: int,
mid_pin: int, set_pin: int = None, rst_pin: int = None) -> None:
"""
初始化五向按键类,配置所有按键的 GPIO 引脚并启用内置上拉电阻。
Args:
up_pin (int): UP 按键的 GPIO 引脚。
down_pin (int): DOWN 按键的 GPIO 引脚。
left_pin (int): LEFT 按键的 GPIO 引脚。
right_pin (int): RIGHT 按键的 GPIO 引脚。
mid_pin (int): MID 按键的 GPIO 引脚。
set_pin (int): SET 按键的 GPIO 引脚。
rst_pin (int): RST 按键的 GPIO 引脚。
Returns:
None
"""
# 初始化各个方向的按键引脚,设置为输入模式,并启用下拉电阻
self.up_pin = Pin(up_pin, Pin.IN, Pin.PULL_DOWN)
self.down_pin = Pin(down_pin, Pin.IN, Pin.PULL_DOWN)
self.left_pin = Pin(left_pin, Pin.IN, Pin.PULL_DOWN)
self.right_pin = Pin(right_pin, Pin.IN, Pin.PULL_DOWN)
self.mid_pin = Pin(mid_pin, Pin.IN, Pin.PULL_DOWN)
if set_pin is not None and rst_pin is not None:
self.set_pin = Pin(set_pin, Pin.IN, Pin.PULL_DOWN)
self.rst_pin = Pin(rst_pin, Pin.IN, Pin.PULL_DOWN)
# 初始化按键状态字典,默认值为 False(未按下)
self.button_state = {
'UP': False,
'DOWN': False,
'LEFT': False,
'RIGHT': False,
'MID': False,
'SET': False,
'RST': False
}
# 为各个按键引脚设置中断处理函数
self.up_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
self.down_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
self.left_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
self.right_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
self.mid_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
if set_pin is not None and rst_pin is not None:
self.set_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
self.rst_pin.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._handle_button)
def _handle_button(self, pin: Pin) -> None:
"""
按键中断处理函数,根据按键的引脚设置按键状态。
每次按键按下或松开时,更新对应按键的状态。
Args:
pin (Pin): 触发中断的按键引脚。
Returns:
None
"""
if pin == self.up_pin:
self.button_state['UP'] = (pin.value() == 1)
elif pin == self.down_pin:
self.button_state['DOWN'] = (pin.value() == 1)
elif pin == self.left_pin:
self.button_state['LEFT'] = (pin.value() == 1)
elif pin == self.right_pin:
self.button_state['RIGHT'] = (pin.value() == 1)
elif pin == self.mid_pin:
self.button_state['MID'] = (pin.value() == 1)
elif pin == self.set_pin:
self.button_state['SET'] = (pin.value() == 1)
elif pin == self.rst_pin:
self.button_state['RST'] = (pin.value() == 1)
def get_button_state(self, button: str) -> bool:
"""
获取指定按键的当前状态。
检查指定按键是否处于按下状态。
Args:
button (str): 要查询的按键,支持 'UP', 'DOWN', 'LEFT', 'RIGHT', 'MID', 'SET', 'RST'。
Returns:
bool: 返回指定按键的状态,True 表示按下,False 表示未按下。
"""
return self.button_state.get(button, False)
def reset_all(self) -> None:
"""
重置所有按键的状态为未按下。
用于在某些场景下需要清除所有按键状态时使用。
Args:
None
Returns:
None
"""
for button in self.button_state:
self.button_state[button] = False
# ======================================== 初始化配置 ==========================================
# 上电延时3s
time.sleep(3)
# 打印调试信息
print("FreakStudio : GPIO read 5D Joystick value")
# 创建五向按键对象,使用 GPIO 16 到 GPIO 20 连接按键
button = DirectionalButton(up_pin=20, down_pin=18, left_pin=16, right_pin=19, mid_pin=17)
# ======================================== 主程序 ===========================================
# 主循环,读取按键状态并打印出来
while True:
# 检查是否有按键被按下
for button_name in ['UP', 'DOWN', 'LEFT', 'RIGHT', 'MID', 'SET', 'RST']:
# 如果按键被按下,打印按键名称和状态
if button.get_button_state(button_name):
print(f"{button_name} button is pressed.")
# 每隔 100 毫秒循环一次
time.sleep(0.1)
DirectionalButton 类封装了五向摇杆的 7 个按键(UP、DOWN、LEFT、RIGHT、MID、SET、RST)的检测和状态管理,每个按键对应一个 GPIO 引脚,按键状态通过中断方式进行实时检测,包括如下方法:
- 构造方法
__init__:构造函数接收七个引脚参数,这些引脚分别连接到五向摇杆的 7 个按键(UP、DOWN、LEFT、RIGHT、MID、SET、RST),使用Pin.IN来配置引脚为输入模式,并且通过Pin.PULL_DOWN启用下拉电阻(因为按键未按下时,输入引脚的状态是低电平0,按下时变为高电平1)。 - 中断处理方法
_handle_button:中断函数会在每次按键按下(IRQ_FALLING)或松开(IRQ_RISING)时触发,按键的状态会通过检查引脚的电平来更新,在按下时,GPIO 引脚电平为高电平(1),松开时为低电平(0),每个按键都有对应的状态字典 (button_state),保存按键是否被按下的状态。 - 获取按键状态
get_button_state:该函数接收一个按键名称(如'UP')并返回该按键的当前状态,True表示按下,False表示未按下,通过字典的get()方法返回相应按键的状态。 - 重置所有按键状态
reset_all:该函数将所有按键的状态设置为False,即将它们的状态重置为“未按下”,通过字典遍历所有按键,将它们的状态重置。
在主循环中,我们创建 DirectionalButton 类的实例,并将引脚号传入对应的按键引脚,这里使用的是树莓派 Pico 的 GPIO 引脚 16 到 22 连接摇杆的各个按键,主循环中,程序不断检查每个按键的状态;对每个按键,调用 get_button_state() 方法获取当前状态,如果按键被按下,则打印相关信息(如 "UP button is pressed."),每次循环结束后,使用 time.sleep(0.1) 延时 100 毫秒,避免过于频繁地读取按键状态,减轻 CPU 负担。
烧录程序,打开终端,显示如下:


可以看到,按下不同按键时,都能够显示对应按键状态信息。

五向按键是一种常见的输入设备,通常用于电子产品的控制界面,如遥控器、游戏手柄和移动设备,其内部包含五个触点,中心有一个公用触点,周围则分布着多个固定触点。其原理是通过活动触点簧片与公用触点和周边固定触点的连接,实现多种状态的切换。当操作杆移动时,活动触点簧片与相应触点接触,从而形成电路连接。
浙公网安备 33010602011771号