You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pi Pico下CircuitPython操作I2C对接SNES Mini手柄故障(附可用MicroPython代码)

解决方法

修改后的完整CircuitPython代码

import time
import board
import busio

GAMEPAD_ADDR = 0x52
FREQ_MOD = 3
# 修正I2C频率和MicroPython一致为300kHz
i2c = busio.I2C(board.GP17, board.GP16, frequency=int(100000 * FREQ_MOD))

while not i2c.try_lock():
    pass

def reconnect():
    # 和MicroPython的writeto_mem逻辑完全等效:寄存器地址+值拼接发送
    i2c.writeto(GAMEPAD_ADDR, bytes([0x40, 0x00]))
    time.sleep(0.05 / FREQ_MOD)

# 初始化配置
i2c.writeto(GAMEPAD_ADDR, bytes([0x40, 0x00]))
# 修正初始配置后的延时,和MicroPython一致为50ms
time.sleep(0.05)

data = bytearray(6)

while True:
    # 拆分读写操作,不要用writeto_then_readfrom,匹配原MicroPython逻辑
    i2c.writeto(GAMEPAD_ADDR, b'\x00')
    time.sleep(0.05 / FREQ_MOD)
    i2c.readfrom_into(GAMEPAD_ADDR, data)
    
    # 增加原代码的重连逻辑
    if data[1] == 0xff:
        reconnect()
        continue
    
    # 按键解析逻辑和原MicroPython一致
    dataA = 0x17 + (0x17 ^ data[4])
    dataB = 0x17 + (0x17 ^ data[5])
    key_state = []
    if not (dataB & ~0b11111110):
        key_state.append("UP")
    if not (dataB & ~0b11111101):
        key_state.append("LEFT")
    if not (dataA & ~0b10111111):
        key_state.append("DOWN")
    if not (dataA & ~0b01111111):
        key_state.append("RIGHT")
    if not (dataA & ~0b11011111):
        key_state.append("L")
    if not (dataA & ~0b11111101):
        key_state.append("R")
    if not (dataB & ~0b11101111):
        key_state.append("A")
    if not (dataB & ~0b10111111):
        key_state.append("B")
    if not (dataB & ~0b11011111):
        key_state.append("Y")
    if not (dataB & ~0b11110111):
        key_state.append("X")
    if not (dataA & ~0b11101111):
        key_state.append("SELECT")
    if not (dataA & ~0b11111011):
        key_state.append("START")
    if key_state:
        print(" | ".join(key_state))
    time.sleep(0.01)

# 程序退出时释放I2C
i2c.deinit()

修改点说明

  • I2C频率修正:原测试代码用了30kHz,远低于MicroPython版本的300kHz,手柄无法正常响应,修改后和原逻辑一致。
  • writeto_mem等效实现:MicroPython的i2c.writeto_mem(addr, reg, buf)本质就是将寄存器地址作为首字节,拼接数据后一次性发送,i2c.writeto(GAMEPAD_ADDR, bytes([0x40, 0x00]))就是完全等效的实现,不需要额外API。
  • 读写逻辑调整:SNES Mini手柄不支持无间隔的连续I2C读写,废弃writeto_then_readfrom,拆分为写命令、延时、读数据三步,完全匹配原MicroPython的执行时序。
  • 补全重连逻辑:保留了原代码的手柄断开重连机制,避免单次配置失效后无法恢复。
  • 修正了配置后的等待时长,和原MicroPython版本的50ms保持一致,确保手柄配置生效。

内容的提问来源于stack exchange,提问作者neil.morrison

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 13:45:06