



为了让用户能够快速了解产品的各个功能,我们提供了一系列的测试例程,方便客户了解各个接口的使用,为了能够运行例程,需要准备的器件如下:
1. ESP32-S3-RGB-Matrix ×1
2. 任意型号的LED屏幕 x1 (如果有级联需求可以准备多个)
3. VH4 2PIN 散头线(约 500mm) ×1 (如果有级联需求可以准备多个)
4. 螺丝包 × 1
5. 扁平线 16PIN 约 200mm × 1 (如果有级联需求可以准备多个)
6. Micro SD卡 × 1
7. 8Ω 5W 喇叭 × 1
8. USB 线 Type-A 公口 → Type-C 公口 ×1
9. PSU-27W-USB-C-EU-B x 1** USB Type-C接口充电器

如需要级联多个屏幕,需要准备多个屏幕和多个扁平线,每个屏幕连接到一个扁平线端,如果供电不足可以准备双USB Type-C接口充电器供电。
TF 卡仅支持 MMC 通信方式。
USB 下载注意事项(重要)
开发板使用 USB 下载程序
若出现 无法识别端口 的情况,请进入 Boot 模式:
下载完成后,按 RESET 按键运行程序。
menuconfig 中配置以下选项:
Panel Height = 64
Panel Width = 64
根据具体像素大小配置,配错会显示错位。
Scan Wiring Pattern = Standard
扫描接线方式,选最常见标准模式。
Shift Driver IC = Generic
驱动芯片按通用模式初始化,适合大多数普通面板。
Bit Depth = 8-bit
颜色精度中等,效果和性能比较平衡。
Output Clock Speed = 20MHz
数据输出速度,20MHz 通常稳定且够用。
Minimum Refresh Rate = 60Hz
设置最低刷新率 60Hz,减少肉眼闪烁。
Default Brightness = 128
默认亮度一半,亮度和功耗折中。
Display Rotation = 0°
不旋转,按默认方向显示。
本章节包含以下部分,请按需阅读:
初次接触 Arduino ESP32 开发,想要快速上手?我们为您准备了一套通用的 入门教程。
请注意:该教程使用 ESP32-S3-Zero 作为教学示例,所有硬件代码均基于其引脚布局。在动手实践前,建议您对照手中的开发板引脚图,确认引脚配置无误。
请参考 安装和配置 Arduino IDE 教程 下载安装 Arduino IDE 并添加 ESP32 支持。
| 板名称 | 板安装要求 | 版本号要求 |
|---|---|---|
| esp32 by Espressif Systems | “离线”安装/“在线”安装 | 3.3.7 |

Arduino 示例程序:ESP32-S3-RGB-Matrix 示例程序-GitHub Arduino 示例程序:ESP32-S3-RGB-Matrix 示例程序-Gitee
下面给出每个示例的目的、要点说明与运行效果(以便快速上手)。
| 示例程序 | 基础例程说明 |
|---|---|
| 01_SimpleTestShapes | 简单形状绘画 |
| 02_PatternPlasma | 等离子特效 |
| 03_DoubleBuffer | 双缓冲测试,绘制动态图形 |
| 04_OtherShiftDriverPanel | 使用驱动芯片驱动屏幕 |
| 05_AnimatedGIFPanel_SD | 读取 SD 卡中的 GIF 图片并显示 |
| 06_BitmapIcons | 显示bmp 图片 |
| 07_Pixel_Mapping_Test | 展示HUB75基本控制逻辑 |
注意:
【代码分析】
loop():按顺序执行文字绘制、纯色填充与清屏操作,用于快速验证面板的基础显示功能。drawText(wheelval):根据 wheelval 绘制文字并改变颜色效果,用于检查字符渲染与颜色变化是否正常。dma_display->fillScreen():依次将屏幕填充为黑、红、绿、蓝、白等纯色,便于观察整屏刷新与颜色显示效果。delay(2000):每个显示步骤停留 2 秒,方便肉眼确认画面是否正确。dma_display->clearScreen():在测试结束后清空画面,避免上一帧内容残留。
void loop() {
// animate by going through the colour wheel for the first two lines
drawText(wheelval);
wheelval +=1;
delay(2000);
dma_display->clearScreen();
dma_display->fillScreen(myBLACK);
delay(2000);
dma_display->fillScreen( myRED);
delay(2000);
dma_display->fillScreen(myGREEN);
delay(2000);
dma_display->fillScreen(myBLUE);
delay(2000);
dma_display->fillScreen(myWHITE);
delay(2000);
dma_display->clearScreen();
}
【运行效果】

