MultiLCD库:Arduino多款液晶屏统一驱动的实战指南
发布时间:2026/9/2 5:39:09来源:尧图网络
简介这款 Arduino 液晶库由 Stanley 编写并以 GPL 协议开源面向 Arduino 开发者、电子爱好者及创客。它提供统一、易用的 API 驱动不同型号的液晶显示模块可显示字符、位图与简单图形能显著降低多屏适配与切换成本适合需要同时维护多种屏幕或快速验证显示效果的项目。包体共 44 个文件、76KB以 h 头文件和 cpp 驱动实现为主另有 ino 示例和 cbp 工程文件整体目录结构清晰便于在 Arduino IDE 中直接加载并对照学习。资源涵盖 SSD1306、PCD8544、ILI9341、ILI9325D、SSD1289 等常见屏驱源码并附 MicroLCD、UTFT、RGBMatrix 等硬件层实现读者可获得驱动移植、初始化配置、字体与图形绘制以及不同驱动芯片的时序适配与内存配置细节等完整参考。目前已有 2036 人学习下载对需要快速集成多种液晶模块或深入了解 Arduino 显示底层逻辑的开发者是一份实用的开源参考资料。 做 Arduino 项目的时候最让我头疼的其实不是传感器而是屏幕。屏幕型号多、接口杂、不同厂商的库调用方式还不一样今天用 LiquidCrystal 写 1602明天换一块 TFT 就得重新学另外一套 API改到后面整个人都不想碰显示部分。后来我接触了 MultiLCD 这个 Arduino 液晶库它把 1602 字符屏、5110 点阵屏、ST7789/ILI9341 的 TFT、SSD1306 的 OLED 这些常见的液晶屏和模块收敛成一套调用接口。你只需要把屏幕对应的类名和构造参数换掉初始化、清屏、光标、打印这些逻辑几乎不用动。这篇文章就把我实际用这个库踩过的坑和完整的用法记录下来给同样被屏幕搞疯的人一个能直接抄作业的参考。1. 项目背景与库的整体设计思路1.1 为什么需要“一个库管多种屏幕”过去我做小型仪表盘一开始用 1602后来嫌显示信息太少换成 5110 点阵屏。本来以为只是“多接几根线”的事情结果发现两个库的架构差别极大1602 的lcd.print(hello)和 5110 的display.print(hello)虽然长得像但背后的坐标系、字库、取模方式完全不一样。再往后换 ST7789 的 1.8 寸 TFT又要引入 Adafruit_GFX 一整套依赖。项目里同时出现三套屏幕驱动光是维护#include和条件编译就够烦了。MultiLCD 这个库的设计思路正好撞在我的需求上它把所有屏幕差别封装到底层驱动对外暴露的是一套“普适接口”。你上层代码只需要知道自己要“打印一行字”“画一条线”“清个屏”至于底层是字符屏还是图形屏是 SPI 还是 I2C都无所谓。这样带来的最大直接好处是想换屏的时候可以少改甚至不改业务逻辑改动集中在屏幕对象的构造和接线定义。1.2 库的架构是怎么组织的MultiLCD 的典型结构是一个公共基类定义操作接口各种具体屏幕驱动程序继承并实现这套接口。比如公共基类会提供begin()、clear()、setCursor(x, y)、print()、home()这些基础方法字符屏和图形屏再各自实现。用我实际调用过的几个类举例LCD_1602/LCD_2004对应 HD44780 字符屏支持 4 位并行或通过 I2C 转接板。LCD_5110对应 PCD8544Nokia 5110 屏幕那种点阵屏。LCD_TFT对应 ST7735、ST7789、ILI9341 这类 SPI TFT 屏。LCD_OLED对应 SSD1306、SH1106 这类常见 OLED 屏。这种结构让“换屏幕”变成一件特别直观的事。我在同一个项目里测试过 1602 和 TFT 两个版本上层打印逻辑并没有重写只是把LCD_1602 lcd;换成了LCD_TFT lcd;然后把begin()的引脚参数和setCursor()的坐标含义对齐就完成了替换。1.3 主要支持的屏型与实际使用场景我用的时间不算长但几个常用型号都试过一遍整理了一个简单对照表方便你判断手上的屏幕能不能用这个库。屏幕模块/芯片类型通信接口典型分辨率库中对应类HD447801602/2004字符并行4/8位或I2C转接16列2行 / 20列4行LCD_1602 / LCD_2004PCD8544Nokia 5110点阵图形SPI兼容84×48LCD_5110ST7735TFTSPI128×160常见1.8寸LCD_TFTST7789TFTSPI240×240 / 240×320常见1.3/1.54寸LCD_TFTILI9341TFTSPI/8080并行240×320常见2.8/3.5寸LCD_TFTSSD1306 / SH1106OLEDI2C/SPI128×64 / 128×32常见0.96寸LCD_OLED从应用场景看1602 适合做最简单的状态显示OLED 适合低功耗嵌入式设备5110 适合性价比点阵应用TFT 则适合要做复杂界面、小图标的项目。一台 Arduino 板子配一块小 TFT再配合 MultiLCD 库基本能覆盖大部分桌面级项目的显示需求。2. 安装、接线与初始化2.1 把库装进 Arduino IDE安装步没什么特别的有两种方式任选其一。第一种直接下载 ZIP 压缩包然后在 Arduino IDE 里选“项目 - 加载库 - 添加 .ZIP 库”选中下载好的MultiLCD...zip文件IDE 会自动解压并注册。第二种在“库管理器”里搜索 MultiLCD如果作者上传过官方版本可以直接搜索安装后续更新也方便。装完之后建议先跑一个库自带的示例不要一上来就写自己的脚本。我之前跳过这一步直接在业务代码里引用结果连最基本的方法名对不对都没验证后面排查了半天才发现是调用方式和库版本不一致。2.2 接线先分清接口类型别想当然MultiLCD 库里不同屏幕的接线逻辑差异很大最忌讳拿 1602 的引脚定义去套 TFT。先看模块的接口类型再对照引脚接线。对于并行 1602常见的接法是RS、E 接到 Arduino 数字口。D4~D7 接到四个数字口。如果用了 PCF8574 I2C 转接板就只剩 VCC、GND、SDA、SCL 四根线。第三个引脚 V0对比度一般要接一个 10K 电位器否则直接接地可能显示不出内容。对于 SPI 接口的 TFT 和 5110引脚通常是 SCLK、MOSI、CS/CE、DC、RST可能还要加一个背光 BL 引脚。ST7735/ST7789 这类屏在 Arduino Uno 上可以直接复用硬件 SPI 的 SCK 和 MOSI 引脚CS、DC、RST 这三个控制脚随意指定数字口就行。2.3 初始化参数不同屏的“打开方式”每个屏的初始化方法都会有一些自己的参数但 MultiLCD 把它们尽量统一了。比如字符屏的初始化是LCD_1602 lcd; // 声明对象 lcd.begin(12, 11, 5, 4, 3, 2); // RS, E, D4, D5, D6, D7TFT 屏的初始化可能变成LCD_TFT lcd(10, 9, 8); // CS, DC, RST lcd.begin();begin()里做的事情包括端口初始化、内部延时等待液晶控制器复位、发送初始化命令序列。所以如果你发现屏幕不显示先检查begin()是否被调用这是最简单也是最容易忽视的问题。有一个经验尽量把屏幕对象定义放在全局区不要在setup()里用局部对象。因为局部对象在setup()结束后可能被释放或者内存布局发生变化某些平台上会出现“开机正常几秒后花屏”的诡异现象。3. 统一 API 实战一套代码切换多种液晶屏3.1 字符型 LCD 的经典写法字符屏的 API 最直观先看一个完整的 1602 示例。#include MultiLCD.h LCD_1602 lcd; void setup() { lcd.begin(12, 11, 5, 4, 3, 2); // RS, E, D4, D5, D6, D7 lcd.setCursor(0, 0); lcd.print(MultiLCD Demo); lcd.setCursor(0, 1); lcd.print(Hello, Maker!); } void loop() { }setCursor()在字符屏里的两个参数是“列”和“行”第一行第一列是(0, 0)最多到(15, 1)。这个坐标语义和图形屏是不一样的后面切 TFT 时要特别注意。如果你想显示动态内容比如温湿度传感器的值可以用sprintf先把数值拼成字符串再交给print()输出这样能避免print各种重载方法在字符屏上产生的显示混乱。3.2 LCD_TFT 的绘制调用TFT 屏的 API 会更丰富因为要支持画点、画线、填充矩形这些图形操作。我用的 ST7789 屏是 240x240 分辨率示例代码大概长这样#include MultiLCD.h LCD_TFT lcd(10, 9, 8); // CS, DC, RST void setup() { lcd.begin(); lcd.fillScreen(COLOR_RED); lcd.setColor(COLOR_WHITE); lcd.drawLine(0, 0, 239, 239); lcd.drawRect(20, 20, 100, 60); lcd.setCursor(0, 0); lcd.print(TFT OK 240x240); } void loop() { }fillScreen是整个屏幕填充一种颜色setColor设置后续绘制颜色drawLine和drawRect的坐标是像素坐标。这里需要特别说明的是不同屏幕的色值定义可能不同库一般会内置COLOR_WHITE、COLOR_RED这些常量比你自己拼 RGB565 要省心得多。OLED 的用法也类似我手头 0.96 寸 I2C SSD1306 的初始化需要扫描地址一般是0x3C或0x3D然后LCD_OLED lcd(0x3C); lcd.begin();OLED 优点是对比度高、视角大缺点是需要预留 I2C 总线如果总线上还有别的设备记得地址别冲突。3.3 从 1602 换成 TFT到底要改哪些地方切换屏幕时最关心的就是“我到底要改多少代码”。以我的经验这三个地方是逃不掉要动的对象声明LCD_1602 lcd;改成LCD_TFT lcd(10, 9, 8);。初始化begin()的参数从并行引脚变成 SPI 控制引脚。坐标语义字符屏setCursor(0, 1)是第二行第一个字符TFT 的setCursor(0, 1)如果对应像素坐标那就很可能只差了 1 个像素需要改成setCursor(0, 16)这样的值才能让文字出现在左上角。至于print()、clear()这些基本方法MultiLCD 尽量做成了通用接口不用改。不过打印文字时字符屏自带字体TFT 需要内置字库才能输出如果你自定义了字体那么切屏时也要把字库一起换掉这点很容易被新手忽略。4. 常见问题与排查技巧实录4.1 白屏、黑屏、花屏先按优先级排查实际调试屏幕最常见的就是这三个症状我按遇到频率从高到低排个序。第一类是“完全不亮”。先量背光供电再看对比度。1602 的 V0 如果不接电位器可能整个屏幕就是一片白底黑块或者干脆没有任何内容。OLED 如果完全黑大概率是 I2C 地址不对或者 SDA/SCL 接反。第二类是“白屏”。TFT 白屏特别常见。可能原因包括初始化命令序列没发成功、SPI 引脚没接对、CS/DC/RST 三根控制线搞混、屏幕驱动型号选错。比如 ST7789 的初始化命令和 ILI9341 不一样库如果自动识别不了就会白屏。要排查先确认你实际模组用的是哪个主控芯片再在库配置里指定对应型号不要想当然。第三类是“花屏”。TFT 花屏往往和时序有关。接线太长、杜邦线质量差、SPI 速率拉太高都可能导致数据传输出错。我有一块 1.54 寸 TFT刚开始怎么调都是下半屏花后来发现是排线旁边横着一根电源线干扰太严重了把线分开之后问题就没了。4.2 电压和电平那个“AVDD 多少伏”的坑屏幕的供电和逻辑电平问题很多人会忽略等屏烧了才后悔。多数 Arduino 模块是 5V 逻辑但很多小屏尤其是 ST7789 和 SSD1306模块上面的 VCC 或者 VDD 都是 3.3V。如果你的 Arduino 板子是 5V最好确认模块是否自带电平转换。网上很多几十块的小屏模组虽然标注“兼容 5V”但其实是靠板载稳压芯片和电平转换实现的如果是裸屏没有转换电路5V 直接怼上去轻则白屏花屏重则直接冒烟。至于“AVDD 电压多少伏”这个问题经常出现在 TFT 数据手册里。AVDD 是液晶面板内部的模拟电源电压一般不是给用户直接使用的常见值在 5V 到 7V 左右但不同面板差异很大必须查具体驱动芯片的手册。模组化的小屏通常已经用 DC-DC 升压把模块输入电压转换成内部需要的 AVDD你不需要自己去调。库能做的事情只是保证初始化时序正确电源域这种硬件风险只能靠你按模块说明书来。4.3 I2C 地址扫描与引脚冲突I2C 类屏幕最常见的问题是找不到设备。别猜直接写个扫描程序几秒钟就出结果。#include Wire.h void setup() { Wire.begin(); Serial.begin(9600); Serial.println(I2C Scanner); } void loop() { for (byte addr 1; addr 127; addr) { Wire.beginTransmission(addr); if (Wire.endTransmission() 0) { Serial.print(Found I2C device: 0x); Serial.println(addr, HEX); } } delay(1000); }如果扫描不到先检查 SDA/SCL 是否接反再接法参考 Uno 上的 A4/A5 引脚不同板子不一样。如果有多个 I2C 设备还要看地址是否冲突。PCF8574 转接板上一般有 A0/A1/A2 三个跳线可以改地址0x3F、0x27 都是常见默认值。还有一个容易忽略的问题Uno 的 SDA/SCL 和某些 SPI 引脚共用或者和中断引脚冲突。如果同一个引脚既要接屏幕又要接另一个外设初始化顺序不对就会互相干扰。碰到这种情况干脆给屏幕单独分引脚能少很多莫名其妙的 bug。4.4 SPI 接线太长导致花屏的规避如果你的 ST7735/ST7789 接线特别长比如超过 15cm高速 SPI 下数据信号容易出现反射和串扰。最直接的解决办法是把 SPI 时钟降下来。在 MultiLCD 这类库中一般有setSpeed()或者初始化参数里可以指定 SPI 频率改成 4MHz 甚至 2MHz很多花屏问题立刻消失。另外CS 引脚一定要接对并且保持有效电平有些库在初始化期间会把 CS 拉低如果 CS 悬空控制器可能收不到命令。RST 引脚也不能省有些模块上面虽然有复位电路但初始化序列里仍然需要一次硬件复位否则首次开机就是白屏。5. 扩展给 MultiLCD 增加新屏和跨平台移植5.1 底层驱动是怎么组织的如何加一块新屏如果你手头有一块不在支持列表里的屏幕也不用慌MultiLCD 这类库的设计本身就方便扩展。你只需要理解它的顶层抽象一个新屏幕驱动本质上就是实现“清屏、定位、打印、画点”这几件事。画点是最底层的基础操作有了drawPixel(x, y, color)就能组合出画线、画矩形、画圆。新增屏幕时先查阅主控芯片的数据手册把初始化命令序列写对再填上基础接口函数。我写过一个简化的类骨架大概长这样class LCD_MyScreen : public LCD_Base { public: void begin() { // 初始化控制器发送reset和命令序列 } void clear() { // 填充背景色或清空显示RAM } void setCursor(uint8_t x, uint8_t y) { // 设置显示RAM地址 } void print(const char *s) { // 把字符串映射到显示缓存 } };关键不是代码量而是初始化时序。不同液晶控制器的命令字、延时要求、MADCTL 之类寄存器配置都不同直接照抄别的型号大概率翻车。建议先用原厂或分厂商的资料验证单色/单行显示再逐步加入图形接口。5.2 在 ESP32、STM32 上使用时的注意点如果你准备把 MultiLCD 用到非 AVR 平台也就是 ESP32、STM32 这类开发板上有几个点需要提前留意。首先是引脚映射。ESP32 的硬件 SPI 分为 VSPI 和 HSPI默认引脚和 Arduino Uno 完全不同。比如默认 SPI 时钟可能在 GPIO18MOSI 在 GPIO23不同的开发板丝印可能又重新映射过。接线之前先去确认自己板子的引脚图别把 MISO 当 MOSI 用。其次是逻辑电平。ESP32 和 STM32 基本都是 3.3V 逻辑和大多数 3.3V 液晶模块匹配良好。但如果你还在板上插了 5V 外设务必把电源域分离否则逻辑电平不匹配会让屏幕显示颜色不准或闪烁。再就是性能和内存。STM32 的底层 GPIO 操作和 AVR 不一样有些库会为平台做条件编译。如果库本身没有适配你可能要用 HAL 库自己改底层驱动或者在 ESP32 上直接用 Arduino 核心层提供的 SPI API。好在 MultiLCD 封装出来的顶层接口在移植时不用动真正需要改的是每个屏幕驱动里和引脚读写相关的底层代码。还有一个实用建议如果你没有实物又想在动手前快速验证逻辑可以先用 Wokwi 仿真平台模拟一块屏幕。仿真虽然不能完全复现硬件时序细节但能检查引脚接法、代码逻辑这类“人容易犯的错”等逻辑跑通了再上真硬件能省不少调线时间。最后再分享一个我自己的习惯把各种屏幕的接线和初始化参数统一写到一个Display_Config.h文件里每次换屏只改宏定义不用反复翻代码。比如把 1602 的引脚定义、TFT 的 SPI 引脚和型号、OLED 的 I2C 地址都集中管理。这样物理换屏时我只需要把对应宏切换掉然后重新编译验证一遍。MultiLCD 的价值不在于让你少写几行代码而在于它把“不同屏幕之间的差异”隔离在了一个可控位置让你在硬件折腾中能少掉一层无谓的烦恼。本文还有配套的精品资源点击获取
网站建设高端定制企业官网