跳转至

M5_CARDPUTER

命名空间: m5
头文件: M5Cardputer.h
全局实例: M5Cardputer

主设备类。封装 M5Unified 并添加键盘支持。


公开成员

Display / Lcd

M5GFX &Display = M5.Display;
M5GFX &Lcd     = Display;

320×240 TFT 显示屏。完整绘图 API 见 显示屏 (M5GFX)


Power

Power_Class &Power = M5.Power;

电池电量、充电状态、休眠控制。详细 API 见下方。


Speaker

Speaker_Class &Speaker = M5.Speaker;

音调生成和 WAV 播放。完整 API 见 扬声器


Mic

Mic_Class &Mic = M5.Mic;

I2S 麦克风录音。完整 API 见 麦克风


BtnA

Button_Class &BtnA = M5.getButton(0);

物理按钮 A。详细 API 见下方。


Keyboard

Keyboard_Class Keyboard = Keyboard_Class();

键盘输入处理器。完整 API 见 Keyboard_Class


In_I2C / Ex_I2C

I2C_Class &In_I2C = m5::In_I2C;   // 内部 I2C(板载外设)
I2C_Class &Ex_I2C = m5::Ex_I2C;   // 外部 I2C(Port.A)

设备扫描和寄存器读写。详细 API 见下方。


方法

begin()

void begin(bool enableKeyboard = true);

初始化设备及 M5Unified。自动检测板型,若 enableKeyboardtrue 则启动键盘驱动。

参数 类型 默认值 说明
enableKeyboard bool true 是否启用键盘扫描
void setup() {
    M5Cardputer.begin();  // 默认: 启用键盘
}

begin(cfg)

void begin(m5::M5Unified::config_t cfg, bool enableKeyboard = true);

使用自定义 M5Unified 配置初始化。配置选项见 配置

参数 类型 默认值 说明
cfg m5::M5Unified::config_t 自定义硬件配置
enableKeyboard bool true 是否启用键盘扫描
void setup() {
    auto cfg = M5.config();
    cfg.serial_baudrate = 115200;
    cfg.internal_imu = false;               // Cardputer 没有 IMU
    cfg.internal_rtc = false;               // Cardputer 没有 RTC
    M5Cardputer.begin(cfg, true);
}

update()

void update(void);

刷新 M5Unified 状态并扫描键盘。每次 loop() 迭代必须调用。

void loop() {
    M5Cardputer.update();

    // 检查键盘
    if (M5Cardputer.Keyboard.isChange()) { /* ... */ }

    // 检查按钮
    if (M5Cardputer.BtnA.wasPressed()) { /* ... */ }
}

按钮 A API

wasPressed()

bool wasPressed();

按钮从未按下变为按下时精确返回一次 true(上升沿)。

void loop() {
    M5Cardputer.update();

    if (M5Cardputer.BtnA.wasPressed()) {
        M5Cardputer.Display.println("按钮已按下!");
    }
}

wasReleased()

bool wasReleased();

按钮从按下变为释放时精确返回一次 true(下降沿)。

if (M5Cardputer.BtnA.wasReleased()) {
    M5Cardputer.Display.println("按钮已释放。");
}

isPressed()

bool isPressed();

按钮按住期间持续返回 true

if (M5Cardputer.BtnA.isPressed()) {
    // 按住时每帧触发
    M5Cardputer.Speaker.tone(1000, 50);
}

isHolding()

bool isHolding();

按钮进入"长按"状态时返回 true(按下时间超过长按阈值)。

if (M5Cardputer.BtnA.isHolding()) {
    M5Cardputer.Display.fillCircle(160, 120, 10, TFT_RED);
}

isReleased()

bool isReleased();

按钮 未按下 时返回 true

if (M5Cardputer.BtnA.isReleased()) {
    M5Cardputer.Display.drawString("就绪", 10, 10);
}

wasHold()

bool wasHold();

按钮按住时长达长按阈值(默认 500ms)时精确返回一次 true

if (M5Cardputer.BtnA.wasHold()) {
    M5Cardputer.Display.println("检测到长按!");
    // 弹出菜单
}

wasChangePressed()

bool wasChangePressed();

按钮状态发生任何变化时返回 true(按下 → 释放,或释放 → 按下)。

if (M5Cardputer.BtnA.wasChangePressed()) {
    // 切换静音状态
    static bool muted = false;
    muted = !muted;
    if (muted) M5Cardputer.Speaker.setVolume(0);
    else M5Cardputer.Speaker.setVolume(128);
}

wasReleasedAfterHold()

bool wasReleasedAfterHold();

按钮被长按后释放时精确返回一次 true

if (M5Cardputer.BtnA.wasReleasedAfterHold()) {
    M5Cardputer.Display.println("长按已释放 — 操作已确认。");
}

