长生栈 长生栈
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Living Team

编程技术分享
首页
  • 编程语言

    • C语言
    • C++
    • Java
    • Python
  • 数据结构和算法

    • 全排列算法实现
    • 动态规划算法
  • CMake
  • gitlab 安装和配置
  • docker快速搭建wordpress
  • electron+react开发和部署
  • Electron-创建你的应用程序
  • ImgUI编译环境
  • 搭建图集网站
  • 使用PlantUml画时序图
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机视觉

  • ESP32开发

    • ESP32-开发环境配置
    • ESP32-点亮LED灯
    • ESP32-点亮OLED屏幕
      • 效果
      • 使用SSD1306驱动oled屏幕
        • 连线
        • 代码
    • ESP32-实时操作系统freertos
    • ESP32-PWM驱动SG90舵机
    • ESP32-网络摄像头方案
  • Linux系统移植

  • 快速开始

  • 编程小知识

  • 技术
  • ESP32开发
DC Wang
2025-06-14
目录

ESP32-点亮OLED屏幕

# ESP32-点亮OLED屏幕

本文以ESP32-S3N16R8为例,介绍如何使用SSD1306驱动128x64的oled单色屏幕。

# 效果

画面显示一个不断旋转的立方体,并显示帧率。

output

# 使用SSD1306驱动oled屏幕

# 连线

ESP32-S3 (引脚定义)    ➔    SSD1306 OLED屏幕
-----------------------------------------
  GPIO11 (OLED_DIN)    ➔     MOSI/D1 (数据输入)
  GPIO12 (OLED_CLK)    ➔     SCK/D0 (时钟信号)
  GPIO16 (OLED_DC)     ➔     DC (数据/命令选择)
  GPIO17 (OLED_RST)    ➔     RES (复位信号)
  GPIO10 (OLED_CS)     ➔     CS (片选信号)
      3.3V             ➔     VCC (电源正极)
      GND              ➔     GND (电源负极)
1
2
3
4
5
6
7
8
9

# 代码

#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define OLED_DIN   11
#define OLED_CLK   12
#define OLED_DC    16
#define OLED_RST   17
#define OLED_CS    10

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_DIN, OLED_CLK, OLED_DC, OLED_RST, OLED_CS);

// 3D立方体参数
struct Point2D { float x, y; };
struct Point3D { float x, y, z; };
const int CUBE_SIZE = 10;  // 立方体边长
Point3D cube[] = {
  {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1},
  {-1, -1, 1},  {1, -1, 1},  {1, 1, 1},  {-1, 1, 1}
};

// 旋转参数
float angleX = 0, angleY = 0, angleZ = 0;
const float ROTATION_SPEED = 0.02;

// 帧率计算
unsigned long frameCount = 0;
unsigned long lastFPSUpdate = 0;
float fps = 0;

// 3D到2D投影(正交投影)
Point3D project(Point3D point) {
  return {
    point.x * CUBE_SIZE + SCREEN_WIDTH/2,
    point.y * CUBE_SIZE + SCREEN_HEIGHT/2 + 5, // 中心向下加上5像素的偏移
    point.z
  };
}

// 绕X轴旋转
void rotateX(Point3D &p, float angle) {
  float y = p.y;
  p.y = y * cos(angle) - p.z * sin(angle);
  p.z = y * sin(angle) + p.z * cos(angle);
}

// 绕Y轴旋转
void rotateY(Point3D &p, float angle) {
  float x = p.x;
  p.x = x * cos(angle) - p.z * sin(angle);
  p.z = x * sin(angle) + p.z * cos(angle);
}

// 绕Z轴旋转
void rotateZ(Point3D &p, float angle) {
  float x = p.x;
  p.x = x * cos(angle) - p.y * sin(angle);
  p.y = x * sin(angle) + p.y * cos(angle);
}

// 绘制立方体
void drawCube() {
  // 存储投影后的2D点坐标
  Point2D screenPoints[8];

  // 旋转并投影所有顶点
  for (int i=0; i<8; i++) {
    Point3D tp = cube[i];
    rotateX(tp, angleX);
    rotateY(tp, angleY);
    rotateZ(tp, angleZ);
    Point3D proj = project(tp);
    screenPoints[i] = { (int)proj.x, (int)proj.y };
  }

  // 定义12条边(顶点索引对)
  const int edges[12][2] = {
    {0,1}, {1,2}, {2,3}, {3,0}, // 前面
    {4,5}, {5,6}, {6,7}, {7,4}, // 后面
    {0,4}, {1,5}, {2,6}, {3,7}  // 连接面
  };

  // 绘制所有边
  for (auto &edge : edges) {
    Point2D p1 = screenPoints[edge[0]];
    Point2D p2 = screenPoints[edge[1]];
    display.drawLine(p1.x, p1.y, p2.x, p2.y, SSD1306_WHITE);
  }
}

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  unsigned long frameStart = millis();
  
  display.clearDisplay();
  
  // 绘制立方体
  drawCube();
  
  // 更新旋转角度
  angleX += ROTATION_SPEED;
  angleY += ROTATION_SPEED * 0.7;
  angleZ += ROTATION_SPEED * 0.3;
  
  // 显示帧率
  display.setCursor(0, 0);
  display.print("FPS:");
  display.print(fps, 1);
  
  display.display();
  frameCount++;
  
  // 计算帧率
  if (millis() - lastFPSUpdate >= 1000) {
    fps = frameCount * 1000.0 / (millis() - lastFPSUpdate);
    lastFPSUpdate = millis();
    frameCount = 0;
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
编辑 (opens new window)
#ESP32
ESP32-点亮LED灯
ESP32-实时操作系统freertos

← ESP32-点亮LED灯 ESP32-实时操作系统freertos→

最近更新
01
ESP32-网络摄像头方案
06-14
02
ESP32-PWM驱动SG90舵机
06-14
03
ESP32-实时操作系统freertos
06-14
更多文章>
Theme by Vdoing | Copyright © 2019-2025 DC Wang All right reserved | 辽公网安备 21021102001125号 | 吉ICP备20001966号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式