跳到主要内容

Arduino 开发

本章节包含以下部分,请按需阅读:

Arduino 入门教程

初次接触 Arduino ESP32 开发,想要快速上手?我们为您准备了一套通用的 入门教程

请注意:该教程使用 ESP32-S3-Zero 作为教学示例,所有硬件代码均基于其引脚布局。在动手实践前,建议您对照手中的开发板引脚图,确认引脚配置无误。

配置开发环境

1. 安装和配置 Arduino IDE

请参考 安装和配置 Arduino IDE 教程 下载安装 Arduino IDE 并添加 ESP32 支持。

2. 安装库

要运行示例,需要安装对应的库。 可从 此链接 下载 ESP32-C6-LCD-0.85 开发板的示例程序包。包内的 Arduino\libraries 目录已包含本教程所需的全部库文件。

库或文件名称说明版本安装方式
lvglLVGL 图形化库v8.4.0 或 v9.3.0通过库管理器或手动安装
GFX_Library_for_ArduinoGFX 图形化库v1.6.0通过库管理器或手动安装
U8g2图形显示库v2.35.30通过库管理器或手动安装
FastLEDRGB 灯驱动库v3.10.1通过库管理器或手动安装
ESP32-audioI2S-master音频处理库v3.4.0通过库管理器或手动安装
OneButton按键库v2.6.1通过库管理器或手动安装
版本兼容性说明

LVGL 及其驱动库的版本之间存在较强的依赖关系。例如,为 LVGL v8 编写的驱动可能不兼容 LVGL v9。为确保示例能够稳定复现,推荐使用上表列出的特定版本。混合使用不同版本的库可能导致编译失败或运行时异常。

安装步骤:

  1. 解压已下载的 示例程序

  2. 将其 Arduino\libraries 目录下的所有文件夹(ESP32-audioI2S-master 、GFX_Library_for_Arduino 等)复制到 Arduino 的库文件夹中。

    信息

    Arduino 库文件夹的路径通常是:c:\Users\<用户名>\Documents\Arduino\libraries

    也可以在 Arduino IDE 中通过 文件 > 首选项,查看“项目文件夹位置”来定位。库文件夹就是此路径下的 libraries 文件夹。

  3. 其他安装方式请参考:Arduino 库管理教程

ESP32-C6-LCD-0.85 所需开发板安装说明

板名称板安装要求版本号要求
ESP32 by Espressif Systems“离线”安装/“在线”安装3.2.0

3. 其他提示

ESP32-C6-LCD-0.85 需要选择及配置开发板。

  1. ESP32-C6-LCD-0.85 需要选择 ESP32C6 Dev Module。
  2. 选择 USB 端口
  3. ESP32-C6-LCD-0.85 使用 ESP32-C6 原生 USB 接口,而非 UART 转 USB。对于串口通信:
    • printf() 函数可直接使用;

    • 若要使用 Serial.println() 函数,需要额外配置:在 IDE 工具菜单中启用"USB CDC On Boot"选项,或在代码中声明 HWCDC 对象处理 USB 串口通信。

  4. 选择 8MB flash
  5. 选择合适大小的分区表

示例程序

Arduino 示例程序位于 示例程序Arduino/examples 目录中。

示例程序基础例程说明依赖库
01_audio_out读取 SD 卡的音频文件,并播放ESP32-audioI2S-master
02_button_example按键测试OneButton
03_ws2812b_example测试 RGB 灯FastLED
04_gfx_helloworld屏幕上显示 HelloWorldGFX_Library_for_Arduino
05_esp_wifi_analyzer屏幕上显示 WiFi 信号强度GFX_Library_for_Arduino
06_gfx_u8g2_font通过加载字库,实现各国文字显示GFX_Library_for_Arduino、U8g2
07_sd_card_test测试 SD 卡的读写---
08_lvgl_example_v8lvgl v8.4.0 示例程序GFX_Library_for_Arduino、lvgl
09_lvgl_example_v9lvgl v9.3.0 示例程序GFX_Library_for_Arduino、lvgl

01_audio_out

本示例演示 ESP32-C6-LCD-0.85 使用喇叭播放音频,屏幕无现象。

代码解释

  • 设置 I2S 引脚:
    void setupI2S() {
    i2s.setPins(I2S_BCK_PIN, I2S_LRCK_PIN, I2S_DOUT_PIN, I2S_DIN_PIN, I2S_MCK_PIN);
    // Initialize the I2S bus in standard mode
    if (!i2s.begin(I2S_MODE_STD, EXAMPLE_SAMPLE_RATE, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT)) {
    Serial.println("Failed to initialize I2S bus!");
    return;
    }
    }
  • 设置播放的音频数据:
    i2s.write((uint8_t *)audio_data, AUDIO_SAMPLES * 2);

运行效果

  • 播放音频文件,屏幕无现象

02_button_example

本示例演示如何使用 OneButton 库读取按键的单击、双击和长按等状态,并通过串口打印。

代码解释

  • 绑定回调函数:

    button1.attachClick(click1);
    button1.attachDoubleClick(doubleclick1);
    button1.attachLongPressStart(longPressStart1);
    button1.attachLongPressStop(longPressStop1);
    button1.attachDuringLongPress(longPress1);

运行效果

  • 屏幕无现象
  • 串口打印按钮信息