【代码分析】
loop():通过逐像素计算与调色板映射生成动态等离子特效。for (int x ...) / for (int y ...):遍历整块面板的每个像素,逐点计算并绘制颜色。sin8()、sin16()、cos16():结合坐标和 time_counter 生成动态变化的中间值 v,构造流动波纹效果。ColorFromPalette(currentPalette, (v >> 8)):根据计算结果从当前调色板中取色。dma_display->drawPixelRGB888():将计算出的 RGB 颜色写入当前像素。time_counter、cycles、fps:分别用于驱动动画变化、统计循环次数和计算绘制帧率。if (cycles >= 1024):重置计数器并随机切换调色板,实现不同色系自动轮换。Serial.printf_P():每 5 秒输出一次 Effect fps,用于观察特效绘制速度。
void loop() {
for (int x = 0; x < PANE_WIDTH; x++) {
for (int y = 0; y < PANE_HEIGHT; y++) {
int16_t v = 128;
uint8_t wibble = sin8(time_counter);
v += sin16(x * wibble * 3 + time_counter);
v += cos16(y * (128 - wibble) + time_counter);
v += sin16(y * x * cos8(-time_counter) / 8);
currentColor = ColorFromPalette(currentPalette, (v >> 8)); //, brightness, currentBlendType);
dma_display->drawPixelRGB888(x, y, currentColor.r, currentColor.g, currentColor.b);
}
}
++time_counter;
++cycles;
++fps;
if (cycles >= 1024) {
time_counter = 0;
cycles = 0;
currentPalette = palettes[random(0,sizeof(palettes)/sizeof(palettes[0]))];
}
// print FPS rate every 5 seconds
// Note: this is NOT a matrix refresh rate, it's the number of data frames being drawn to the DMA buffer per second
if (fps_timer + 5000 < millis()){
Serial.printf_P(PSTR("Effect fps: %d\n"), fps/5);
fps_timer = millis();
fps = 0;
}
} // end loop
【运行效果】

【代码分析】
loop():演示双缓冲动画的完整流程,包括切换缓冲区、后台绘制和更新运动状态。display->flipDMABuffer():将后续绘图切换到未显示的后台缓冲区,用于减少动态图形闪烁。delay(1000/display->calculated_refresh_rate):等待当前帧完成显示,避免过早翻转缓冲区导致撕裂或闪烁。display->clearScreen():清空后台缓冲区,为新一帧绘制做准备。delay(25):模拟耗时绘图过程,用于更直观地观察启用双缓冲后的平滑效果。display->fillRect():绘制多个运动方块,形成动态测试画面。velocityx / velocityy 判断逻辑:当方块碰到屏幕边界时反转运动方向,实现反弹效果。Squares[i].xpos / Squares[i].ypos 更新:根据速度更新方块坐标,推动下一帧动画。
void loop()
{
// Flip all future drawPixel calls to write to the back buffer which is NOT being displayed.
display->flipDMABuffer();
// SUPER IMPORTANT: Wait at least long enough to ensure that a "frame" has been displayed on the LED Matrix Panel before the next flip!
delay(1000/display->calculated_refresh_rate);
// Now clear the back-buffer we are drawing to.
display->clearScreen();
// This is here to demonstrate flicker if double buffering is disabled. Emulates a long draw routine that would typically occur after a 'clearscreen'.
delay(25);
for (int i = 0; i < numSquares; i++)
{
// Draw rect and then calculate
display->fillRect(Squares[i].xpos, Squares[i].ypos, Squares[i].square_size, Squares[i].square_size, Squares[i].colour);
if (Squares[i].square_size + Squares[i].xpos >= display->width()) {
Squares[i].velocityx *= -1;
} else if (Squares[i].xpos <= 0) {
Squares[i].velocityx = abs (Squares[i].velocityx);
}
if (Squares[i].square_size + Squares[i].ypos >= display->height()) {
Squares[i].velocityy *= -1;
} else if (Squares[i].ypos <= 0) {
Squares[i].velocityy = abs (Squares[i].velocityy);
}
Squares[i].xpos += Squares[i].velocityx;
Squares[i].ypos += Squares[i].velocityy;
}
}
【运行效果】

