Skip to content

Grove 外设

主菜单按键:e

外接模块集合:左侧 Grove 的 I2C(收音机、NFC、总线扫描)、UART(GPS;亦支持 Adv 上 Cap LoRa-1262 GNSS)。选择页每页最多 8 项;数字键按当前页从 1 编号,字母快捷键不依赖当前页即可直达。子应用中 ESC / GO 回到本集合;在选择页再按一次返回主菜单。

本页说明固件里已经落地的芯片接线、功能,以及源码 API。收音机见 Radio;NFC 见 NFC;GPS 见 GPS;总线扫描见 I2C 扫描CC1101 驱动源码仍在,选择页入口暂隐藏(未完成)。

截图

选择页

exi2c-hub

子应用

按键子应用总线芯片功能
1 / rRADIOGrove I2CTEA5767 / RDA5807MFM 收音、搜台、电台列表;RDA 另有音量 / RDS
2 / eEXI2Grove I2C扫描到的任意地址列地址、猜测芯片名与用途
3 / nNFCGrove I2CST25R3916(Unit NFC)读 / 写 13.56 MHz、NDEF / 历史卡模拟、历史
4 / gGPSGrove UART 或 Cap UARTAT6668(Unit / Cap LoRa GNSS)Live / 速度 / 星图 / 录制;自动探测源

快捷键

按键作用
18进入当前页对应子应用
r / e / n / g直达 RADIO / EXI2 / NFC / GPS
[ ] / 方向键选择页翻页(超过 8 项时)
ESC / GO子应用 → 选择页 → 主菜单
h子应用内 Help(选择页无 Help)

硬件接口

Cardputer-ADV 对外有两路常用外设口。Grove 集合把它们放在同一个入口,但协议不同,不能混插电源

左侧 Grove(Ex_I2C)

屏幕朝自己、键盘在下时,机身左侧 HY2.0-4P 橡胶座。固件里对应 M5Cardputer.Ex_I2C。进入相关 App 时会 Ex_I2C.begin()(启动阶段只 setPort,不 begin 则 Grove 扫描全空)。

顺序(上→下)针脚作用
1GND
25V电源(给 5V 模块)
3G2SDA
4G1SCL

收音机模块按丝印 SDA / SCL / VCC / GND 对到上表,不要按模块从左到右硬数。音频走模块 3.5 mm 耳机孔,不走机身喇叭。

备用:Grove 上探测不到 FM 芯片时,Radio 会再试 M5Cardputer.In_I2C(EXT 排针 G8=SDA / G9=SCL)。

背面 EXT14(CC1101 SPI)

与 microSD 共用 SPI,片选独立。固件用 FSPI,SPISettings(2 MHz, MSBFIRST, SPI_MODE0)

模块脚GPIO作用
VCC3.3 V仅 3.3 V,禁止接 5V
GNDGND
CSNG13片选
SCKG40SPI 时钟
MOSIG14主机输出
MISOG39主机输入
GDO0G15RX/TX 完成中断
GDO2G5可选载波侦测(固件已接,RST 未接)

EXT14 上的 5VIN / 5VOUT 是 5 V,不能给 CC1101 当 VCC。


已接入的芯片

TEA5767(FM)

总线I2C,地址 0x60
优先 Grove G2/G1,其次 In_I2C G8/G9
频率单位0.01 MHz(9850 = 98.50 MHz)
频段欧带 87.50–108.00 MHz;日带 76.00–91.00 MHz
步进0.10 MHz
音量芯片无音量寄存器,用耳机旋钮
探测scanID(0x60);写 5 字节寄存器组
源码include/tea5767.hsrc/tea5767.cpp

功能:调谐、静音、强制单声道、软静音、弱台削高音(HCC)、立体声噪声抑制(SNC)、去加重 50/75 µs、本振高/低边注入(HLSI)、硬件搜台(SM/SUD/SSL)、左右声道静音、standby。电平 ADC 只在写寄存器后更新,界面会周期性 kickAdc()

RDA5807M(FM + RDS)

总线I2C;顺序地址 0x10,随机地址 0x11
同 TEA5767
频率单位0.01 MHz
频段87–108 / 76–91 / 76–108 / 65–76 / 50–76 MHz
步进25 / 50 / 100 / 200 kHz
音量芯片 0–15
探测读寄存器 0x00,芯片 ID 高字节为 0x58
源码include/rda5807m.hsrc/rda5807m.cpp

功能:调谐 / 硬件搜台、静音、高阻输出、低音增强、软静音、弱立体声混单声道、AFC、RDS/RBDS(站名 PS、电台文本 RT、时钟 CT、备选频率 AF)、可选 I2S。I2C 扫描写探测可能误开射频,扫完会 silence():写 0x02 = 0(ENABLE=0、音频高阻)。

FmTuner::begin() 先探 RDA,再探 TEA。两颗同时在线时走 RDA。

