本节我们继续ESP和ST 7789的话题,这节课我们来学学如何展示图片,话不多说,先上效果
好,教程开始~前情提要,要看懂这篇,建议搭配楼主的前两期文章
使用ESP32驱动LCD-ST7789屏幕[ESP--2]
加速你的LCD-ST7789屏幕![ESP--3]
好,话不多说,直接开始
显示原理
ST7789支持的颜色为RGB565,一般我们常见的颜色是RGB888,就是RGB三色各占一个字节(一个字节8位),ST7789毕竟是MCU模块,自然要减轻负担,所以RGB阉割成了2字节能表示的(人眼对绿光最敏感,所以绿光的色阶更多)
然后如何在屏幕上放像素呢?
cpp
tft.drawPixel(x , y , 0xFFFF);
//封装好的函数,直接输入一个二字节数就行,多么简单
所以现在的问题就是怎么把图片转换为一个RGB565数组,然后导入我们的程序。这里我使用的是开源的格式转换工具BMPCVT
在网上和GITHUB上有这个软件
使用方法
- 点击FILE/OPEN 打开你需要转换的文件
、
选择IMAGE/CONVERT INTO /16BIT COLOR565
选择FILE/SAVE AS/进入下面的界面
选择C bitmap的格式,保存到你可见的位置
/
最后的加工
不过这个数组我们现在还不能直接使用,因为我们用的是eSPI 库,这个作者用的是GUI(?)
打开文件,你会看到这个画面
- 删除include 命令
- 删除数组的static 修饰符
- 删去结尾的那个结构体
- 将这个文件放到你的工程中去
- 如果可以,把后缀改成H,然后包含一下
下面就是代码了
cpp
#include <TFT_eSPI.h>
#include <SPI.h>
#include "image_rgb565.cpp"
//包含你的数组
class Timer {
public:
Timer() : start_timepoint(std::chrono::high_resolution_clock::now()) {}
void reset() {
start_timepoint = std::chrono::high_resolution_clock::now();
}
double elapsed() const {
auto end_timepoint = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_time = end_timepoint - start_timepoint;
return elapsed_time.count();
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> start_timepoint;
};
Timer timer;
TFT_eSPI tft = TFT_eSPI(); // 使用优化后的TFT_eSPI库
void drawImage() {
// 将图片数据绘制到 ST7789 上
int16_t x = 0, y = 0; // 图像绘制起始位置
for (int16_t j = 0; j < 240; j++) {
for (int16_t i = 0; i < 240; i++) {
uint16_t color = image_data[j * 240 + i];
tft.drawPixel(x + i, y + j, color);
}
}
}
void setup() {
Serial.begin(9600);
tft.init();
tft.setRotation(1); // 设置旋转
// 如果需要,可以明确调用长宽
// 显示固定的文本,只在 setup 中显示一次
tft.fillScreen(TFT_BLACK);
Serial.printf("Total heap: %d ", ESP.getHeapSize()); // 获取总堆内存大小
Serial.println();
Serial.printf("Free heap: %d", ESP.getFreeHeap()); // 获取当前可用堆内存大小
Serial.println();
Serial.printf("Total PSRAM: %d", ESP.getPsramSize()); // 获取总PSRAM大小(如果支持)
Serial.println();
Serial.printf("Free PSRAM: %d", ESP.getFreePsram()); // 获取当前可用PSRAM大小(如果支持)
Serial.println();
}
void loop() {
// 绘制动态变化的部分
tft.fillRect(0, 0, 100, 50, TFT_BLACK); // 清除FPS部分
drawImage();
float FPS = 1 / (timer.elapsed());
tft.setCursor(0, 0);
tft.printf("FPS: %.2f", FPS);
timer.reset();
delay(50);
}