【代码分析】
loop():持续生成整屏动态特效,用于验证带移位寄存器驱动芯片面板的显示兼容性。for (int x ...) / for (int y ...):遍历整块屏幕,对每个像素分别计算颜色值。sin8()、sin16()、cos16():结合坐标和 time_counter 生成连续变化的颜色索引。ColorFromPalette(currentPalette, (v >> 8) + 127):根据中间值从调色板中映射出最终颜色。dma_display->drawPixelRGB888():将 RGB 颜色逐点写入 DMA 显示缓冲区。time_counter、cycles、fps:分别用于驱动动画变化、控制换色周期和统计绘制帧率。if (cycles >= 1024):定期重置动画参数并随机切换调色板,便于观察不同色彩下的显示效果。Serial.printf_P():周期输出 FPS 信息,用于评估当前图案绘制速度。void loop(){
for (int x = 0; x < dma_display->width(); x++) {
for (int y = 0; y < dma_display->height(); y++) {
int16_t v = 0;
uint8_t wibble = sin8(time_counter);
v += sin16(x * wibble * 3 + time_counter);
v += cos16(y * (128 - wibble) + time_counter);
v += sin16(y * x * cos8(-time_counter) / 8);
currentColor = ColorFromPalette(currentPalette, (v >> 8) + 127); //, brightness, currentBlendType);
dma_display->drawPixelRGB888(x, y, currentColor.r, currentColor.g, currentColor.b);
}
}
++time_counter;
++cycles;
++fps;
if (cycles >= 1024) {
time_counter = 0;
cycles = 0;
currentPalette = palettes[random(0,sizeof(palettes)/sizeof(palettes[0]))];
}
// print FPS rate every 5 seconds
// Note: this is NOT a matrix refresh rate, it's the number of data frames being drawn to the DMA buffer per second
if (fps_timer + 5000 < millis()){
Serial.printf_P(PSTR("Effect fps: %d\n"), fps/5);
fps_timer = millis();
fps = 0;
}
}
【运行效果】

【代码分析】
setup():完成 SD 卡、HUB75 面板和 GIF 解码器的初始化,为后续播放 GIF 动画做准备。SD_MMC.setPins():配置 SD 卡使用的时钟、命令和数据引脚。SD_MMC.begin("/sdcard", true):以 1-bit 模式挂载 SD 卡文件系统。SD_MMC.cardType()、cardSize()、totalBytes()、usedBytes():读取卡类型、容量和空间占用信息,用于确认存储介质状态。HUB75_I2S_CFG mxconfig(...):配置 HUB75 面板的宽度、高度和级联数量。dma_display = new MatrixPanel_I2S_DMA(mxconfig):创建 DMA 显示对象。dma_display->begin():启动 DMA 显示并分配显示缓冲区。SD_MMC.open("/gifs"):打开 GIF 文件目录。root.openNextFile():遍历 /gifs 目录中的文件。GifFiles.push_back(filename):将找到的 GIF 文件路径保存到列表中,供后续循环播放使用。gif.begin(LITTLE_ENDIAN_PIXELS):初始化 GIF 解码器,并设置像素字节序。void setup()
{
Serial.begin(115200);
// **************************** Setup SD Card access via SD_MMC 1-bit ****************************
if (!SD_MMC.setPins(BSP_SD_CLK, BSP_SD_CMD, BSP_SD_D0)) {
Serial.println("SD_MMC setPins Failed");
return;
}
if(!SD_MMC.begin("/sdcard", true)){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
//listDir(SD_MMC, "/", 1, false);
Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
// **************************** Setup DMA Matrix ****************************
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width
PANEL_RES_Y, // module height
PANEL_CHAIN // Chain length
);
// Keep ESP32-S3 default HUB75 mapping to avoid Flash/PSRAM reserved pins.
//mxconfig.clkphase = false;
//mxconfig.driver = HUB75_I2S_CFG::FM6126A;
// Display Setup
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
// Allocate memory and start DMA display
if( not dma_display->begin() )
Serial.println("****** !KABOOM! HUB75 memory allocation failed ***********");
dma_display->setBrightness8(128); //0-255
dma_display->clearScreen();
// **************************** Setup Sketch ****************************
Serial.println("Starting AnimatedGIFs Sketch");
// SD CARD STOPS WORKING WITH DMA DISPLAY ENABLED>...
File root = SD_MMC.open("/gifs");
if(!root){
Serial.println("Failed to open directory");
return;
}
File file = root.openNextFile();
while(file){
if(!file.isDirectory())
{
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
std::string filename = "/gifs/" + std::string(file.name());
Serial.println(filename.c_str());
GifFiles.push_back( filename );
// Serial.println("Adding to gif list:" + String(filename));
totalFiles++;
}
file = root.openNextFile();
}
file.close();
Serial.printf("Found %d GIFs to play.", totalFiles);
//totalFiles = getGifInventory("/gifs");
// This is important - Set the right endianness.
gif.begin(LITTLE_ENDIAN_PIXELS);
}
【运行效果】