CC1101(433 MHz Sub-GHz,入口暂隐藏)

源码与 EXT14 接线仍保留,但 Grove 选择页暂不显示(功能未完成)。勿与 Cap LoRa GNSS 同时假定占用 G13 / G15

总线SPI(非 I2C),库 RadioLib
EXT14,见上表
默认频率433.92 MHz
可调范围387.00–464.00 MHz,步进 0.25 MHz
调制begin(freq, 4.8 kbps, 4.8 kHz 频偏, 58 kHz RX BW, 10 dBm, 32 bit 前导)
源码include/app_cc1101.hsrc/app_cc1101.cpp

功能(代码已有):初始化 / 再初始化、发测试包 CP-<序号>、监听约 3 s 收包、方向键改频率、500 ms 刷新 RSSI。无芯片显示 NOT FOUND。离开 App 时 standby()

I2C 扫描地址表(仅猜测)

扫描地址 8–1190x080x77)。绿点=表内已知映射,灰点=未知(显示 -- / unknown)。ExI2 表是常见 Grove / Unit 猜测,不是驱动清单。固件真正驱动的外接芯片主要是上列 FM、NFC、GPS(及暂隐藏的 CC1101)。

地址猜测芯片用途
0x10 / 0x11RDA5807Mradio
0x18ES8311codec
0x23BH1750light
0x26MiniScaleweight
0x29VL53L0XToF
0x34TCA8418keyboard
0x3C / 0x3DSSD1306OLED
0x418Encoderencoder
0x438Angleangle
0x44SHT3xENV
0x48ADS1115ADC
0x50EEPROMmemory
0x51BM8563RTC
0x57UnitUSsonar
0x5AMLX90614NCIR
0x5FCardKBkeyboard
0x60TEA5767radio
0x61PbHubhub
0x68 / 0x69BMI270IMU
0x70QMP6988ENV
0x76 / 0x77BMP280ENV

板载确认(Hardware Test → InI2):0x18 ES8311、0x34 TCA8418、0x68 BMI270。


App 层 API

入口约定与其它 App 相同:enter* / leave* / update* / handle*,Help 走 close* / is*HelpVisible

app_ex_i2c(集合)

cpp
void enterExI2cApp();
void leaveExI2cApp();
void updateExI2cApp();
void handleExI2cApp(const Keyboard_Class::KeysState& status);
bool handleExI2cBack();          // 子应用内回 hub;已在 hub 返回 false
bool closeExI2cHelp();           // Radio / 扫描 / CC1101 / NFC / GPS Help 委托
bool isExI2cHelpVisible();
bool isExI2cRadioActive();       // 截图 slug
bool isExI2cCc1101Active();

handleExI2cBack()main.cpp 里先于回主菜单调用。离开集合时会停 Radio / 静音总线上的 FM / 停 CC1101 / 停 NFC / 停 GPS。

app_radio

cpp
void enterRadioApp();
void leaveRadioApp();
void silenceFmRadioOnBus(m5::I2C_Class& bus); // 扫描写探测后 mute + standby
void updateRadioApp();
void handleRadioApp(const Keyboard_Class::KeysState& status);
bool closeRadioHelp();
bool closeRadioStations();
bool closeRadioSeek();
bool isRadioHelpVisible();

app_i2c_scan

cpp
void drawI2cScanApp(m5::I2C_Class& bus, const char* title, bool internal_bus);
void handleI2cScanApp(const String& key, m5::I2C_Class& bus,
                      const char* title, bool internal_bus);
bool closeI2cScanHelp(m5::I2C_Class& bus, const char* title, bool internal_bus);
bool isI2cScanHelpVisible();
void resetI2cScanHelp();

Grove 集合传入 M5Cardputer.Ex_I2C, "ExI2", false。Hardware Test 的 InI2 / ExI2 共用同一套函数。drawI2cScanApp 内部 bus.scanID(found),随后 silenceFmRadioOnBus(bus)

app_cc1101

cpp
void enterCc1101App();
void leaveCc1101App();
void updateCc1101App();
void handleCc1101App(const Keyboard_Class::KeysState& status);
bool closeCc1101Help();
bool isCc1101HelpVisible();
按键作用
r按当前频率重新 begin
t发送 CP-<序号>
lstartReceive(),约 3 s 超时
方向键±0.25 MHz
h接线与按键 Help

驱动 API

Radio App 经 FmTuner 门面调用两颗 FM 芯片;芯片专属能力仍从 tea() / rda() 取出。频率一律 0.01 MHz

FmTunerinclude/fm_tuner.h

cpp
bool begin(m5::I2C_Class& bus);          // RDA → TEA
void detach();
static void silenceIfPresent(m5::I2C_Class& bus);

Chip chip() const;                       // None / Tea5767 / Rda5807m
bool isRda() const;
const char* chipName() const;

