深色模式
M5Cardputer(ADV) Arduino 功能例程速查手册(综合本地实测版)
本手册基于 D:/M5AVD/CardputerAdv_资料 下的官方 API 文档(00~04)与已测 examples(display / button / buzzer / keyboard / inputText / mic / sdcard / ir_nec)整理,并综合 D:/M5AVD/M5Radio 项目实测写法。所有例程均可直接复制编译。 与网上通用教程的关键差异:颜色/对齐用 LovyanGFX 原生写法(GREEN/middle_center),playRaw 是 6 参数,clear() 是整屏清屏——以本机实测 examples 为准。
0. 开发环境 & 板型
Arduino IDE,板管理装M5Stack,开发板选M5Cardputer(库会自动识别 Cardputer / Cardputer-ADV 两种板型,键盘读取器自动切换:ADV 用 TCA8418 I2C 矩阵,旧版用 74HC138)。
库管理器装M5Cardputer(自带 M5Unified / M5GFX / IRremote)。WiFi/SD/SPI 是 ESP32 核心自带,无需另装。
屏幕 240×135,竖屏用时 setRotation(1) 旋转为横屏。
编译用默认 4MB 分区即可。
1. 统一框架(所有程序开头)
cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true); // true = 启用键盘;不用键盘写 M5Cardputer.begin(cfg)
M5Cardputer.Display.setRotation(1); // 横屏
}
void loop() {
M5Cardputer.update(); // 必须每帧调用,刷新键盘/按钮/扬声器状态
}
```cpp
要点:
- M5Cardputer.Display 是一个 LovyanGFX 实例。
- 颜色常量:GREEN / BLACK / WHITE / RED / YELLOW / BLUE / CYAN / MAGENTA(LovyanGFX 原生,不要写 TFT_GREEN 这类 Adafruit 风格)。
- 文字对齐 datum:middle_center / top_center / top_left 等(不要写 MC_DATUM)。
## 2. 屏幕初始化
```cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
M5Cardputer.Display.setRotation(1); // 横屏(1) / 竖屏(0)
M5Cardputer.Display.fillScreen(BLACK); // 清成黑底
M5Cardputer.Display.setTextColor(GREEN); // 前景色
M5Cardputer.Display.setTextSize(1); // 文字大小(浮点, 约0.5~2)
M5Cardputer.Display.setTextDatum(middle_center); // 对齐方式
}
void loop() { M5Cardputer.update(); }
```cpp
换字体(可选):
```cpp
M5Cardputer.Display.setTextFont(&fonts::Orbitron_Light_32); // 内置字体之一
// 其它可用:fonts::FreeSerifBoldItalic18pt7b / fonts::FreeSansBoldOblique12pt7b
```cpp
## 3. 显示文字
三种写法:指定坐标、流式打印、居中对齐。
```cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
M5Cardputer.Display.fillScreen(BLACK);
// 方式1:指定坐标 (x, y),原点在左上
M5Cardputer.Display.setTextColor(WHITE);
M5Cardputer.Display.setTextSize(1);
M5Cardputer.Display.drawString("Hello Cardputer", 10, 10);
// 方式3:居中对齐
M5Cardputer.Display.setTextDatum(middle_center);
M5Cardputer.Display.setTextColor(CYAN);
M5Cardputer.Display.drawString("Center",
M5Cardputer.Display.width() / 2, M5Cardputer.Display.height() / 2);
M5Cardputer.Display.setTextDatum(top_left); // 改回左上对齐
}
void loop() { M5Cardputer.update(); }
```cpp
滚动终端(M5Canvas,来自 inputText.ino):
```cpp
#include "M5Cardputer.h"
#include "M5GFX.h"
M5Canvas canvas(&M5Cardputer.Display);
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
M5Cardputer.Display.setRotation(1);
canvas.createSprite(M5Cardputer.Display.width() - 8,
M5Cardputer.Display.height() - 36);
canvas.setTextScroll(true);
canvas.println("log line 1");
canvas.println("log line 2");
canvas.pushSprite(4, 4);
}
void loop() { M5Cardputer.update(); }
```cpp
## 4. 显示图形
矩形、圆、线、三角形(来自 display.ino / 03 文档)。
```cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
M5Cardputer.Display.fillScreen(BLACK);
M5Cardputer.Display.fillRect(10, 10, 80, 40, GREEN); // 实心矩形 x,y,w,h,color
M5Cardputer.Display.drawRect(100, 10, 80, 40, RED); // 空心矩形
M5Cardputer.Display.fillCircle(40, 90, 20, BLUE); // 实心圆 cx,cy,r
M5Cardputer.Display.drawCircle(100, 90, 20, YELLOW); // 空心圆
M5Cardputer.Display.drawLine(10, 120, 200, 120, WHITE); // 线 x0,y0,x1,y1
M5Cardputer.Display.drawTriangle(140, 70, 180, 120, 140, 120, MAGENTA); // 三角
M5Cardputer.Display.drawRoundRect(200, 10, 30, 40, 8, CYAN); // 圆角矩形 x,y,w,h,radius
}
void loop() { M5Cardputer.update(); }
```cpp
随机彩色图形(display.ino 原版风格):
```cpp
uint16_t c = rand();
M5Cardputer.Display.fillCircle(rand() % M5Cardputer.Display.width(),
rand() % M5Cardputer.Display.height(), 20, c);
```cpp
## 5. 清屏 / 局部擦除
```cpp
M5Cardputer.Display.clear(); // 整屏清屏(官方 examples 常用)
M5Cardputer.Display.fillScreen(BLACK); // 等价:清成黑底
// 局部擦除:用背景色画实心矩形盖住旧内容(inputText.ino 用法)
M5Cardputer.Display.fillRect(0, M5Cardputer.Display.height() - 28,
M5Cardputer.Display.width(), 25, BLACK);
```cpp
动态刷新文字/图形时,先局部 fillRect 擦掉旧区域再画新的,避免叠字。
## 6. 按键输入(键盘)
来自 inputText.ino(真实准确)。启用键盘:M5Cardputer.begin(cfg, true)。每帧 M5Cardputer.update() 后检查 isChange() / isPressed()。
```cpp
#include "M5Cardputer.h"
#include "M5GFX.h"
String data = "> ";
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
M5Cardputer.Display.setRotation(1);
M5Cardputer.Display.setTextSize(0.5);
M5Cardputer.Display.drawString(data, 4, M5Cardputer.Display.height() - 24);
}
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange()) {
if (M5Cardputer.Keyboard.isPressed()) {
Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState();
for (auto i : status.word) data += i; // 追加本次按下的字符
if (status.del) data.remove(data.length() - 1); // 退格键
if (status.enter) { /* 回车:提交 data 做你的处理 */ data = "> "; } // 重置输入行
// 重画输入行
M5Cardputer.Display.fillRect(0, M5Cardputer.Display.height() - 28,
M5Cardputer.Display.width(), 25, BLACK);
M5Cardputer.Display.drawString(data, 4, M5Cardputer.Display.height() - 24);
}
}
}
```cpp
要点:
- status.word:本次按下的可打印字符数组(已处理 shift / caps)。
- 特殊键布尔:status.enter / status.del / status.space / status.backspace / status.tab / status.esc / status.up/down/left/right / status.f1..f12。
- 修饰键布尔:status.ctrl / status.shift / status.fn / status.alt / status.opt。
- 检测某个特定键(不依赖 word):M5Cardputer.Keyboard.isKeyPressed('m')(可用 'm' / 'a' / 数字 / ',' 等)。
## 7. 用户按钮 BtnA(G0)
来自 button.ino:
```cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
M5Cardputer.Display.setRotation(1);
}
void loop() {
M5Cardputer.update();
if (M5Cardputer.BtnA.wasPressed()) { M5Cardputer.Speaker.tone(8000, 20); /* 按下 */ }
if (M5Cardputer.BtnA.wasReleased()) { /* 释放 */ }
if (M5Cardputer.BtnA.wasClicked()) { /* 单击 */ }
if (M5Cardputer.BtnA.wasHold()) { /* 长按 */ }
}
```cpp
注意:用 wasPressed() / wasReleased()(事件型,每按一次触发一次),不是 isPressed()。
## 8. 蜂鸣器 / 扬声器 tone
来自 buzzer.ino:
```cpp
#include "M5Cardputer.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
}
void loop() {
M5Cardputer.Speaker.tone(10000, 100); // 频率Hz, 持续ms
delay(1000);
M5Cardputer.Speaker.tone(4000, 20);
delay(1000);
}
```cpp
音量:M5Cardputer.Speaker.setVolume(0..255)。
停止当前音:M5Cardputer.Speaker.end()。
启用:M5Cardputer.Speaker.begin()。
## 9. 播放音频(playRaw)
来自 mic.ino(6 参数,实测可用):
```cpp
int16_t recData[1024];
size_t recSize = sizeof(recData);
M5Cardputer.Speaker.begin(); // 播放前确保扬声器已启用
M5Cardputer.Speaker.playRaw(recData, recSize, 17000, false, 1, 0); // data,len,sampleRate,stereo,repeat,channel
while (M5Cardputer.Speaker.isPlaying()) { delay(1); M5Cardputer.update(); }
```cpp
⚠麦克风与扬声器互斥:播放前 Mic.end() + Speaker.begin();录音前 Speaker.end() + Mic.begin()(见 mic.ino)。
⚠流式连续播放(如网络收音机)连续喂帧时,可用 7 参数重载 playRaw(data, len, sr, false, 1, channel, stop_current),stop_current=false 表示不清掉已排队音频。完整方案见另一篇《M5 网络收音机项目开发指南》(M5Radio 实测)。
## 10. 麦克风录音
来自 mic.ino 要点:
```cpp
M5Cardputer.Speaker.end(); // 先关扬声器(互斥)
M5Cardputer.Mic.begin(); // 启用麦克风
int16_t buf[240];
if (M5Cardputer.Mic.record(buf, 240, 17000)) { // 录 240 样本 @17kHz
// 处理 buf(int16 数组)
}
// 降噪调节
auto cfg = M5Cardputer.Mic.config();
cfg.noise_filter_level = (cfg.noise_filter_level + 8) & 255;
M5Cardputer.Mic.config(cfg);
```cpp
常用采样率 16 kHz / 17 kHz。完整实时波形示例见 examples/mic/mic.ino、examples/mic_wav_record/mic_wav_record.ino(存 WAV 到 SD 卡)。
## 11. microSD 卡
来自 sdcard.ino(真实管脚:CS=12, MOSI=14, SCK=40, MISO=39):
```cpp
#include <M5Cardputer.h>
#include <SPI.h>
#include <SD.h>
#define SD_CS 12
#define SD_SCK 40
#define SD_MISO 39
#define SD_MOSI 14
void setup() {
M5Cardputer.begin();
M5Cardputer.Display.setRotation(1);
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
if (!SD.begin(SD_CS, SPI, 25000000)) {
M5Cardputer.Display.println("SD failed");
while (1);
}
// 写文件
File f = SD.open("/hello.txt", FILE_WRITE);
if (f) { f.print("Hello "); f.close(); }
// 读文件
f = SD.open("/hello.txt");
while (f.available()) Serial.write(f.read());
f.close();
}
void loop() {}
```cpp
注意:TF 卡金属触点朝屏幕的反面插入。
## 12. 红外发送
来自 ir_nec.ino(IR_TX_PIN = 44):
```cpp
#define DISABLE_CODE_FOR_RECEIVER
#define SEND_PWM_BY_TIMER
#define IR_TX_PIN 44
#include "M5Cardputer.h"
#include <IRremote.hpp>
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
IrSender.begin(DISABLE_LED_FEEDBACK);
IrSender.setSendPin(IR_TX_PIN);
}
void loop() {
IrSender.sendNEC(0x1111, 0x34, 0); // 地址, 命令, 重复次数
delay(1000);
}
```cpp
需安装 IRremote 库(M5Cardputer 依赖自带)。
## 13. 搜索 WiFi / 连接 WiFi
M5 本地 examples 无专门 WiFi 例,以下基于 ESP32 原生 WiFi 库 +M5Radio 项目实测要点。
例程A 扫描附近热点:
```cpp
#include "M5Cardputer.h"
#include "WiFi.h"
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg);
M5Cardputer.Display.setRotation(1);
M5Cardputer.Display.setTextSize(0.5);
// ⚠ 实测要点(来自 M5Radio):扫描前先断开并关闭 autoReconnect,否则偶发返回 0 条
WiFi.disconnect(false);
WiFi.setAutoReconnect(false);
delay(150);
int n = WiFi.scanNetworks(false, true);
if (n <= 0) { delay(300); n = WiFi.scanNetworks(false, true); } // 偶发0重试一次
WiFi.setAutoReconnect(true);
for (int i = 0; i < n; i++) {
M5Cardputer.Display.print(i + 1); M5Cardputer.Display.print(": ");
M5Cardputer.Display.print(WiFi.SSID(i));
M5Cardputer.Display.print(" (");
M5Cardputer.Display.print(WiFi.RSSI(i));
M5Cardputer.Display.println("dBm)");
}
}
void loop() { M5Cardputer.update(); }
```cpp
要点:WiFi.SSID(i) 名称、WiFi.RSSI(i) 信号强度(dBm,越接近 0 越强,-30 极好 / -80 很弱)、WiFi.encryptionType(i) 加密方式。
例程B 连接 WiFi:
```cpp
#include "WiFi.h"
const char* ssid = "你的SSID";
const char* password = "你的密码";
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); }
// 已连上,可开始网络操作
}
```cpp
## 14. 电源 / 电池
来自 03 文档:
float voltage = M5Cardputer.Power.getBatteryVoltage(); // 电池电压,如 4.1
// 百分比参考 M5Radio:按 3.0V~4.2V 线性换算
充电时把电源开关拨到 ON。
RGB LED 由 GPIO38 供电,使用前需 digitalWrite(LED_EN, HIGH) 点亮。
插入 3.5mm 耳机后,扬声器功放会被禁用。
## 15. 综合示例:键盘输入终端
改编自 inputText.ino,做一个最小终端:输入字符串,Enter 提交到串口,可接你自己的逻辑。
```cpp
#include "M5Cardputer.h"
#include "M5GFX.h"
String data = "> ";
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
Serial.begin(115200);
M5Cardputer.Display.setRotation(1);
M5Cardputer.Display.setTextSize(0.5);
M5Cardputer.Display.drawString(data, 4, M5Cardputer.Display.height() - 24);
}
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange()) {
if (M5Cardputer.Keyboard.isPressed()) {
Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState();
for (auto i : status.word) data += i;
if (status.del) data.remove(data.length() - 1);
if (status.enter) {
String cmd = data.substring(2); // 去掉 "> "
Serial.println(cmd); // 提交你的处理
data = "> ";
}
M5Cardputer.Display.fillRect(0, M5Cardputer.Display.height() - 28,
M5Cardputer.Display.width(), 25, BLACK);
M5Cardputer.Display.drawString(data, 4, M5Cardputer.Display.height() - 24);
}
}
}
```cpp
## 附:本地材料索引(备查)
- API 文档:D:/M5AVD/CardputerAdv_资料/00_硬件规格与管脚表.md、01_Arduino IDE环境配置.md、02_依赖库说明.md、03_M5Cardputer核心API.md、04_示例代码汇总.md
- 已测例程:D:/M5AVD/CardputerAdv_资料/examples/(display / button / buzzer / keyboard/inputText / mic / sdcard / ir_nec / UI/REPL)
- 综合大案例(所有功能集成 + 网络收音机):D:/M5AVD/M5Radio(见另一篇《M5 网络收音机项目开发指南(M5Radio·已实测)》)