ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ESP8266/ESP32驱动MAX7219多屏显示实战:级联、滚动与优化

ESP8266/ESP32驱动MAX7219多屏显示实战:级联、滚动与优化 1. 项目缘起与整体设计思路1.1 为什么要在 ESP8266/ESP32 上折腾多屏显示手头攒了一堆 MAX7219 的 8x8 LED 点阵模块单个 8x8 能显示的东西实在有限——一个字母、一个数字、顶多一个简单图标。但如果你把四块、八块甚至更多块级联起来就能拼出一块足够大的“信息看板”滚动显示文字、温湿度、时间、传感器数据甚至做个简易的频谱显示器。Tobers Multidisplay 这个项目就是冲着这个需求去的在 ESP8266 和 ESP32 这两块最普及的物联网开发板上用 Arduino IDE 驱动多块 MAX7219 点阵实现灵活的多屏显示。这个项目的核心价值在于“多”和“兼容”。多指的是支持任意数量 MAX7219 模块级联屏幕宽度可以按需扩展兼容指的是同一套代码逻辑能跑在 ESP8266 和 ESP32 两个平台上不用为每块板子重写驱动。适合谁呢如果你刚接触 Arduino 和 LED 点阵想从点亮一个 8x8 开始逐步扩展到多屏滚动显示这个项目能给你一条清晰的路径。如果你已经玩过单屏想把手头的模块串起来做点实用的东西比如桌面天气站、车间产量看板、自习室倒计时器那这套多屏方案直接就能用。我最初做这个是因为家里有个鱼缸想实时显示水温和室温单块 8x8 只能轮流显示两个数字看着太累。后来把四块屏拼成 32x8 的长条一行显示“水温 26.3C”另一行滚动显示时间这才算能用。从那以后就顺手把代码整理成了兼容 ESP8266 和 ESP32 的版本也就是这个项目的雏形。1.2 硬件选型背后的取舍逻辑选 MAX7219 而不是 74HC595 或者 WS2812理由很直接。74HC595 需要自己处理扫描刷新代码复杂且占用 CPUWS2812 虽然单线控制方便但每个灯珠独立寻址做点阵文字显示时数据量巨大刷新率上不去。MAX7219 是专门的 LED 驱动芯片内部自带扫描电路和亮度调节单片机只需要通过 SPI 接口把显示数据丢给它就行CPU 占用极低。而且 MAX7219 模块通常做成 8x8 点阵加驱动芯片的一体板背面有输入输出排针级联就是简单的插线操作。ESP8266 和 ESP32 的选择则取决于你的具体需求。ESP8266 便宜、够用单核 80MHz可超频到 160MHz驱动四到八块 MAX7219 毫无压力。ESP32 双核 240MHz内存更大蓝牙和 WiFi 可以同时用适合需要联网获取数据同时还要驱动多屏的场景。我实测下来ESP8266 驱动八块屏滚动显示帧率能稳定在 30fps 以上ESP32 驱动十六块屏也毫无卡顿。如果你只是做本地显示ESP8266 完全足够如果要接云端数据或者做 Web 配置界面直接上 ESP32 更省心。注意MAX7219 模块的工作电压是 5V而 ESP8266/ESP32 的 GPIO 是 3.3V 电平。直接连接时MAX7219 能识别 3.3V 的高电平但为了稳定建议在 DIN、CLK、CS 三条线上各串一个 100Ω 到 220Ω 的电阻或者用 74HCT245 做电平转换。我试过直接连短距离没问题但线长超过 20cm 后偶尔会出现花屏串电阻后就没再出现过。1.3 软件架构一套代码兼容两个平台Tobers Multidisplay 的软件架构分三层底层是 SPI 通信和 MAX7219 寄存器操作中间层是帧缓冲和显示刷新上层是文字滚动和图形绘制。底层用条件编译区分 ESP8266 和 ESP32 的 SPI 库调用——ESP8266 用SPI库ESP32 用SPIClass但引脚定义和初始化流程基本一致。中间层维护一个二维数组作为显存所有绘制操作先写到显存再统一刷新到 MAX7219避免闪烁。上层提供scrollText()、drawBitmap()、setBrightness()等接口调用者不需要关心底层是几块屏、什么平台。这种分层设计的好处是当你从 ESP8266 换到 ESP32 时只需要改一下#define的平台宏和引脚号上层业务代码一行不用动。我试过把同一个温湿度显示程序从 NodeMCU 搬到 ESP32 DevKit只改了三个引脚定义编译烧录直接跑通。另外帧缓冲的大小是根据屏幕数量动态计算的比如四块屏就是 32x8 字节八块屏就是 64x8 字节ESP8266 的 80KB 内存完全放得下。2. 核心细节解析与实操要点2.1 MAX7219 级联的硬件连接与注意事项MAX7219 模块级联的接线逻辑是第一块的 DOUT 接第二块的 DIN第二块的 DOUT 接第三块的 DIN以此类推。CLK 和 CS 所有模块并联由单片机统一控制。电源方面每块 MAX7219 模块满亮度全亮时电流大约 150mA 到 200mA四块就是 600mA 到 800mA。如果你用 ESP8266 的板载 3.3V 稳压器给 MAX7219 供电大概率会烧掉稳压器或者导致复位。正确的做法是MAX7219 的 VCC 和 GND 直接接到独立的 5V 电源单片机的 5V 引脚只用来给逻辑电平参考或者干脆不接。我踩过的坑一开始用 NodeMCU 的 VIN 引脚给四块 MAX7219 供电结果 WiFi 一连接就重启串口打印“reset reason: power-on”。后来用万用表一量VIN 电压在 WiFi 发射瞬间从 5V 掉到 3.8VMAX7219 直接复位。换了个 5V 2A 的独立电源后问题消失。所以记住一条LED 点阵的电源必须独立不要从开发板取电。引脚连接方面ESP8266 的硬件 SPI 引脚是 GPIO12MISO、GPIO13MOSI、GPIO14CLK、GPIO15CS。但 MAX7219 只需要 MOSI 和 CLKCS 可以用任意 GPIO。我通常用 GPIO15 作为 CSGPIO13 作为 DINGPIO14 作为 CLK。ESP32 的默认 SPI 引脚是 GPIO23MOSI、GPIO18CLK、GPIO5CS但 ESP32 的 GPIO 矩阵允许任意映射所以你也可以用其他引脚。不过为了代码兼容性我建议在 ESP32 上也用 GPIO13、GPIO14、GPIO15 这组这样同一份引脚定义两个平台都能用。信号ESP8266 引脚ESP32 引脚MAX7219 引脚DINGPIO13GPIO13DINCLKGPIO14GPIO14CLKCSGPIO15GPIO15CSVCC外部 5V外部 5VVCCGND共地共地GND提示ESP8266 的 GPIO15 在启动时必须为低电平否则会进入错误的启动模式。MAX7219 的 CS 引脚内部有上拉所以直接连接没问题。但如果你外接了其他上拉电阻记得在启动时确保 GPIO15 被拉低。2.2 帧缓冲与刷新机制的设计考量帧缓冲是一个二维字节数组每个字节对应 MAX7219 的一行 8 个像素。比如四块屏级联总宽度 32 列高度 8 行帧缓冲就是byte frame[8][4]每个元素代表某块屏的某一行。绘制文字时先通过字库把字符转换成点阵数据再按列偏移写入帧缓冲。刷新时遍历每一块屏通过 SPI 把对应的 8 个字节发送到 MAX7219 的 8 个行寄存器。为什么不用 MAX7219 的自动扫描因为自动扫描需要你持续发送数据而 MAX7219 内部有显存你只需要在数据变化时更新即可。但滚动显示时数据每帧都在变所以还是得每帧刷新。刷新频率我一般设在 50Hz 到 100Hz也就是每 10ms 到 20ms 刷新一次。ESP8266 的 SPI 时钟可以跑到 40MHz发送 32 字节四块屏只需要 6.4 微秒完全不会成为瓶颈。这里有个细节MAX7219 的寄存器地址从 0x01 到 0x08 对应第 1 到第 8 行0x0C 是关机模式0x0F 是显示测试。初始化时需要依次写入关机模式 0x00正常操作、解码模式 0x00不解码直接点阵、扫描限制 0x07扫描 8 行、亮度 0x00 到 0x0F、显示测试 0x00关闭。这些寄存器的值会通过 DOUT 传递给下一块屏所以级联时只需要对第一块屏发送初始化命令后面的屏会自动接收。我实测发现如果初始化时亮度设得太高比如 0x0F四块屏全亮时电流会超过 1A电源纹波明显增大ESP8266 的 WiFi 会断流。后来我把亮度降到 0x03电流降到 400mA 左右稳定性大幅提升。所以亮度不要一上来就拉满根据电源能力逐步调整。2.3 字库与滚动算法的实现细节字库我用的是经典的 5x7 点阵字体每个字符占 5 列行高 7加上 1 列间隔总共 6 列。这样在 8 行高的屏幕上上下各留 1 行空白看起来比较舒服。字库数据存在 PROGMEM 里ESP8266 和 ESP32 都支持PROGMEM关键字把字库放在 Flash 里而不是 RAM 里节省宝贵的内存。一个完整的 ASCII 字库大约 1KB 左右对 Flash 容量来说微不足道。滚动算法的核心是维护一个“虚拟画布”宽度等于屏幕宽度加上文字总宽度。每帧把画布向左移动一列然后把可见部分拷贝到帧缓冲。具体实现时我用一个int scrollPos变量记录当前滚动偏移绘制文字时从scrollPos开始逐列写入帧缓冲。当scrollPos超过文字总宽度时重置为屏幕宽度形成循环滚动。这里有个性能优化点不要每帧都重新解析字库。我一开始每帧都调用drawChar()把字符转换成点阵结果 ESP8266 的 CPU 占用率飙到 70%滚动明显卡顿。后来改成先把整条文字渲染到一个大缓冲区滚动时只做内存拷贝CPU 占用率降到 15% 以下。这个优化对于多屏场景尤其重要因为屏幕越宽每帧需要处理的数据量越大。注意ESP8266 的PROGMEM读取需要用到pgm_read_byte()函数不能直接解引用指针。ESP32 虽然也支持PROGMEM但它的 Flash 可以直接寻址所以pgm_read_byte()在 ESP32 上只是普通的内存读取。为了代码兼容统一用pgm_read_byte()即可。3. 实操过程与核心环节实现3.1 开发环境搭建与库安装Arduino IDE 的安装就不赘述了官网下载即可。关键是开发板支持包的安装。ESP8266 的支持包地址是http://arduino.esp8266.com/stable/package_esp8266com_index.jsonESP32 的支持包地址是https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json。在“首选项”的“附加开发板管理器网址”里填入这两个地址然后在“开发板管理器”里搜索安装即可。我建议 ESP8266 用 3.0.2 版本ESP32 用 2.0.11 版本这两个版本我实测最稳定。库方面Tobers Multidisplay 不依赖外部库所有代码都是自包含的。但如果你要用 WiFi 获取网络时间ESP8266 需要NTPClient库ESP32 可以用内置的configTime()函数。安装NTPClient时注意选NTPClient by Fabrice Weinberg不要选成其他同名库。另外如果你要用 DHT 温湿度传感器需要安装DHT sensor library by Adafruit这个库在 ESP8266 和 ESP32 上都能用。烧录设置方面ESP8266 的 NodeMCU 板子选“NodeMCU 1.0 (ESP-12E Module)”Flash Size 选“4MB (FS:2MB OTA:~1019KB)”CPU Frequency 选“160MHz”。ESP32 的 DevKit 选“ESP32 Dev Module”Flash Size 选“4MB”Partition Scheme 选“Default 4MB with spiffs”。上传速度 ESP8266 用 921600ESP32 用 921600 或 460800 都行。如果遇到a fatal esptool.py error occurred: failed to connect to esp8266: timed out先检查 USB 线是不是只能供电不能传数据再检查驱动有没有装好最后按住 FLASH 键再点上传。3.2 多屏初始化的完整代码实现下面这段代码是初始化的核心部分兼容 ESP8266 和 ESP32。先定义平台宏和引脚然后实现 SPI 发送函数和 MAX7219 寄存器写入函数。#if defined(ESP8266) #include SPI.h #define DIN_PIN 13 #define CLK_PIN 14 #define CS_PIN 15 #elif defined(ESP32) #include SPI.h #define DIN_PIN 13 #define CLK_PIN 14 #define CS_PIN 15 #endif #define NUM_DEVICES 4 // 级联的 MAX7219 模块数量 void maxTransfer(uint8_t dev, uint8_t reg, uint8_t data) { digitalWrite(CS_PIN, LOW); // 发送到目标设备之前的所有设备地址自动递减 for (uint8_t i 0; i NUM_DEVICES; i) { if (i dev) { SPI.transfer(reg); SPI.transfer(data); } else { SPI.transfer(0x00); // 空操作 SPI.transfer(0x00); } } digitalWrite(CS_PIN, HIGH); } void maxInit() { pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV16); // 约 5MHz稳定可靠 for (uint8_t d 0; d NUM_DEVICES; d) { maxTransfer(d, 0x0C, 0x00); // 正常操作 maxTransfer(d, 0x0F, 0x00); // 关闭显示测试 maxTransfer(d, 0x09, 0x00); // 不解码 maxTransfer(d, 0x0A, 0x03); // 亮度 3/15 maxTransfer(d, 0x0B, 0x07); // 扫描 8 行 } for (uint8_t d 0; d NUM_DEVICES; d) { for (uint8_t r 1; r 8; r) { maxTransfer(d, r, 0x00); // 清空显存 } } }这段代码的关键在于maxTransfer函数。MAX7219 的级联数据是“穿透式”的你发送的数据会从第一块传到第二块再传到第三块。所以如果你只想更新第三块屏的某一行需要先发送两个空操作对应第一块和第二块再发送目标寄存器和数据。maxTransfer里的循环就是干这个的遍历所有设备只有目标设备发送真实数据其他设备发送 0x00。提示SPI.setClockDivider(SPI_CLOCK_DIV16)在 ESP8266 上对应 5MHz在 ESP32 上需要用SPI.setFrequency(5000000)。为了代码兼容我通常用条件编译分别处理。实测 5MHz 下即使杜邦线长 30cm显示也很稳定。如果你追求更高刷新率可以提到 10MHz但线长要控制在 15cm 以内。3.3 滚动文字显示的完整流程滚动显示的核心是维护一个帧缓冲和滚动偏移。下面以显示“Hello”为例说明从文字到屏幕的完整流程。第一步把“Hello”渲染到临时缓冲区。每个字符 5 列加上 1 列间隔5 个字符共 30 列。缓冲区宽度设为 30高度 8。用字库逐列写入比如字符 H 的点阵数据是{0x7F, 0x08, 0x08, 0x08, 0x7F}表示第 1 列全亮第 2 到 4 列只有中间一行亮第 5 列全亮。第二步把临时缓冲区拷贝到帧缓冲。帧缓冲宽度是NUM_DEVICES * 8比如四块屏就是 32 列。如果文字宽度 30 小于 32直接居中显示如果大于 32就需要滚动。滚动时每帧把帧缓冲左移一列从临时缓冲区取下一列填入最右侧。第三步刷新到 MAX7219。遍历每一块屏把帧缓冲中对应的 8 列数据发送到该屏的 8 个行寄存器。比如第一块屏对应帧缓冲的第 0 到 7 列第二块对应第 8 到 15 列以此类推。uint8_t frame[8][NUM_DEVICES]; // 帧缓冲 int scrollPos 0; void renderText(const char* text) { // 把文字渲染到临时缓冲区 int len strlen(text); int bufWidth len * 6; uint8_t buf[8][bufWidth]; memset(buf, 0, sizeof(buf)); for (int i 0; i len; i) { drawChar(buf, i * 6, text[i]); } // 滚动拷贝到帧缓冲 for (int x 0; x NUM_DEVICES * 8; x) { int srcX scrollPos x; for (int y 0; y 8; y) { if (srcX bufWidth) { frame[y][x / 8] | (buf[y][srcX] (x % 8)); } else { frame[y][x / 8] ~(1 (x % 8)); } } } scrollPos; if (scrollPos bufWidth) scrollPos 0; // 刷新到 MAX7219 for (uint8_t d 0; d NUM_DEVICES; d) { for (uint8_t r 0; r 8; r) { maxTransfer(d, r 1, frame[r][d]); } } }这段代码里有个位操作技巧frame[y][x / 8] | (buf[y][srcX] (x % 8))。因为帧缓冲是按字节存储的每个字节对应 8 列所以需要把列数据移位到正确的位位置。这个操作在 ESP8266 和 ESP32 上都是单周期指令速度很快。我实测下来四块屏滚动 20 个字符帧率能稳定在 60fps 以上。如果你觉得滚动太快可以在每帧之间加delay(30)到delay(50)。但注意不要用delay()阻塞太久否则 WiFi 或蓝牙的响应会变慢。更好的做法是用millis()做非阻塞定时。3.4 联网获取时间与温湿度数据的集成如果你想让屏幕显示网络时间ESP8266 可以用NTPClient库ESP32 用configTime()。以 ESP8266 为例先连接 WiFi然后初始化 NTP 客户端每 60 秒更新一次时间。显示时把小时和分钟格式化成字符串传给renderText()。#include NTPClient.h #include WiFiUdp.h WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, pool.ntp.org, 8 * 3600, 60000); void setup() { WiFi.begin(SSID, PASSWORD); while (WiFi.status() ! WL_CONNECTED) delay(500); timeClient.begin(); } void loop() { timeClient.update(); char timeStr[6]; sprintf(timeStr, %02d:%02d, timeClient.getHours(), timeClient.getMinutes()); renderText(timeStr); delay(50); }温湿度传感器我用的是 DHT22接在 GPIO4 上。ESP8266 和 ESP32 都可以用 Adafruit 的 DHT 库。注意 DHT22 的读取间隔不能小于 2 秒否则数据会出错。我通常每 5 秒读一次把温度和湿度拼成字符串滚动显示。注意ESP8266 在 WiFi 工作时GPIO4 和 GPIO5 会有 PWM 信号干扰如果 DHT22 接在这两个引脚上读数会偶尔失败。建议接在 GPIO12 或 GPIO13 上。ESP32 的 GPIO 没有这个问题任意引脚都可以。4. 常见问题与排查技巧实录4.1 显示花屏、闪烁、部分模块不亮花屏是最常见的问题通常有三个原因。第一是电源功率不足四块 MAX7219 全亮时电流接近 800mA如果电源只有 500mA电压会跌落导致数据错乱。解决办法是换 5V 2A 以上的电源并在每块模块的 VCC 和 GND 之间并一个 100μF 电解电容。第二是 SPI 时钟太快杜邦线太长导致信号反射。把SPI.setClockDivider从SPI_CLOCK_DIV2改成SPI_CLOCK_DIV16或者缩短线长到 15cm 以内。第三是 CS 引脚没有正确拉低检查digitalWrite(CS_PIN, LOW)是否在SPI.transfer之前执行。部分模块不亮先检查级联线序。MAX7219 模块的输入输出方向是固定的DIN 是输入DOUT 是输出。如果你把第一块的 DOUT 接到了第二块的 DOUT数据就传不过去。正确的接法是第一块 DOUT 接第二块 DIN。另外检查NUM_DEVICES是否和实际模块数量一致如果设多了多出来的空操作会占用时间如果设少了后面的模块收不到数据。闪烁问题通常是刷新频率太低或者帧缓冲没有清空。我一开始每帧只更新变化的列结果旧数据残留导致闪烁。后来改成每帧先memset(frame, 0, sizeof(frame))清空再重新绘制闪烁就消失了。代价是 CPU 占用率略高但 ESP8266 完全扛得住。4.2 编译报错与烧录失败速查问题现象可能原因解决方法a fatal esptool.py error occurred: failed to connect to esp8266: timed out驱动未装、USB 线仅供电、GPIO0 未拉低装 CH340 或 CP2102 驱动换数据线按住 FLASH 再上传error: SPI was not declared in this scope未包含 SPI.h 或平台宏错误确认#include SPI.h在文件顶部检查#if defined(ESP8266)拼写Sketch too bigFlash 分区不够在开发板设置里选 4MB 分区或优化字库大小invalid conversion from const char* to char*字符串常量传给非 const 参数把函数参数改成const char*上传后串口无输出波特率不匹配检查Serial.begin(115200)和串口监视器波特率是否一致ESP32 烧录时如果遇到Failed to connect to ESP32: Timed out waiting for packet header按住 BOOT 键再点上传看到Connecting...后松开。ESP32 的自动复位电路有时不太可靠手动按键最稳。另外ESP32 的 GPIO12 在启动时不能为高否则会进入错误的 Flash 电压模式。如果你把 MAX7219 的 DIN 接在 GPIO12 上启动时可能失败。建议避开 GPIO12用 GPIO13。4.3 多屏扩展时的内存与性能优化当你把屏幕从四块扩展到八块甚至十六块时帧缓冲会线性增长。八块屏的帧缓冲是8 x 8 64字节十六块是8 x 16 128字节对 ESP8266 的 80KB RAM 来说微不足道。但滚动时的临时缓冲区会更大比如滚动 100 个字符临时缓冲区是8 x 600 4800字节这就有点吃紧了。解决办法是分段渲染每次只渲染屏幕宽度加 6 列的字符滚动到边界时再加载下一段。这样临时缓冲区只需要8 x (屏幕宽度 6)字节四块屏就是8 x 38 304字节非常省内存。性能方面ESP8266 的 SPI 发送 128 字节十六块屏需要约 25 微秒加上帧缓冲拷贝和字库解析每帧总耗时约 2ms理论上能跑 500fps。但实际受限于 WiFi 和传感器读取我通常把刷新率控制在 50fps 左右留出 CPU 时间给其他任务。如果你发现滚动卡顿先检查是不是在loop()里用了delay()改成millis()非阻塞定时后流畅度会明显提升。提示ESP32 双核的优势在这里体现得很明显。你可以把屏幕刷新放在核心 0WiFi 和传感器读取放在核心 1用xTaskCreatePinnedToCore()创建任务。这样即使 WiFi 正在传输大量数据屏幕滚动也不会卡。ESP8266 是单核只能靠非阻塞编程来兼顾但实测四块屏以内完全没问题。4.4 独家避坑经验与实操心得第一个坑MAX7219 模块的 PCB 质量参差不齐。我买过一批便宜模块级联时第三块总是随机花屏。后来发现是模块背面的排针焊接不良DOUT 信号时断时续。重新补焊后问题消失。所以如果你遇到莫名其妙的显示问题先拿万用表蜂鸣档测一下排针的通断。第二个坑ESP8266 的 GPIO15 在启动时必须为低但 MAX7219 的 CS 引脚内部有上拉。如果你直接把 GPIO15 接到 CS启动时 GPIO15 被上拉到高电平ESP8266 会进入 SDIO 启动模式表现为串口无输出。解决办法是在 GPIO15 和 GND 之间接一个 10kΩ 下拉电阻确保启动时为低。我一开始不知道这个折腾了一晚上以为板子坏了。第三个坑字库的PROGMEM读取。ESP8266 的pgm_read_byte()返回的是uint8_t但如果你把字库定义成const uint8_t font[] PROGMEM在某些版本的 Arduino 核心上会报错。正确的写法是const uint8_t font[] PROGMEM {...}注意PROGMEM的位置。ESP32 对PROGMEM的兼容性更好但为了统一我建议两个平台都用相同的写法。第四个坑WiFi 和 MAX7219 的电源干扰。ESP8266 在 WiFi 发射瞬间电流会突增到 300mA如果 MAX7219 和 ESP8266 共用电源电压跌落会导致 MAX7219 复位。我试过在 ESP8266 的 VCC 和 GND 之间并一个 470μF 电容情况有所改善但最彻底的方案还是独立供电。如果你非要用一个电源至少用 5V 3A 的并且给 ESP8266 单独加 LC 滤波。第五个坑滚动速度的调节。delay()是最简单的调速方式但会阻塞 WiFi。更好的做法是用millis()计算时间差只有超过设定间隔才刷新一帧。比如if (millis() - lastScroll 30) { scrollPos; lastScroll millis(); }。这样即使 WiFi 正在处理数据滚动也不会卡顿只是帧率会动态调整。5. 项目扩展与进阶玩法5.1 从单色点阵到多色 RGB 点阵的升级路径MAX7219 驱动的是单色 LED如果你想要彩色显示可以换成 WS2812 点阵或者 RGB LED 矩阵。但 WS2812 的刷新需要大量数据ESP8266 驱动 16x16 的 WS2812 矩阵时每帧需要发送 768 字节刷新率会降到 30fps 以下。ESP32 的 RMT 外设可以硬件驱动 WS2812不占用 CPU是更好的选择。如果你坚持用 ESP8266建议把矩阵控制在 8x8 以内或者用 APA102 这种带独立时钟的灯带SPI 接口驱动起来更轻松。5.2 用 Web 界面远程配置显示内容ESP8266 和 ESP32 都可以做 Web 服务器。你可以做一个简单的网页输入要显示的文字、滚动速度、亮度通过 HTTP 请求发送给开发板。ESP8266 用ESP8266WebServer库ESP32 用WebServer库API 基本一致。我试过在 ESP32 上跑 Web 服务器同时驱动八块 MAX7219响应速度很快网页提交后屏幕立即更新。注意 Web 服务器的回调函数里不要做耗时操作把显示更新放到loop()里处理。5.3 多屏显示在物联网场景中的实际应用我目前把四块 MAX7219 装在一个 3D 打印的壳子里放在书桌上显示内容分三部分第一行滚动显示天气和室温第二行显示当前时间第三行显示待办事项数量。数据通过 MQTT 从家里的服务器推送过来。ESP8266 每 10 秒从 MQTT 订阅一次数据更新到屏幕。整个系统跑了半年多除了偶尔因为路由器重启需要重连 WiFi没有出过其他问题。如果你也想做类似的东西建议从显示固定文字开始逐步加入联网功能每加一个功能就测试稳定性不要一次性全加上去。这个项目后续还可以扩展成多块 ESP8266 通过 WiFi 同步显示比如客厅一块、卧室一块显示同样的内容。或者加入按钮手动切换显示模式。MAX7219 的级联数量理论上没有上限只要你电源够、内存够拼一面 LED 墙也不是不可能。
返回列表