pressedFor(ms)

bool pressedFor(uint32_t ms);

按钮已被持续按住至少 ms 毫秒时返回 true

// 按住 3 秒后关机
if (M5Cardputer.BtnA.pressedFor(3000)) {
    M5Cardputer.Display.println("正在关机...");
    M5Cardputer.Power.powerOff();
}

releasedFor(ms)

bool releasedFor(uint32_t ms);

按钮已释放至少 ms 毫秒时返回 true

// 5 秒无操作后显示待机提示
if (M5Cardputer.BtnA.releasedFor(5000)) {
    M5Cardputer.Display.drawString("按任意键唤醒", 10, 10);
}

wasReleaseFor(ms)

bool wasReleaseFor(uint32_t ms);

按钮被按住至少 ms 毫秒后释放时精确返回一次 true

if (M5Cardputer.BtnA.wasReleaseFor(1000)) {
    M5Cardputer.Display.println("至少按住 1 秒。");
}

连击检测

bool wasClicked();              // 快速按下并释放
bool wasSingleClicked();        // 单击已确认
bool wasDoubleClicked();        // 双击已确认
bool wasDecideClickCount();     // 连击次数已确定
uint8_t getClickCount();        // 累计连击次数
void loop() {
    M5Cardputer.update();

    if (M5Cardputer.BtnA.wasSingleClicked()) {
        M5Cardputer.Display.println("单击!");
    }
    if (M5Cardputer.BtnA.wasDoubleClicked()) {
        M5Cardputer.Display.println("双击!");
    }
    if (M5Cardputer.BtnA.wasDecideClickCount()) {
        uint8_t count = M5Cardputer.BtnA.getClickCount();
        M5Cardputer.Display.printf("%u 连击\n", count);
    }
}

按钮配置

void setDebounceThresh(uint32_t msec);   // 默认: 10ms
void setHoldThresh(uint32_t msec);       // 默认: 500ms
uint32_t getDebounceThresh();
uint32_t getHoldThresh();
void setup() {
    M5Cardputer.begin();
    // 更灵敏的长按检测
    M5Cardputer.BtnA.setHoldThresh(300);
    // 对抖动较大的按钮增加消抖时间
    M5Cardputer.BtnA.setDebounceThresh(20);
}

电源 API

getBatteryLevel()

int32_t getBatteryLevel();

返回电量百分比(0–100)。无法读取时返回 -1。

void loop() {
    M5Cardputer.update();
    int battery = M5Cardputer.Power.getBatteryLevel();
    M5Cardputer.Display.setCursor(280, 0);
    M5Cardputer.Display.printf("%d%%", battery);
}

getBatteryVoltage()

int16_t getBatteryVoltage();

返回电池电压,单位毫伏(mV)。

int16_t voltage = M5Cardputer.Power.getBatteryVoltage();
M5Cardputer.Display.printf("电池: %d mV\n", voltage);

getBatteryCurrent()

int32_t getBatteryCurrent();

返回电池电流,单位毫安(mA)。正值 = 充电中,负值 = 放电中。

int32_t current = M5Cardputer.Power.getBatteryCurrent();
if (current > 0) M5Cardputer.Display.println("充电中");
else M5Cardputer.Display.printf("放电中: %d mA\n", current);

isCharging()

is_charging_t isCharging();

返回充电状态:

含义
is_charging 正在充电
is_discharging 正在放电
charge_unknown 无法判断
if (M5Cardputer.Power.isCharging() == is_charging) {
    M5Cardputer.Display.drawString("  充电中", 250, 0);
}

充电控制

void setBatteryCharge(bool enable);         // 启用/禁用充电
void setChargeCurrent(uint16_t max_mA);     // 最大充电电流(mA)
void setChargeVoltage(uint16_t max_mV);     // 最大充电电压(mV)
// 限制充电电流以控制发热
M5Cardputer.Power.setChargeCurrent(500);   // 最大 500mA

powerOff()

void powerOff();

关闭所有电源轨。设备在物理复位前不会响应。

// 长按关机
if (M5Cardputer.BtnA.pressedFor(3000)) {
    M5Cardputer.Power.powerOff();
}

deepSleep(micro_seconds)

void deepSleep(uint64_t micro_seconds = 0, bool touch_wakeup = true);

进入 ESP32 深度休眠。指定时间后唤醒,或由触摸/按钮唤醒。

// 深度休眠 30 秒
M5Cardputer.Power.deepSleep(30000000);

// 无限休眠直到按键(0 = 无限)
M5Cardputer.Power.deepSleep(0, true);

lightSleep(micro_seconds)

void lightSleep(uint64_t micro_seconds = 0, bool touch_wakeup = true);

进入 ESP32 轻度休眠。唤醒速度比深度休眠快,但功耗略高。