uint16_t freqMin() const;
uint16_t freqMax() const;
uint16_t freqStep() const;
void setFrequency(uint16_t freq_centi, bool wait_settle = true);
bool readStatus(Status& out);            // RSSI 统一到 0–15
void refreshSignal();                    // TEA:kickAdc

void setMute(bool on);
void setMono(bool on);
void setStandby(bool on);
void startSearch(bool up);
void abortSearch();

Tea5767& tea();
Rda5807m& rda();

Statusfreq_centirssi(0–15)、raw_rssiqualitystereoreadyband_limitvalid_stationrds_ready / rds_synced

TEA 专属 setter(RDA 模式下不写寄存器):setJapanBandsetDeemphasis75setHighSideInjectionsetSoftMutesetHighCutsetStereoNoiseCancelsetSeekStopsetChannelMute

Tea5767

cpp
bool begin(m5::I2C_Class& bus);
bool probe() const;
bool silence(m5::I2C_Class& bus);

void setFrequency(uint16_t freq_centi, bool wait_settle = true);
uint16_t getFrequency();
bool readStatus(Status& out);
void kickAdc();
void startSearch(bool up);
void abortSearch();

void setMute(bool on);
void setMono(bool on);
void setSoftMute(bool on);
void setHighCut(bool on);
void setStereoNoiseCancel(bool on);
void setJapanBand(bool on);
void setDeemphasis75(bool on);
void setHighSideInjection(bool on);
void setSeekStop(SeekStop level);     // Low / Mid / High
void setChannelMute(ChannelMute ch);  // Off / Left / Right
void setStandby(bool on);
void setPort1(bool high);
void setPort2(bool high);

Rda5807m

cpp
bool begin(m5::I2C_Class& bus, bool reset = true);
bool probe(uint16_t* chip_id = nullptr);
bool initialize();
bool softReset();
bool silence(m5::I2C_Class& bus);
bool setStandby(bool standby);

bool setBand(Band band);
bool setSpacing(Spacing spacing);
bool setFrequency(uint16_t freq_centi, bool wait = true, uint32_t timeout_ms = 500);
bool startTune(uint16_t freq_centi);
bool pollTune(Status* status = nullptr);
bool startSeek(bool up);
bool abortSeek();
bool waitSeek(uint32_t timeout_ms = 5000, Status* status = nullptr);

bool setMute(bool mute);
bool setMono(bool mono);
bool setHighZ(bool high_z);
bool setVolume(uint8_t volume);          // 0–15
bool setBass(bool enabled);
bool setDeemphasis50(bool use_50us);
bool setSoftMute(bool enabled);
bool setSoftBlend(bool enabled);
bool setAfc(bool enabled);
bool setSeekThreshold(uint8_t threshold);
bool setSeekWrap(bool wrap);
bool setRds(bool enabled);
bool setRbds(bool enabled);
bool pollRds(RdsGroup* group = nullptr);

const char* programService() const;      // PS
const char* radioText() const;           // RT
uint16_t programId() const;              // PI

诊断:readRegister / writeRegister 仅公开寄存器,写限制在 0x020x08

RadioLib CC1101

固件用法(不是完整 RadioLib 列表):

cpp
g_radio.begin(freq_mhz, 4.8f, 4.8f, 58.0f, 10, 32);
g_radio.setFrequency(freq_mhz);
g_radio.transmit(payload);
g_radio.startReceive();
g_radio.available();
g_radio.readData(buf, len);
g_radio.getRSSI();
g_radio.standby();

m5::I2C_Class(总线)

全局:M5Cardputer.Ex_I2CM5Cardputer.In_I2C。扫描与驱动都走这一层:

方法用途
begin()初始化 Grove / 内部口
isEnabled()是否已 init
scanID(bool result[120]) / scanID(addr)扫描或探单个地址
getSDA() / getSCL()当前引脚
writeRegister* / readRegister*寄存器读写

底层整理见仓库 api/M5Unified.md 的 I2C_Class 一节。


使用说明

  1. 主菜单按 e 打开 Grove。暖绿卡片:1 RADIO、2 EXI2、3 NFC、4 GPS(CC1101 入口暂隐藏)。
  2. 收音机:4 pin 成品板插左侧 Grove(G2=SDA、G1=SCL),耳机插模块孔。无芯片显示 NO MOD。操作见 Radio
  3. 扫描:插上外设后进 EXI2,或 Hardware Test 8r 再扫。扫 FM 地址可能短暂出声,扫完会 mute + standby。
  4. NFC:Unit NFC(ST25R3916)插左侧 Grove。见 NFC
  5. GPS:Grove AT6668 Unit,或 Adv + Cap LoRa-1262 GNSS;进入时自动探测。见 GPS
  6. 退出子应用或整个集合时,FM / NFC / GPS 会停总线或关串口,避免占口。

Sparks for M5Stack Cardputer