开发平台:Arduino 开发板:Beetle ESP32 C6 功能:驱动OLED |
ESP32-C6点亮0.96寸OLED显示屏的计划可以大致分为以下几个步骤:
硬件准备:
确保你拥有ESP32-C6开发板和0.96寸OLED显示屏。
检查显示屏的接口,通常这种尺寸的OLED显示屏使用I2C通信协议,因此需要确保ESP32-C6上有合适的I2C接口。
库的安装:
安装用于I2C通信的库,例如Adafruit_BusIO库和Adafruit_EPD库。这些库将帮助你在ESP32-C6和OLED显示屏之间建立通信。
连接ESP32-C6和OLED显示屏:
根据OLED显示屏的引脚定义,将SCL(串行时钟)和SDA(串行数据)连接到ESP32-C6的相应I2C接口上。
确保其他必要的电源和地线连接正确。
编写代码:
在Arduino IDE中编写代码,初始化I2C接口,并设置OLED显示屏的参数。
使用库函数来驱动OLED显示屏,例如设置显示内容、字体、颜色等。
上传代码并测试:
将编写好的代码上传到ESP32-C6开发板上。
观察OLED显示屏是否成功点亮,并显示预期的内容。
调试和优化:
如果显示屏没有正常工作,检查硬件连接和代码是否有误。
根据需要调整代码,优化显示效果和性能。
#include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED显示屏的宽度,单位为像素 #define SCREEN_HEIGHT 64 // OLED显示屏的高度,单位为像素 #define OLED_RESET -1 // 复位引脚编号(如果与Arduino复位引脚共用则为-1) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define NUMFLAKES 10 // 动画示例中的雪花数量 #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 // 定义位图数据,存储在程序存储区 static const unsigned char PROGMEM logo_bmp[] = { // ... 位图数据 ... }; const int I2C_ADDR = 0x3c; // OLED屏幕的I2C地址 #define SDA_PIN 19 // SDA引脚(数据线) #define SCL_PIN 20 // SCL引脚(时钟线) void setup() { // 初始化串行通信 Serial.begin(9600); // 初始化OLED显示屏 if (!display.begin(SSD1306_SWITCHCAPVCC, I2C_ADDR)) { Serial.println(F("SSD1306 allocation failed")); while (1); // 如果初始化失败,则无限循环 } // 清除显示屏内容 display.clearDisplay(); // 显示一个白色像素点 display.drawPixel(10, 10, WHITE); display.display(); // 更新显示屏内容 // 等待两秒 delay(2000); // 这里应该调用测试函数,但需要确保它们已经被定义 // testdrawline(); // 绘制多行 // ... 调用其他测试函数 ... } void loop() { // 主循环中的代码 // 通常这里会放置需要重复执行的代码 } // 下面是测试函数的声明(或定义),这些函数需要在其他地方实现 // void testdrawline(); // void testdrawrect(); // ... 其他测试函数的声明 ... // 注意:如果您要取消注释 testdrawbitmap(); 函数,您需要确保实现了它 // testdrawbitmap();
// 反转显示屏的颜色,白色变为黑色,黑色变为白色 display.invertDisplay(true); delay(1000); // 等待一秒 // 恢复显示屏的正常颜色显示 display.invertDisplay(false); delay(1000); // 再等待一秒 // 调用一个名为testanimate的函数来动画显示位图 // 此函数尚未在给定的代码段中定义,需要在其他地方实现 testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // 动画显示位图 // Arduino主循环的入口点,此函数将无限循环 void loop() { // 主循环内目前为空,您可以在此处添加需要重复执行的代码 } // 定义一个函数,用于测试绘制直线 void testdrawline() { int16_t i; // 清除显示屏缓冲区 display.clearDisplay(); // 从左到右绘制一系列横线 for(i=0; i<display.width(); i+=4) { display.drawLine(0, 0, i, display.height()-1, WHITE); display.display(); // 更新屏幕以显示新绘制的直线 delay(1); // 等待一毫秒 } // 从上到下绘制一系列竖线 for(i=0; i<display.height(); i+=4) { display.drawLine(0, 0, display.width()-1, i, WHITE); display.display(); delay(1); } delay(250); // 等待250毫秒 // 清除显示屏缓冲区 display.clearDisplay(); // 从左上到右下绘制一系列对角线 for(i=0; i<display.width(); i+=4) { display.drawLine(0, display.height()-1, i, 0, WHITE); display.display(); delay(1); } // 从右上到左下绘制一系列对角线 for(i=display.height()-1; i>=0; i-=4) { display.drawLine(0, display.height()-1, display.width()-1, i, WHITE); display.display(); delay(1); } delay(250); // 等待250毫秒 // 清除显示屏缓冲区 display.clearDisplay(); // 从右上到左下绘制一系列对角线 for(i=display.width()-1; i>=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE); display.display(); delay(1); } // 从左上到右下绘制一系列对角线 for(i=display.height()-1; i>=0; i-=4) { display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE); display.display(); delay(1); } delay(250); // 等待250毫秒 // 清除显示屏缓冲区 display.clearDisplay(); // 从下到上绘制一系列竖线 for(i=0; i<display.height(); i+=4) { display.drawLine(display.width()-1, 0, 0, i, WHITE); display.display(); delay(1); } // 从左到右绘制一系列横线 for(i=0; i<display.width(); i+=4) { display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE); display.display(); delay(1); } delay(2000); // 暂停两秒 } // 定义一个函数,用于测试绘制矩形(只绘制矩形边框) void testdrawrect(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐缩小矩形的大小并绘制 for(int16_t i=0; i<display.height()/2; i+=2) { display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE); display.display(); // 更新屏幕以显示新绘制的矩形 delay(1); // 等待一毫秒 } // 测试填充矩形的函数void testfillrect(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐扩大矩形的大小并填充颜色 for(int16_t i=0; i<display.height()/2; i+=3) { // 使用反色,使得矩形在白色和黑色之间交替 display.fillRect(i, i, display.width()-i*2, display.height()-i*2, INVERSE); display.display(); // 更新屏幕以显示新填充的矩形 delay(1); // 等待一毫秒 } // 等待两秒 delay(2000); } // 测试绘制圆的函数 void testdrawcircle(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐扩大圆的大小并绘制 for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) { display.drawCircle(display.width()/2, display.height()/2, i, WHITE); display.display(); // 更新屏幕以显示新绘制的圆 delay(1); // 等待一毫秒 } // 等待两秒 delay(2000); } // 测试填充圆的函数 void testfillcircle(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐缩小圆的大小并填充颜色 for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) { display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE); display.display(); // 更新屏幕以显示新填充的圆 delay(1); // 等待一毫秒 } // 等待两秒 delay(2000); } // 测试绘制圆角矩形的函数 void testdrawroundrect(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐扩大圆角矩形的大小并绘制 for(int16_t i=0; i<display.height()/2-2; i+=2) { display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE); display.display(); // 更新屏幕以显示新绘制的圆角矩形 delay(1); // 等待一毫秒 } // 等待两秒 delay(2000); } // 测试填充圆角矩形的函数 void testfillroundrect(void) { // 清除显示屏缓冲区 display.clearDisplay(); // 从屏幕中心开始,逐渐扩大圆角矩形的大小并填充颜色 for(int16_t i=0; i<display.height()/2-2; i+=2) { // 使用反色,使得圆角矩形在白色和黑色之间交替 display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, INVERSE); display.display(); // 更新屏幕以显示新填充的圆角矩形 delay(1); // 等待一毫秒 } // 等待两秒 delay(2000); }
// 测试绘制三角形的函数
void testdrawtriangle(void) {
display.clearDisplay(); // 清除显示屏缓冲区
// 从屏幕中心开始,逐渐增大三角形的大小并绘制
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2, // 三角形顶点1的x坐标(屏幕中心)
display.height()/2-i, // 三角形顶点1的y坐标(屏幕中心上方)
display.width()/2-i, // 三角形顶点2的x坐标
display.height()/2+i, // 三角形顶点2的y坐标(屏幕中心下方)
display.width()/2+i, // 三角形顶点3的x坐标
display.height()/2+i, // 三角形顶点3的y坐标(屏幕中心下方)
WHITE); // 绘制颜色为白色
display.display(); // 更新屏幕以显示新绘制的三角形
delay(1); // 等待一毫秒
}
delay(2000); // 等待两秒
}
// 测试填充三角形的函数
void testfilltriangle(void) {
display.clearDisplay(); // 清除显示屏缓冲区
// 从屏幕中心开始,逐渐缩小三角形的大小并填充颜色
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// 使用反色,使得三角形在白色和黑色之间交替
display.fillTriangle(
display.width()/2, // 三角形顶点1的x坐标(屏幕中心)
display.height()/2-i, // 三角形顶点1的y坐标(屏幕中心上方)
display.width()/2-i, // 三角形顶点2的x坐标
display.height()/2+i, // 三角形顶点2的y坐标(屏幕中心下方)
display.width()/2+i, // 三角形顶点3的x坐标
display.height()/2+i, // 三角形顶点3的y坐标(屏幕中心下方)
INVERSE); // 填充颜色为反色
display.display(); // 更新屏幕以显示新填充的三角形
delay(1); // 等待一毫秒
}
delay(2000); // 等待两秒
}
// 测试绘制字符的函数
void testdrawchar(void) {
display.clearDisplay(); // 清除显示屏缓冲区
display.setTextSize(1); // 设置文本大小为正常1:1像素比例
display.setTextColor(WHITE); // 设置绘制文本的颜色为白色
display.setCursor(0, 0); // 设置光标位置为左上角
display.cp437(true); // 使用完整的256字符'Code Page 437'字体
// 不是所有字符都能在显示屏上完全显示。这是正常的。
// 库会绘制它能够绘制的内容,其余的将被裁剪。
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' '); // 如果是换行符,则写入空格
else display.write(i); // 否则写入当前字符
}
display.display(); // 更新屏幕以显示绘制的字符
delay(2000); // 等待两秒
}
// 测试绘制文本样式的函数
void testdrawstyles(void) {
display.clearDisplay(); // 清除显示屏缓冲区
display.setTextSize(1); // 设置文本大小为正常1:1像素比例
display.setTextColor(WHITE); // 设置绘制文本的颜色为白色
display.setCursor(0,0); // 设置光标位置为左上角
display.println(F("Hello, world!")); // 打印并换行"Hello, world!"
display.setTextColor(BLACK, WHITE); // 设置绘制文本的颜色为反色(黑色背景,白色文本)
display.println(3.141592); // 打印浮点数3.141592
display.setTextSize(2); // 设置文本大小为2倍像素比例
display.setTextColor(WHITE); // 设置绘制文本的颜色为白色
display.print(F("0x")); // 打印"0x"
display.println(0xDEADBEEF, HEX); // 打印十六进制数0x
// 测试文本滚动效果的函数 void testscrolltext(void) { display.clearDisplay(); // 清除显示屏缓冲区 display.setTextSize(2); // 设置文本大小为2倍像素比例 display.setTextColor(WHITE); // 设置绘制文本的颜色为白色 display.setCursor(10, 0); // 设置光标位置 display.println(F("scroll")); // 打印并换行"scroll" display.display(); // 更新屏幕以显示初始文本 delay(100); // 等待0.1秒 // 在不同方向上滚动文本,并在之间暂停: display.startscrollright(0x00, 0x0F); // 从左向右滚动 delay(2000); // 等待2秒 display.stopscroll(); // 停止滚动 delay(1000); // 等待1秒 display.startscrollleft(0x00, 0x0F); // 从右向左滚动 delay(2000); // 等待2秒 display.stopscroll(); // 停止滚动 delay(1000); // 等待1秒 display.startscrolldiagright(0x00, 0x07); // 对角线方向向右滚动 delay(2000); // 等待2秒 display.startscrolldiagleft(0x00, 0x07); // 对角线方向向左滚动 delay(2000); // 等待2秒 display.stopscroll(); // 停止滚动 delay(1000); // 等待1秒 } // 测试绘制位图的函数 void testdrawbitmap(void) { display.clearDisplay(); // 清除显示屏缓冲区 // 在屏幕中心绘制位图 display.drawBitmap( (display.width() - LOGO_WIDTH ) / 2, // 计算位图的x坐标位置 (display.height() - LOGO_HEIGHT) / 2, // 计算位图的y坐标位置 logo_bmp, // 位图数据 LOGO_WIDTH, // 位图宽度 LOGO_HEIGHT, // 位图高度 1); // 位图的颜色深度(通常为1) display.display(); // 更新屏幕以显示位图 delay(1000); // 等待1秒 } // 定义常量,用于下面的函数中的图标数组索引 #define XPOS 0 // x坐标索引 #define YPOS 1 // y坐标索引 #define DELTAY 2 // y轴变化量索引 // 测试动画效果的函数,传入位图数据、宽度和高度 void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) { int8_t f; // 循环变量 uint8_t icons[NUMFLAKES][3]; // 存储雪花图标位置的数组 // 初始化雪花位置 for(f = 0; f < NUMFLAKES; f++) { icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); // 随机x坐标(确保不会超出屏幕边界) icons[f][YPOS] = -LOGO_HEIGHT; // 初始y坐标为屏幕上方,即图标初始不可见 icons[f][DELTAY] = random(1, 6); // 随机y轴变化量(下落速度) Serial.print(F("x: ")); // 打印x坐标到串行监视器 Serial.print(icons[f][XPOS], DEC); // 以十进制格式打印x坐标 Serial.print(F(" y: ")); // 打印y坐标 Serial.print(icons[f][YPOS], DEC); // 以十进制格式打印y坐标 Serial.print(F(" dy: ")); // 打印y轴变化量 Serial.println(icons[f][DELTAY], DEC); // 以十进制格式打印y轴变化量 } for(;;) { // 无限循环 display.clearDisplay(); // 清除显示屏缓冲区 // 绘制每个雪花图标 for(f = 0; f < NUMFLAKES; f++) { display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE); // 绘制位图 } display.display(); // 更新屏幕以显示雪花图标 delay(200); // 等待0.
for(;;) { // 无限循环 display.clearDisplay(); // 清除显示屏缓冲区 // 绘制每个雪花图标 for(f = 0; f < NUMFLAKES; f++) { display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE); // 绘制位图 // 检查雪花是否已经移出屏幕底部 if (icons[f][YPOS] >= display.height()) { // 如果是,则重新初始化雪花的位置到屏幕顶部之外的一个随机位置 icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); // 重新设置x坐标 icons[f][YPOS] = -LOGO_HEIGHT; // 将y坐标设置为屏幕顶部上方 icons[f][DELTAY] = random(1, 6); // 重新设置y轴变化量 } } display.display(); // 更新屏幕以显示雪花图标 delay(200); // 等待0.2秒 }
描述了一个在屏幕上显示并模拟雪花下落效果的程序片段。程序通过不断绘制雪花图标并更新它们的位置来模拟雪花飘落的效果。
代码的主要逻辑如下:
初始化一个无限循环,用于持续更新屏幕上的雪花图标。
在每次循环中,首先清除显示屏缓冲区,确保没有之前的绘制残留。
遍历所有雪花图标(由icons数组表示),对每个雪花图标进行绘制。绘制位置由当前雪花的x坐标(icons[f][XPOS])和y坐标(icons[f][YPOS])决定。
检查雪花图标的y坐标是否超出了屏幕的高度。如果是,则执行以下操作:
重新计算雪花图标的x坐标,将其置于屏幕宽度范围内的随机位置,确保不会超出屏幕边界。
将雪花图标的y坐标设置为屏幕顶部之上(通常是负数,代表屏幕外的位置),这样雪花在下一帧更新时会从屏幕顶部开始下落。
重新为雪花图标分配一个随机的y轴变化量(即下落速度),影响雪花每次循环下落的距离。
调用display.display()函数更新屏幕,将绘制好的雪花图标显示出来。
等待一段时间(例如0.2秒),使雪花下落动画看起来更流畅。
视频:
ESP32-C6驱动0.96寸OLED显示屏并显示图案_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1QE421M7pA/?spm_id_from=333.999.0.0&vd_source=0e4686609dd9c60a63b3f7fe54080c03