// 轻度休眠 5 秒,按键唤醒
M5Cardputer.Power.lightSleep(5000000, true);

timerSleep(seconds)

void timerSleep(int seconds);
void timerSleep(const rtc_time_t& time);
void timerSleep(const rtc_date_t& date, const rtc_time_t& time);

使用 PMIC 的 RTC 定时休眠。在指定时间唤醒。

// 休眠 60 秒
M5Cardputer.Power.timerSleep(60);

getVBUSVoltage()

int16_t getVBUSVoltage();

返回 USB VBUS 电压(mV)。该板型不支持时返回 -1。

int16_t vbus = M5Cardputer.Power.getVBUSVoltage();
if (vbus > 4000) {
    M5Cardputer.Display.println("USB 电源已连接");
}

setLed(brightness)

void setLed(uint8_t brightness = 255);

控制电源 LED(如有)。0 = 关闭, 1–255 = 开启并设置亮度。

M5Cardputer.Power.setLed(128);  // 半亮

I2C API

In_I2CEx_I2C 共享相同的 I2C_Class API。

scanID() — 设备扫描

void scanID(bool* result, uint32_t freq = 100000);   // 扫描所有 7 位地址
bool scanID(uint8_t addr, uint32_t freq = 100000);   // 检查单个地址

第一种重载需要 bool[120] 数组。第二种在地址响应时返回 true

// 扫描外部 Port.A 上的所有设备
bool devices[120];
M5Cardputer.Ex_I2C.scanID(devices, 100000);
for (int i = 0; i < 120; i++) {
    if (devices[i]) {
        M5Cardputer.Display.printf("发现设备 0x%02X\n", i);
    }
}

// 检查 OLED 显示屏是否已连接
if (M5Cardputer.Ex_I2C.scanID(0x3C)) {
    M5Cardputer.Display.println("找到 OLED!");
}

writeRegister8() / readRegister8() — 单字节寄存器读写

bool writeRegister8(uint8_t address, uint8_t reg, uint8_t data, uint32_t freq = 100000);
uint8_t readRegister8(uint8_t address, uint8_t reg, uint32_t freq = 100000);

向 I2C 设备的寄存器写入或读取一个字节。

// 写入配置
M5Cardputer.Ex_I2C.writeRegister8(0x68, 0x6B, 0x00, 400000);  // 唤醒 MPU6050

// 读取传感器数据
uint8_t val = M5Cardputer.Ex_I2C.readRegister8(0x68, 0x75, 400000);  // 读取 WHO_AM_I
M5Cardputer.Display.printf("WHO_AM_I: 0x%02X\n", val);

writeRegister() / readRegister() — 多字节寄存器读写

bool writeRegister(uint8_t address, uint8_t reg, const uint8_t* data, size_t length, uint32_t freq);
bool readRegister(uint8_t address, uint8_t reg, uint8_t* result, size_t length, uint32_t freq);

向 I2C 设备写入或读取多个字节。

// 从 MPU6050(地址 0x68)读取 6 字节加速度数据
uint8_t accelData[6];
M5Cardputer.Ex_I2C.readRegister(0x68, 0x3B, accelData, 6, 400000);

int16_t ax = (accelData[0] << 8) | accelData[1];
int16_t ay = (accelData[2] << 8) | accelData[3];
int16_t az = (accelData[4] << 8) | accelData[5];

M5Cardputer.Display.printf("AX=%d AY=%d AZ=%d\n", ax, ay, az);

bitOn() / bitOff() — 位操作

bool bitOn(uint8_t address, uint8_t reg, uint8_t bits, uint32_t freq);   // 置位 (OR)
bool bitOff(uint8_t address, uint8_t reg, uint8_t bits, uint32_t freq);  // 清位 (AND NOT)

读-改-写便捷方法:设置或清除寄存器中的指定位。

// 设置设备 0x68 寄存器 0x6B 的第 3 位
M5Cardputer.Ex_I2C.bitOn(0x68, 0x6B, 0x08, 400000);

// 清除第 3 位
M5Cardputer.Ex_I2C.bitOff(0x68, 0x6B, 0x08, 400000);

I2C 总线信息

i2c_port_t getPort();   // I2C 端口号
int8_t getSDA();        // SDA 引脚
int8_t getSCL();        // SCL 引脚
bool isEnabled();       // 总线是否已配置
void setup() {
    M5Cardputer.begin();

    M5Cardputer.Display.printf("Ex_I2C: SDA=%d SCL=%d\n",
        M5Cardputer.Ex_I2C.getSDA(),
        M5Cardputer.Ex_I2C.getSCL());

    if (M5Cardputer.Ex_I2C.isEnabled()) {
        M5Cardputer.Display.println("外部 I2C 就绪");
    }
}