【代码分析】
setup():完成显示初始化,并通过渐变方式绘制 WiFi 图标,验证位图资源与绘制接口是否正常。dma_display->begin():启动 HUB75 面板显示。dma_display->setBrightness8(90):设置面板亮度。dma_display->fillScreen() / dma_display->clearScreen():初始化和切换阶段清空画面,避免残影干扰。for (int r = 0; r < 255; r++):逐步增加红色分量,用于生成淡入动画。drawXbm565(0,0,64,32, wifi_image1bit, ...):将 WiFi 的 XBM 位图绘制到屏幕上。loop():循环切换不同图标,实现图标轮播显示。drawXbm565(5,0, 32, 32, icon_bits[current_icon]):绘制当前索引对应的图标数据。icon_name[current_icon]:通过串口输出当前显示的图标名称,便于调试。current_icon = (current_icon + 1) % num_icons:循环更新图标索引,确保轮播不会越界。void setup() {
// put your setup code here, to run once:
delay(1000); Serial.begin(115200); delay(200);
/************** DISPLAY **************/
Sprintln("...Starting Display");
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(90); //0-255
dma_display->clearScreen();
dma_display->fillScreen(dma_display->color444(0, 0, 0));
// Fade a Red Wifi Logo In
for (int r=0; r < 255; r++ )
{
drawXbm565(0,0,64,32, wifi_image1bit, dma_display->color565(r,0,0));
delay(10);
}
delay(2000);
dma_display->clearScreen();
}
void loop() {
// Loop through Weather Icons
Serial.print("Showing icon ");
Serial.println(icon_name[current_icon]);
drawXbm565(5,0, 32, 32, icon_bits[current_icon]);
current_icon = (current_icon +1 ) % num_icons;
delay(2000);
dma_display->clearScreen();
}
【运行效果】

【代码分析】
loop():按行列顺序逐点点亮像素,用于检查面板像素映射与软件配置是否一致。for (int i ...) / for (int j ...):遍历 FourScanPanel 的全部像素坐标。FourScanPanel->drawPixel(j, i, FourScanPanel->color565(255, 0, 0)):将当前像素点亮为红色,形成可观察的扫描轨迹。delay(30):让扫描点以较慢速度移动,便于观察实际点亮顺序。dma_display->clearScreen():整屏扫描完成后清空画面,开始下一轮测试。delay(2000):在每轮扫描结束后停留 2 秒,方便确认映射结果是否正确。void loop() {
for (int i = 0; i < FourScanPanel->height(); i++)
{
for (int j = 0; j < FourScanPanel->width(); j++)
{
FourScanPanel->drawPixel(j, i, FourScanPanel->color565(255, 0, 0));
delay(30);
}
}
delay(2000);
dma_display->clearScreen();
} // end loop
【运行效果】

