资讯动态

Arduino与OLED屏幕开发指南:从驱动到实时时钟项目实战

发布时间:2026/8/19 10:24:59 来源:尧图企业网站定制
1. 项目缘起为什么Arduino和OLED是绝配如果你玩过一阵子Arduino手头可能已经堆满了各种传感器和模块从温湿度到超声波从舵机到LED灯带。但很多时候我们缺一个能直接“说话”的窗口。串口监视器当然能用但每次调试都得连着电脑项目做完了也没法独立展示信息。这时候一块小小的OLED显示屏就成了点睛之笔。OLED全称有机发光二极管它和Arduino的组合可以说是创客项目里的“黄金搭档”。我最早用上它是为了给一个环境监测站做个简易的显示面板。当时也考虑过LCD1602但那个蓝底白字的屏幕功耗高、可视角度一般而且显示内容非常有限。而一块0.96英寸的OLED分辨率可以达到128x64这意味着你可以显示好几行文字甚至画点简单的图形和图标功耗还特别低。最关键的是它通常通过I2C或SPI接口通信只需要2根或4根线就能驱动不占太多IO口接线清爽程序库成熟对新手极其友好。从网络上的热度也能看出来“Arduino OLED”是一个经久不衰的搜索组合。大家用它做的项目五花八门有显示日期时间的迷你时钟有展示传感器数据的仪表盘有游戏机上的状态栏还有智能小车上的信息屏。它让项目从“黑盒子”变成了能与人交互的设备成就感直接拉满。今天我就以最常用的I2C接口0.96寸OLED为例把手把手带你从接线、驱动库安装到显示文字、图形和动画最后做一个实用的实时时钟项目把里面的原理、坑点和技巧都讲透。2. 硬件准备与接线避开第一个坑工欲善其事必先利其器。玩转Arduino和OLED第一步就是把硬件连对。别看就几根线这里藏着新手最容易踩的第一个坑。2.1 核心部件选择首先你需要一块Arduino主板。最经典的就是Arduino Uno资源足够兼容性最好本文的示例都将基于Uno。当然你用Arduino Nano、ESP32或者STM32通过Arduino框架也完全没问题核心逻辑是相通的。其次是OLED屏幕。市场上最常见的是0.96英寸和1.3英寸的款式驱动芯片多为SSD1306。我强烈推荐选择I2C接口的版本原因很简单省线。I2C只需要两根信号线SDA, SCL加上电源和地一共4根线。而SPI接口虽然刷新率可能更高但需要4根以上的信号线对于IO口紧张的Uno来说不太划算。你的OLED模块背面通常会有4个或7个引脚。4引脚的一般就是I2C的VCC、GND、SCL、SDA。7引脚的则可能同时支持I2C和SPI需要根据模块上的跳线帽来选择通信模式。注意务必确认你的OLED模块工作电压。大多数模块是3.3V和5V兼容的但仍有部分仅支持3.3V。如果模块上有一个LDO稳压芯片通常是个小黑块一般就是5V兼容的。最稳妥的方法是查看产品说明书或者先用3.3V供电测试。2.2 接线图与原理接线非常简单但顺序和原理值得一说。VCC- Arduino的5V或3.3V引脚根据模块兼容性选择优先试5V。GND- Arduino的GND。SCL- Arduino的A5引脚。这里有个关键点在Arduino Uno上A4和A5引脚在内部被固定为I2C的SDA和SCL。A5对应SCL时钟线。SDA- Arduino的A4引脚。为什么是A4和A5因为Arduino的Wire库I2C通信库硬件上就映射到了这两个引脚。对于其他板子如ESP32I2C引脚可以自定义但Uno是固定的。接好线后硬件部分就完成了。是不是比想象中简单但别急着上电我们还需要在软件上做好准备。3. 软件环境与库安装让屏幕“活”起来硬件是躯体软件是灵魂。要让OLED显示内容我们需要一个强大的“翻译官”——驱动库。在Arduino IDE中我们将使用最流行且功能强大的Adafruit_SSD1306库以及它所依赖的Adafruit_GFX图形库。3.1 安装驱动库的两种方法打开你的Arduino IDE建议使用1.8.x稳定版或更新的2.x版本按照以下步骤操作方法一通过库管理器安装推荐这是最无脑的方法。点击菜单栏的工具 - 管理库...会弹出库管理器窗口。在搜索框中输入“SSD1306”你会看到一堆结果。我们需要安装的是Adafruit SSD1306作者是Adafruit。注意通常你需要安装两个库先安装Adafruit GFX Library。这个库提供了所有绘图函数画点、线、圆、文字等。再安装Adafruit SSD1306。这个库是专门针对SSD1306驱动芯片的它依赖于GFX库。点击“安装”即可IDE会自动处理依赖关系。这是最不容易出错的方式。方法二手动安装备选如果库管理器下载慢或失败可以去GitHub手动下载。访问Adafruit的GitHub仓库搜索“Adafruit_SSD1306”和“Adafruit-GFX-Library”下载ZIP文件。然后在IDE中点击项目 - 加载库 - 添加.ZIP库...选择你下载的ZIP文件。注意手动安装时要确保两个库都正确安装并且放在Arduino IDE的libraries文件夹下。安装成功后你可以在文件 - 示例菜单中找到Adafruit SSD1306的示例程序这说明库已经就绪。3.2 理解I2C地址与扫描库安装好了但你的OLED屏幕真的被Arduino认识吗这里涉及到I2C通信的一个核心概念设备地址。I2C总线上可以挂多个设备每个设备都有一个唯一的7位地址。对于SSD1306 OLED常见的地址是0x3C但有些模块也可能是0x3D。如何确认你的屏幕地址我们可以运行一个简单的I2C扫描程序。打开一个新的Arduino草图复制以下代码#include Wire.h void setup() { Wire.begin(); Serial.begin(9600); Serial.println(I2C Scanner开始扫描...); } void loop() { byte error, address; int nDevices 0; Serial.println(扫描中...); for(address 1; address 127; address ) { Wire.beginTransmission(address); error Wire.endTransmission(); if (error 0) { Serial.print(在地址 0x); if (address16) Serial.print(0); Serial.print(address, HEX); Serial.println( 发现设备); nDevices; } } if (nDevices 0) Serial.println(未发现任何I2C设备); else Serial.println(扫描完成。); delay(5000); // 每5秒扫描一次 }上传代码打开串口监视器波特率设为9600。如果接线正确你应该会看到类似“在地址 0x3C 发现设备”的输出。记下这个地址在后续初始化屏幕时会用到。如果什么都没发现请回头检查接线、电源或者尝试另一个I2C地址。4. 第一个程序让“Hello World”点亮屏幕万事俱备现在让我们写第一个程序在OLED上显示经典的“Hello World”。我们将一步步拆解代码理解每一行的作用。4.1 代码逐行解析创建一个新的Arduino草图输入以下代码// 1. 引入必要的库 #include SPI.h #include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h // 2. 定义OLED屏幕的尺寸和I2C地址 #define SCREEN_WIDTH 128 // 像素宽度 #define SCREEN_HEIGHT 64 // 像素高度 #define OLED_ADDR 0x3C // 替换为你的I2C扫描到的地址 // 3. 创建屏幕对象 // 参数宽度高度Wire对象复位引脚-1表示没有复位引脚I2C地址 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, -1, OLED_ADDR); void setup() { // 4. 初始化串口用于调试 Serial.begin(9600); // 5. 初始化OLED显示屏 if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { Serial.println(F(SSD1306分配失败)); for(;;); // 如果初始化失败程序死循环 } Serial.println(OLED初始化成功); // 6. 清空屏幕缓冲区全黑 display.clearDisplay(); // 7. 设置文本颜色白色 display.setTextColor(SSD1306_WHITE); // 8. 设置文本大小1为默认每个字符5x8像素 display.setTextSize(2); // 放大到2倍 // 9. 设置光标位置X, Y。坐标原点(0,0)在屏幕左上角。 display.setCursor(10, 20); // 10. 打印文本到缓冲区 display.println(Hello, World!); // 11. 将缓冲区内容发送到OLED屏幕真正显示出来 display.display(); // 12. 等待一会儿 delay(2000); } void loop() { // 暂时为空屏幕内容会保持 }关键点解析第3行创建对象Adafruit_SSD1306 display(...)这行代码创建了一个名为display的对象我们后续所有操作画图、写字都通过这个对象调用其方法来完成。Wire表示使用硬件I2C-1表示我们没有连接复位引脚。第5行初始化display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)是启动屏幕的关键。SSD1306_SWITCHCAPVCC是一个参数告诉驱动芯片使用内部电荷泵生成驱动电压这是最常用的方式。如果初始化失败通常是因为I2C地址不对或接线问题。第6-11行显示流程这是核心操作流程clearDisplay()清空缓冲区 - 设置颜色、大小、位置 -println()写入内容到缓冲区 -display()将缓冲区内容一次性刷新到屏幕。所有绘图和文字操作都是在内存缓冲区中进行的只有调用display()后更改才会在物理屏幕上生效。这是一个非常重要的概念可以避免屏幕闪烁。4.2 上传与调试将代码上传到你的Arduino。如果一切顺利你将看到屏幕上清晰地显示出“Hello, World!”。如果屏幕不亮或显示乱码请按以下步骤排查屏幕完全不亮检查VCC和GND是否接反或接触不良。用万用表测量模块供电引脚是否有5V或3.3V电压。显示乱码或雪花点最常见的原因是I2C地址错误。请务必用扫描程序确认地址并修改代码中的OLED_ADDR。初始化失败串口打印出“SSD1306分配失败”。检查接线特别是SDA和SCL是否接在了A4和A5。尝试将地址在0x3C和0x3D之间切换。内容显示不全或位置不对检查setCursor的坐标。屏幕宽度128高度64。如果你设置的起始X坐标加上文本的像素宽度超过了128超出的部分就不会显示。文本的像素宽度大致等于字符数 * 6 * 文本大小对于默认字体。5. 深入图形库超越简单的文字显示只会显示文字可不够Adafruit_GFX库的强大之处在于它提供了丰富的图形绘制功能。让我们把这些功能用起来做一个更丰富的显示界面。5.1 基本图形绘制函数下面的代码演示了如何画点、线、矩形、圆和三角形。我们将在一个新的loop()函数中动态绘制这些图形。void loop() { // 清屏 display.clearDisplay(); // --- 绘制图形 --- // 1. 画一个点 (x, y) display.drawPixel(10, 10, SSD1306_WHITE); // 2. 画一条线 (起点x, 起点y, 终点x, 终点y, 颜色) display.drawLine(0, 15, 127, 15, SSD1306_WHITE); // 3. 画一个矩形 (左上角x, 左上角y, 宽度, 高度, 颜色) display.drawRect(20, 20, 40, 30, SSD1306_WHITE); // 空心矩形 display.fillRect(70, 20, 40, 30, SSD1306_WHITE); // 实心矩形 // 4. 画一个圆 (圆心x, 圆心y, 半径, 颜色) display.drawCircle(40, 55, 10, SSD1306_WHITE); // 空心圆 display.fillCircle(90, 55, 10, SSD1306_WHITE); // 实心圆 // 5. 画一个三角形 (三个顶点的x, y坐标, 颜色) int16_t x0 110, y0 20; int16_t x1 120, y1 40; int16_t x2 100, y2 40; display.drawTriangle(x0, y0, x1, y1, x2, y2, SSD1306_WHITE); // --- 显示文字 --- display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.println(Graphics Demo); // 将缓冲区内容推送到屏幕 display.display(); delay(5000); // 显示5秒 }坐标系统屏幕左上角是原点(0,0)X轴向右递增Y轴向下递增。这是计算机图形学中常见的坐标系。5.2 创建动态动画一个跳动的小球静态图形看腻了我们来做个简单的动画——一个在屏幕边界内来回弹跳的小球。这需要我们在loop()中不断更新小球的位置并重绘。int ballX SCREEN_WIDTH / 2; // 小球初始X位置 int ballY SCREEN_HEIGHT / 2; // 小球初始Y位置 int ballRadius 5; int ballSpeedX 2; // X方向速度 int ballSpeedY 1; // Y方向速度 void loop() { // 清屏用黑色填充相当于擦除上一帧 display.clearDisplay(); // 更新小球位置 ballX ballX ballSpeedX; ballY ballY ballSpeedY; // 边界碰撞检测与反弹 if (ballX ballRadius || ballX SCREEN_WIDTH - ballRadius) { ballSpeedX -ballSpeedX; // X方向速度取反 } if (ballY ballRadius || ballY SCREEN_HEIGHT - ballRadius) { ballSpeedY -ballSpeedY; // Y方向速度取反 } // 绘制小球实心圆 display.fillCircle(ballX, ballY, ballRadius, SSD1306_WHITE); // 绘制边框 display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE); // 显示当前坐标可选 display.setTextSize(1); display.setCursor(2, 2); display.print(X:); display.print(ballX); display.print( Y:); display.print(ballY); // 刷新屏幕 display.display(); delay(20); // 控制帧率约50FPS }这个例子包含了动画的核心逻辑状态更新位置、碰撞检测边界判断、画面重绘清屏后画新图。delay(20)控制了动画的帧率值越小动画越快。你可以尝试修改ballSpeedX/Y和delay的值观察动画效果的变化。实操心得在做动画时clearDisplay()是必须的否则你会看到运动轨迹的拖影。但这也带来了一个问题全屏刷新可能导致肉眼可见的闪烁。对于更复杂的动画可以采用“局部刷新”或“双缓冲”策略不过对于SSD1306和简单的Arduino项目全屏刷新的开销是可以接受的。如果发现闪烁严重可以尝试减少delay的时间或者只擦除和重绘发生变化的部分区域但这会大大增加代码复杂度。6. 综合实战打造一个离线运行的OLED时钟现在我们把前面学到的所有知识整合起来做一个真正实用的小项目一个离线运行的实时时钟RTC。这个时钟可以显示年、月、日、星期、时、分、秒即使Arduino断电需要备用电池也能保持时间。6.1 硬件升级添加DS3231高精度时钟模块Arduino Uno本身没有实时时钟功能断电后时间信息会丢失。我们需要一个外部的RTC模块。DS3231是一款非常流行且高精度的I2C RTC芯片它自带温度补偿走时精准而且有备用电池接口通常配一个CR2032纽扣电池。接线在原有OLED接线基础上增加DS3231模块的VCC- Arduino5VDS3231模块的GND- ArduinoGNDDS3231模块的SDA- ArduinoA4(与OLED共用SDA线)DS3231模块的SCL- ArduinoA5(与OLED共用SCL线)注意I2C总线是支持多设备并联的只要设备地址不同就行。DS3231的默认I2C地址是0x68与OLED的0x3C不冲突所以可以共享SDA和SCL线。6.2 软件准备安装RTC库我们需要一个新的库来驱动DS3231。在Arduino库管理器中搜索并安装RTClib by Adafruit。这个库同样由Adafruit维护与我们的开发环境兼容性好。6.3 完整代码与解析以下是完整的OLED时钟代码包含了时间读取、格式化显示和自动翻页效果。#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #include RTClib.h // 包含RTC库 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_ADDR 0x3C Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, -1, OLED_ADDR); RTC_DS3231 rtc; // 创建RTC对象 // 星期几的字符串数组 char daysOfTheWeek[7][4] {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; int displayPage 0; // 显示页面索引 unsigned long lastPageChange 0; const long pageInterval 3000; // 页面切换间隔3秒 void setup() { Serial.begin(9600); display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR); display.clearDisplay(); // 初始化RTC if (!rtc.begin()) { Serial.println(找不到RTC模块); while (1); // 停止执行 } // 如果RTC丢失电源以下行可以设置时间为编译时间 if (rtc.lostPower()) { Serial.println(RTC失去电力设置时间为编译时间); // 这行代码会在编译时将当前电脑时间设置为RTC的时间。 // 注意上传后需要立即上传一次或者通过其他方式校准时间。 rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } // 如果需要手动设置时间取消下面一行的注释并修改日期时间 // rtc.adjust(DateTime(2024, 5, 27, 15, 30, 0)); } void loop() { DateTime now rtc.now(); // 从RTC获取当前时间 // 每3秒切换一次显示页面 if (millis() - lastPageChange pageInterval) { displayPage (displayPage 1) % 2; // 在0和1之间切换 lastPageChange millis(); } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); if (displayPage 0) { // 页面0大字体显示时间 display.setTextSize(3); display.setCursor(10, 15); // 格式化小时和分钟保持两位数字 if (now.hour() 10) display.print(0); display.print(now.hour()); display.print(:); if (now.minute() 10) display.print(0); display.print(now.minute()); // 小字体显示秒和日期 display.setTextSize(2); display.setCursor(90, 25); if (now.second() 10) display.print(0); display.print(now.second()); display.setTextSize(1); display.setCursor(15, 50); display.print(now.year()); display.print(/); if (now.month() 10) display.print(0); display.print(now.month()); display.print(/); if (now.day() 10) display.print(0); display.print(now.day()); display.print( ); display.print(daysOfTheWeek[now.dayOfTheWeek()]); } else if (displayPage 1) { // 页面1显示更多信息如温度 display.setTextSize(2); display.setCursor(20, 10); display.print(Temp:); display.print(rtc.getTemperature()); // DS3231可以读取温度 display.print( C); display.setTextSize(1); display.setCursor(10, 40); display.print(RTC Battery OK); display.setCursor(10, 50); display.print(Page Auto-Switch); } // 绘制一个底部状态栏显示页面指示器 display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE); for (int i 0; i 2; i) { if (i displayPage) { display.fillCircle(10 i * 15, SCREEN_HEIGHT - 10, 3, SSD1306_WHITE); } else { display.drawCircle(10 i * 15, SCREEN_HEIGHT - 10, 3, SSD1306_WHITE); } } display.display(); delay(100); // 主循环延迟降低CPU占用 }项目要点与避坑指南时间设置代码中rtc.adjust(DateTime(F(__DATE__), F(__TIME__)))这行很巧妙它利用编译时的时间来设置RTC。但这需要你编译并上传代码的那一刻你的电脑时间是准确的。上传成功后记得把这行代码注释掉或者用if (rtc.lostPower())包裹否则每次重启都会重置为编译时间。更专业的做法是写一个串口命令来设置时间。电池续航DS3231模块上的CR2032电池是为了在主板断电时维持时钟运行和芯片内SRAM数据。如果长时间不用电池电量耗尽会导致时间丢失rtc.lostPower()会返回true。I2C冲突确保OLED和RTC的I2C地址不冲突。如果遇到其中一个设备无法识别可以尝试单独连接测试。显示优化代码中通过displayPage变量实现了两个显示页面的自动切换让有限屏幕显示更多信息。状态栏的小圆点指示了当前页面这是一个提升用户体验的小技巧。7. 进阶技巧与性能优化当你熟悉了基础操作后可能会遇到一些性能或功能上的瓶颈。这里分享几个进阶技巧。7.1 使用自定义字体Adafruit_GFX库默认的字体是5x8像素比较小。你可以使用库自带的其他字体或者使用Adafruit-GFX-Library中的Fonts文件夹下的字体甚至自己创建字体。首先你需要包含字体头文件。例如使用内置的16点阵字体#include Fonts/FreeMonoBold12pt7b.h // 包含字体 void setup() { // ... 初始化代码 ... display.setFont(FreeMonoBold12pt7b); // 设置字体 display.setTextSize(1); // 使用字体时setTextSize(1)表示原始字体大小 display.setCursor(0, 20); display.println(Large Font); display.display(); }注意使用大字体非常消耗内存RAM。Arduino Uno只有2KB的RAM一个中文字库或大英文字体很容易导致内存不足程序运行异常。如果遇到奇怪的问题可以尝试移除自定义字体看看。7.2 局部刷新与减少闪烁全屏刷新clearDisplay()和display()是导致闪烁的主要原因。对于更新不频繁的内容如时钟的秒数可以只刷新变化的部分。// 假设只在屏幕右上角更新秒数 void updateSeconds(uint8_t sec) { // 1. 用黑色矩形擦除旧秒数区域覆盖法清空局部 display.fillRect(90, 0, 30, 20, SSD1306_BLACK); // 2. 设置颜色和位置 display.setTextColor(SSD1306_WHITE); display.setCursor(90, 0); // 3. 绘制新秒数 if(sec 10) display.print(0); display.print(sec); // 4. 局部刷新抱歉SSD1306库的display()是全局刷新。 // 我们只能通过减少不必要的clearDisplay()来间接优化。 // display.display(); // 最终还是需要全局刷新 }实际上标准的Adafruit库不支持真正的局部刷新。优化思路是只在必要时调用clearDisplay()。例如在时钟例子中只有切换页面时才需要清屏更新秒数时不需要。我们可以将静态元素如边框、标题和动态元素分开绘制。7.3 内存不足与F()宏在Arduino上字符串常量如Hello, World!默认存放在RAM中。Uno的RAM非常有限大量使用字符串会导致内存迅速耗尽。F()宏可以将字符串常量存放在Flash程序存储器中只在需要时调入RAM。// 消耗RAM Serial.println(这是一个很长的调试信息会占用宝贵的RAM空间。); // 推荐使用F()宏节省RAM Serial.println(F(这是一个很长的调试信息但存放在Flash中。)); display.println(F(OLED显示的文字也可以用F()包裹。));养成使用F()宏的习惯对于复杂的项目稳定性至关重要。7.4 与其他传感器结合OLED作为输出设备天然适合与各种输入传感器结合。例如用DHT11显示温湿度#include DHT.h #define DHTPIN 2 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); void loop() { float h dht.readHumidity(); float t dht.readTemperature(); display.clearDisplay(); display.setTextSize(1); display.setCursor(0,0); display.print(F(Temp: )); display.print(t); display.println(F( C)); display.print(F(Humi: )); display.print(h); display.println(F( %)); display.display(); delay(2000); // DHT11读取间隔至少2秒 }思路就是传感器读取数据 - 数据处理 - 格式化字符串 - 通过display对象输出。你可以将这个模式扩展到光敏、声音、距离等任何传感器。8. 常见问题排查与终极清单即使按照教程你也可能会遇到问题。这里汇总一个终极排查清单帮你快速定位。问题1上传代码后OLED屏幕不亮无任何显示。检查电源用万用表测量OLED的VCC和GND之间是否有电压5V或3.3V。检查地址运行I2C扫描程序确认OLED的I2C地址并确保代码中OLED_ADDR与之匹配。检查库确认Adafruit_SSD1306和Adafruit_GFX库已正确安装。尝试运行库自带的示例文件ssd1306_128x64_i2c。检查复位引脚如果你的OLED模块有RST引脚需要连接到Arduino的一个数字引脚并在代码中修改对象声明将-1改为对应的引脚号。问题2屏幕有亮光但显示乱码、条纹或部分显示。初始化顺序确保在setup()中先执行display.begin()再进行其他设置。电源干扰I2C对电源噪声敏感。尝试在OLED的VCC和GND之间并联一个10uF-100uF的电解电容。上拉电阻I2C总线需要上拉电阻通常4.7KΩ-10KΩ连接到SDA和SCL。很多OLED模块已经内置了如果没有你需要自己在Arduino的A4和A5引脚上拉到5V。缓冲区溢出确保你绘制的图形或文字没有超出屏幕边界0-127, 0-63。问题3程序运行一段时间后死机或行为异常。内存泄漏检查是否在loop()中不断创建新的对象或字符串。确保将不变的字符串用F()宏处理。堆栈溢出避免过深的函数递归调用。使用Serial.print()调试在关键步骤后添加串口打印观察程序执行到哪一步卡住。问题4显示内容有残影或刷新慢。减少clearDisplay()调用只在需要完全清除屏幕时调用它。优化loop()速度移除不必要的delay()将长时间的操作如传感器读取间隔拉长。检查代码效率避免在loop()中进行复杂的浮点运算或字符串拼接。问题5想显示中文或特殊符号。使用取模软件这是最通用的方法。使用如PCtoLCD2002等软件将汉字转换为点阵数组数据。包含字库数组在代码中定义这个数组然后使用drawBitmap()函数将数组数据绘制到屏幕上。注意内存一个16x16的汉字需要32字节的RAM或Flash大量汉字会占用大量空间。Uno可能只能存储很少的汉字考虑使用Flash存储PROGMEM。玩转Arduino和OLED就像搭积木基础操作很简单但组合起来能创造出无限可能。从显示几个字符到构建一个带菜单的交互系统每一步的实践都会带来新的体会。我最深的感受是硬件项目成功的那一刻快乐是纯粹的。别怕出错屏幕不亮、显示乱码都是必经之路对照清单排查你总能找到原因。当你看到自己编写的代码让像素点点亮组成有意义的图案和信息时那种对物理世界的掌控感正是创造的乐趣所在。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价