03_ws2812b_example

本示例 ESP32-C6-LCD-0.85 使用 FastLED 驱动 sw2812b RGB 灯,每 500ms 切换一种随机的颜色

代码解释

  • 初始化 ws2812b, 并设置亮度:

    FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS); // GRB ordering is typical
    FastLED.setBrightness(100); // 0-255

运行效果

  • 屏幕无现象
  • RGB 灯每 500ms 切换一种随机的颜色

04_gfx_helloworld

本示例演示 ESP32-C6-LCD-0.85 使用 GFX_Library_for_Arduino 库驱动屏幕并在屏幕上显示 HelloWorld

代码解释

  • 配置屏幕接口、分辨率等
    Arduino_DataBus *bus = new Arduino_HWSPI(3 /* DC */, 5 /* CS */, 1 /* SCK */, 2/* MOSI */, GFX_NOT_DEFINED /* MISO */);
    Arduino_GFX *gfx = new Arduino_ST7735(bus, 4 /* RST */, 0 /* rotation */, true /* IPS */,128 /* width */, 128 /* height */,2 /* col offset 1 */, 3 /* row offset 1 */);

运行效果

  • 屏幕显示

05_esp_wifi_analyzer

本示例演示 ESP32-C6-LCD-0.85 使用 GFX_Library_for_Arduino 库显示 WiFi 频段信号强度

运行效果

  • 屏幕显示

06_gfx_u8g2_font

本示例演示 ESP32-C6-LCD-0.85 使用 GFX_Library_for_Arduino 库通过加载字库,实现各国文字显示

运行效果

  • 屏幕显示

07_sd_card_test

本示例使用 ESP32-C6-LCD-0.85 测试 SD 卡的读写功能

代码

07_sd_card_test.ino
#include "FS.h"
#include "SD_MMC.h"

int clk = 16;
int cmd = 15;
int d0 = 17;
int d1 = 18;
int d2 = 13;
int d3 = 14;

void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);

File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}

File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels) {
listDir(fs, file.path(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}

void createDir(fs::FS &fs, const char *path) {
Serial.printf("Creating Dir: %s\n", path);
if (fs.mkdir(path)) {
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}

void removeDir(fs::FS &fs, const char *path) {
Serial.printf("Removing Dir: %s\n", path);
if (fs.rmdir(path)) {
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}

void readFile(fs::FS &fs, const char *path) {
Serial.printf("Reading file: %s\n", path);

File file = fs.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}

Serial.print("Read from file: ");
while (file.available()) {
Serial.write(file.read());
}
}

void writeFile(fs::FS &fs, const char *path, const char *message) {
Serial.printf("Writing file: %s\n", path);

File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
}

void appendFile(fs::FS &fs, const char *path, const char *message) {
Serial.printf("Appending to file: %s\n", path);

File file = fs.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
}

void renameFile(fs::FS &fs, const char *path1, const char *path2) {
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}

void deleteFile(fs::FS &fs, const char *path) {
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path)) {
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}

void testFileIO(fs::FS &fs, const char *path) {
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if (file) {
len = file.size();
size_t flen = len;
start = millis();
while (len) {
size_t toRead = len;
if (toRead > 512) {
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %lu ms\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}

file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}

size_t i;
start = millis();
for (i = 0; i < 2048; i++) {
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %lu ms\n", 2048 * 512, end);
file.close();
}

void setup() {
Serial.begin(115200);
delay(3000);
if (!SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
Serial.println("Pin change failed!");
return;
}
if (!SD_MMC.begin()) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();

if (cardType == CARD_NONE) {
Serial.println("No SD_MMC card attached");
return;
}

Serial.print("SD_MMC 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_MMC Card Size: %lluMB\n", cardSize);

listDir(SD_MMC, "/", 0);
createDir(SD_MMC, "/mydir");
listDir(SD_MMC, "/", 0);
removeDir(SD_MMC, "/mydir");
listDir(SD_MMC, "/", 2);
writeFile(SD_MMC, "/hello.txt", "Hello ");
appendFile(SD_MMC, "/hello.txt", "World!\n");
readFile(SD_MMC, "/hello.txt");
deleteFile(SD_MMC, "/foo.txt");
renameFile(SD_MMC, "/hello.txt", "/foo.txt");
readFile(SD_MMC, "/foo.txt");
testFileIO(SD_MMC, "/test.txt");
Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
}

void loop() {
delay(10);
}

代码解释

  • SD 卡初始化 :

    if (!SD_MMC.setPins(clk, cmd, d0, d1, d2, d3)) {
    Serial.println("Pin change failed!");
    return;
    }
    if (!SD_MMC.begin()) {
    Serial.println("Card Mount Failed");
    return;
    }

运行效果

  • 屏幕无现象
  • 打开串口监视器

08_lvgl_example_v8

本示例演示了使用 ESP32-C6-LCD-0.85 运行 lvgl(v8.4.0)示例程序。

  • 需要安装 lvgl v8.4.0 版本,如已安装其他版本,请重新安装。

运行效果

  • 屏幕显示

09_lvgl_example_v9

本示例演示了使用 ESP32-C6-LCD-0.85 运行 lvgl(v9.3.0)示例程序。

  • 需要安装 lvgl v9.3.0 版本,如已安装其他版本,请重新安装。

运行效果

  • 屏幕显示