本章节包含以下部分,请按需阅读:
初次接触 ESP32 ESP-IDF 开发,想要快速上手?我们为您准备了一套通用的 入门教程。
请注意:该教程使用 ESP32-S3-Zero 作为教学示例,所有硬件代码均基于其引脚布局。在动手实践前,建议您对照手中的开发板引脚图,确认引脚配置无误。
以下内容以 Windows 系统为例,使用 VS Code + ESP-IDF 扩展 的方式进行开发。Mac/Linux 用户请参考 官方说明。
此部分图示以安装 ESP-IDF V5.2.2 为例示范,安装时请选用与您开发板示例匹配的 ESP-IDF 版本。
前往 ESP-IDF Installation Manager 下载 ESP-IDF 安装管理器。这是乐鑫最新推出的跨平台安装工具,下文将演示如何使用其离线安装功能。
在页面中点击 Offline Installer 标签,然后在筛选栏中选择 Windows 操作系统和你需要的 ESP-IDF 版本(图示仅为参考,请以实际为准)。

确认选择无误后,点击下载按钮。浏览器将自动同时下载两个文件:一个是 ESP-IDF 离线整合包(.zst),另一个是 ESP-IDF 安装器(.exe)。

请耐心等待两个文件下载完成。
下载完成后,双击运行 ESP-IDF 安装器(eim-gui-windows-x64.exe)。
启动后,可在右上角将界面语言切换为中文。

安装工具会自动检测同一目录下是否存在离线整合包。点击 从存档安装。

接下来,选择安装路径。建议使用默认路径;若需自定义,请确保路径中不包含中文或空格。确认无误后,点击 开始安装。

当看到如下界面时,表示 ESP-IDF 已安装成功。

建议同时安装驱动程序。点击 完成安装,然后点击 安装驱动程序。

下载并安装 Visual Studio Code。
安装时建议勾选 通过 Code 打开操作添加到 Windows 资源管理器文件上下文菜单,以便快速打开项目文件夹。
在 VS Code 中,点击侧边活动栏中的 扩展图标(或使用快捷键 Ctrl + Shift + X)打开 扩展 视图。
在搜索框中输入 ESP-IDF,找到 ESP-IDF 扩展并点击安装。

当 ESP-IDF 扩展版本 ≥ 2.0 时,扩展会自动检测并识别上述步骤中安装的 ESP-IDF 环境,无需手动配置。
IDF 示例程序:ESP32-S3-RGB-Matrix 示例程序-GitHub IDF 示例程序:ESP32-S3-RGB-Matrix 示例程序-Gitee
下面给出每个示例的目的、要点说明与运行效果(以便快速上手)。
| 示例程序 | 基础例程说明 |
|---|---|
| 01_Matrix_RGBW | 简单测试 RGBW 灯颜色切换 |
| 02_Matrix_Font_5x7 | 测试 5x7 字体显示 |
| 03_Matrix_QMI | 测试 QMI 功能显示 |
| 04_Matrix_RTC | 测试 RTC 时间显示 |
| 05_Matrix_SDCard | 测试 SD 卡挂载与容量读取 |
| 06_Matrix_SHTC3 | 测试 SHTC3 温湿度传感器 |
| 07_Matrix_WiFi | 测试 WiFi 连接 |
| 08_Matrix_Audio | 测试音频播放 |
【代码分析】
rgbw_start():循环切换板载 RGBW 灯颜色,用于验证灯光驱动与日志输出是否正常。sizeof(rgbw_colors) / sizeof(rgbw_colors[0]):计算预设颜色数组长度,供循环切换使用。bsp_display_lock():加锁后操作显示界面,避免与其他显示任务冲突。lv_obj_set_style_bg_color(screen, lv_color_hex(0x000000), 0):将当前屏幕背景设置为黑色,减少灯光测试时的界面干扰。rgbw_set_color(rgbw_colors[color_index].hex_color):把当前颜色值输出到 RGBW 灯珠。ESP_LOGI(TAG, "Current color: %s", ...):打印当前颜色名称,便于调试和观察切换顺序。vTaskDelay(pdMS_TO_TICKS(2000)):每种颜色保持 2 秒,方便观察显示效果。if (color_index >= num_colors):颜色索引到达末尾后回到起点,实现循环切换。void rgbw_start(void) {
/* =======================
* 1. Basic Parameters
* ======================= */
int color_index = 0;
const int num_colors = sizeof(rgbw_colors) / sizeof(rgbw_colors[0]);
/* =======================
* 2. Init Screen
* ======================= */
bool locked = bsp_display_lock(1000);
if (locked) {
lv_obj_t *screen = lv_scr_act();
lv_obj_set_style_bg_color(screen, lv_color_hex(0x000000), 0);
bsp_display_unlock();
}
/* =======================
* 3. Loop Colors
* ======================= */
while (true) {
locked = bsp_display_lock(1000);
if (locked) {
rgbw_set_color(rgbw_colors[color_index].hex_color);
bsp_display_unlock();
}
ESP_LOGI(TAG, "Current color: %s", rgbw_colors[color_index].name);
vTaskDelay(pdMS_TO_TICKS(2000));
color_index++;
if (color_index >= num_colors) {
color_index = 0;
}
}
}
【运行效果】




【代码分析】
font_5x7_start():启动 5x7 字体示例界面,并保持任务常驻运行。ESP_LOGI(TAG, "Matrix Font 5x7 start"):输出启动日志,便于确认示例已经进入运行状态。bsp_display_lock(0):进入 LVGL 显示上下文前先加锁,确保界面初始化过程安全。font_5x7_ui_init():创建 5x7 字体示例所需的界面对象。font_5x7_ui_apply():将字体、布局和默认文本等配置应用到界面上。while (true):保持任务持续存在,避免示例初始化后立即退出。vTaskDelay(pdMS_TO_TICKS(1000)):空闲等待,降低任务空转占用。void font_5x7_start(void) {
/* =======================
* 1. Start Display
* ======================= */
ESP_LOGI(TAG, "Matrix Font 5x7 start");
/* =======================
* 2. Init UI (LVGL Locked)
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
font_5x7_ui_init();
font_5x7_ui_apply();
bsp_display_unlock();
}
/* =======================
* 3. Idle Loop
* ======================= */
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
qmi_start():完成 QMI8658 传感器界面初始化、驱动启动和定时刷新配置。qmi_ui_init():创建 QMI8658 数据显示界面。middle_init_qmi8658():初始化 QMI8658 传感器驱动。qmi_state.qmi_init_ret:保存传感器初始化结果,供界面层判断状态并显示提示。example_ui_install_timer(100, qmi_data_update):安装 100 ms 周期定时器,定时刷新姿态或加速度数据。qmi_data_update:在定时回调中更新传感器数据与界面显示。while (true):保持任务常驻运行。vTaskDelay(pdMS_TO_TICKS(1000)):空闲等待,减少任务资源占用。void qmi_start(void) {
/* =======================
* 1. Start Display & UI
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
qmi_ui_init();
bsp_display_unlock();
}
/* =======================
* 2. Start Sensor & Timer
* ======================= */
qmi_state.qmi_init_ret = middle_init_qmi8658();
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(100, qmi_data_update);
bsp_display_unlock();
}
/* =======================
* 3. Idle Loop
* ======================= */
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
rtc_start():完成 RTC 界面初始化、设时、闹钟配置和实时刷新。rtc_ui_init():创建时间显示相关的界面元素。middle_rtc_init():初始化 RTC 驱动与底层硬件接口。middle_rtc_set_time(rtc_state.rtc_time):将状态结构体中的初始时间写入 RTC 芯片。middle_rtc_alarm(3):配置 RTC 闹钟测试条件,用于验证闹钟功能是否正常。example_ui_install_timer(1, rtc_data_update):安装高频刷新定时器,使界面实时同步当前时间。rtc_data_update:在回调中读取 RTC 数据并更新显示内容。while (true):保持 RTC 示例任务持续运行。void rtc_start(void) {
bool locked = bsp_display_lock(0);
if (locked) {
rtc_ui_init();
bsp_display_unlock();
}
middle_rtc_init();
middle_rtc_set_time(rtc_state.rtc_time);
middle_rtc_alarm(3);
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(1, rtc_data_update);
bsp_display_unlock();
}
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
sdcard_start():完成 SD 卡界面初始化、底层驱动启动和状态定时刷新。sdcard_ui_init():创建用于显示挂载状态、容量和存储信息的界面组件。middle_sdcard_init():执行 SD 卡底层初始化,通常包括总线配置、卡识别和文件系统挂载。example_ui_install_timer(1000, sdcard_data_update):安装 1 秒周期定时器,定时刷新 SD 卡状态与容量信息。sdcard_data_update:在回调中更新 SD 卡显示内容。while (true):保持示例任务持续运行。vTaskDelay(pdMS_TO_TICKS(1000)):空闲等待,减少任务占用。void sdcard_start(void) {
/* =======================
* 1. Start Display & UI
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
sdcard_ui_init();
bsp_display_unlock();
}
/* =======================
* 2. Init SD Card
* ======================= */
middle_sdcard_init();
/* =======================
* 3. Periodic Refresh
* ======================= */
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(1000, sdcard_data_update);
bsp_display_unlock();
}
/* =======================
* 4. Idle Loop
* ======================= */
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
shtc3_start():完成 SHTC3 界面初始化、驱动启动和温湿度数据周期刷新。shtc3_ui_init():创建温度、湿度和状态提示等界面元素。middle_init_shtc3():初始化 SHTC3 传感器驱动。shtc3_state.shtc3_init_ret:保存初始化结果,供界面层判断是否正常显示数据。example_ui_install_timer(500, shtc3_data_update):安装 500 ms 周期定时器,定时更新传感器数据。shtc3_data_update:在回调中读取温湿度信息并刷新界面。while (true):保持示例任务持续运行。vTaskDelay(pdMS_TO_TICKS(1000)):空闲等待,降低任务占用。void shtc3_start(void) {
/* =======================
* 1. Start Display & UI
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
shtc3_ui_init();
bsp_display_unlock();
}
/* =======================
* 2. Init Sensor & Timer
* ======================= */
shtc3_state.shtc3_init_ret = middle_init_shtc3();
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(500, shtc3_data_update);
bsp_display_unlock();
}
/* =======================
* 3. Idle Loop
* ======================= */
while (true){
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
wifi_start():完成 WiFi 界面初始化、STA 参数配置、驱动启动和状态刷新。wifi_ui_init():创建网络状态显示界面。middle_wifi_set_sta_config(WIFI_STA_SSID, WIFI_STA_PASS):设置目标热点的 SSID 和密码。middle_wifi_init():启动 WiFi 驱动并发起连接流程。wifi_state.wifi_init_ret:保存 WiFi 初始化结果,供界面显示连接状态。example_ui_install_timer(1000, wifi_data_update):安装 1 秒周期定时器,定时刷新连接状态和网络信息。wifi_data_update:在回调中更新 WiFi 连接状态、IP 地址等界面内容。while (true):保持示例任务持续运行。void wifi_start(void) {
/* =======================
* 1. Start Display & UI
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
wifi_ui_init();
bsp_display_unlock();
}
/* =======================
* 2. Configure & Enable WiFi
* ======================= */
middle_wifi_set_sta_config(WIFI_STA_SSID, WIFI_STA_PASS);
wifi_state.wifi_init_ret = middle_wifi_init();
/* =======================
* 3. Periodic Refresh
* ======================= */
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(1000, wifi_data_update);
bsp_display_unlock();
}
/* =======================
* 4. Idle Loop
* ======================= */
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

【代码分析】
audio_start():完成音频界面初始化、音频任务创建和状态定时刷新。audio_ui_init():创建音量、播放状态或频谱相关的界面元素。audio_state.audio_out_vol = VOLUME:设置默认音频输出音量。xTaskCreate(audio_task, "aud", 4096, NULL, tskIDLE_PRIORITY + 4, NULL):创建独立音频任务,在后台处理音频业务逻辑。example_ui_install_timer(100, audio_data_update):安装 100 ms 周期定时器,定时同步音频状态到界面。audio_data_update:在回调中更新播放状态、音量或其他音频信息。while (true):保持示例任务持续运行。vTaskDelay(pdMS_TO_TICKS(1000)):空闲等待,降低主任务占用。void audio_start(void) {
/* =======================
* 1. Start Display & UI
* ======================= */
bool locked = bsp_display_lock(0);
if (locked) {
audio_ui_init();
bsp_display_unlock();
}
/* =======================
* 2. Start Audio Task
* ======================= */
audio_state.audio_out_vol = VOLUME;
xTaskCreate(audio_task, "aud", 4096, NULL, tskIDLE_PRIORITY + 4, NULL);
/* =======================
* 3. Periodic UI Refresh
* ======================= */
locked = bsp_display_lock(0);
if (locked) {
example_ui_install_timer(100, audio_data_update);
bsp_display_unlock();
}
/* =======================
* 4. Idle Loop
* ======================= */
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
【运行效果】

开发板设计文件