入手一块圆形屏幕GC9A01,刚开始用tft_espi点了一天也没点亮,不知道是什么原因,后来换了Arduino_GFX这个库成功点亮,库地址:https://github.com/moononournation/Arduino_GFX/wiki/Display-Class 示例程序hello world时钟啥的改个端口声明就完事了就可以跑起来了,但是显示图片就涉及到我这个屏幕小白的知识盲区了,示例里面的例子兼容性很强几乎每个都写了SD模块我没有这个,于是想看看能不能直接取模然后读这个取模的数组,因为是第一次点屏幕很遗憾我没有成功找到那个API(也可能是传参不对),如果有大佬知道请务必教我一下,最终在示例中找到了ImgViewerPng_PNGdec这个示例并加以修改得到了下面的成果
点亮屏幕
首先在PlatformIo中搜索并安装Arduino GFX,这个不多讲了
然后打开helloworld或者clock示例,位置如下图所示,进入后全选复制粘贴到 mian.cpp文件中,记得清空mian.cpp后保留首行的#include <Arduino.h>
//MOSI 是SDA 这里对应自己的接口就可以了
Arduino_DataBus *bus =new Arduino_ESP32SPI(5 /* DC */, 6 /* CS */, 14 /* SCK */, 15 /* MOSI */, -1 /* MISO */, HSPI /* spi_num */);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 7 /* RST */, 0 /* rotation */, true /* IPS */);
编译后,clock示例可能会出现报错,‘xxx‘ was not declared in this scope ,需要手动改一下方法顺序,原因详见我的上一篇文章
https://blog.csdn.net/qq_40288383/article/details/113736395?spm=1001.2014.3001.5502 之后烧录成功就可以进行下一步了
PlatformIo中设置littlefs
在platformIo.ini中加入board_build.filesystem = littlefs
board_build.filesystem = littlefs
然后在src文件夹的同级建立data文件夹,把要显示的图片放在data文件夹下
然后点击PlatformIo图标进入PlatformIo页面依次点击执行下面三个命令(一个执行成功后再点下一个) 将data中的数据烧录到flash中
做完这些我们还要再装一个PNGdec库去读取png格式的文件
platformIo.ini的参考
lib_ldf_mode = deep+可加可不加
bodmer/TFT_eSPI@^2.5.43是因为我没跑起来没有删掉
至此图片的准备工作完成
代码烧录
我对ImgViewerPng_PNGdec.ino这个实例做了删减,删除了SD相关的代码改为直接读取 flash中的PNG图片,并做了翻译以便理解,大伙在做完上面的配置之后可以直接复制粘贴烧录
#include <Arduino.h>
/*******************************************************************************
* PNG图像查看器
* 这是一个简单的PNG图像查看器示例,适用于ESP32并使用LittleFS文件系统。
* 图像来源:https://github.com/logos
*
* 依赖库:
* PNGdec:https://github.com/bitbank2/PNGdec.git
*
* 设置步骤:
* 1. 在Arduino_GFX设置中更改您的LCD参数。
* 2. 使用ESP8266 LittleFS Data Upload工具(针对ESP32,参考:https://github.com/lorol/arduino-esp32fs-plugin)上传PNG文件到LittleFS文件系统。
******************************************************************************/
#define PNG_FILENAME "/image.png"
#define PNG_4BPP_FILENAME "/image.png"
/*******************************************************************************
* Arduino_GFX设置开始
*
* Arduino_GFX会根据在Arduino IDE中所选的开发板尝试查找设置,
* 这里我们针对非显示开发套件的默认引脚进行设置(以ESP32为例)。
* ESP32开发板默认引脚列表:CS:5,DC:27,RST:33,BL:22,SCK:18,MOSI:23,MISO:无
******************************************************************************/
#include <Arduino_GFX_Library.h>
#define GFX_BL DF_GFX_BL // 默认背光灯引脚,您可以将DF_GFX_BL替换为实际的背光灯引脚
/* 更多开发设备声明:https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /*!defined(DISPLAY_DEV_KIT) */
//这里记得改成自己的引脚
Arduino_DataBus *bus =new Arduino_ESP32SPI(5 /* DC */, 6 /* CS */, 14 /* SCK */, 15 /* MOSI */, -1 /* MISO */, HSPI /* spi_num */);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 7 /* RST */, 0 /* rotation */, true /* IPS */);
#endif /*!defined(DISPLAY_DEV_KIT) */
/*******************************************************************************
* Arduino_GFX设置结束
******************************************************************************/
#include <LittleFS.h>
#include <PNGdec.h>
PNG png;
int16_t w, h, xOffset, yOffset;
// 用于访问LittleFS文件系统上文件的函数
File pngFile;
// 打开文件的函数,从LittleFS文件系统中打开指定的PNG文件
void *myOpen(const char *filename, int32_t *size)
{
pngFile = LittleFS.open(filename, "r");
if (!pngFile || pngFile.isDirectory())
{
Serial.println(F("错误:打开 " PNG_FILENAME " 文件用于读取失败"));
gfx->println(F("错误:打开 " PNG_FILENAME " 文件用于读取失败"));
}
else
{
*size = pngFile.size();
Serial.printf("已打开 '%s',大小:%d\n", filename, *size);
}
return &pngFile;
}
// 关闭文件的函数
void myClose(void *handle)
{
if (pngFile)
pngFile.close();
}
// 从打开的文件中读取数据的函数
int32_t myRead(PNGFILE *handle, uint8_t *buffer, int32_t length)
{
if (!pngFile)
return 0;
return pngFile.read(buffer, length);
}
// 在打开的文件中定位到指定位置的函数
int32_t mySeek(PNGFILE *handle, int32_t position)
{
if (!pngFile)
return 0;
return pngFile.seek(position);
}
// 将像素绘制到显示器上的函数
void PNGDraw(PNGDRAW *pDraw)
{
uint16_t usPixels[320];
uint8_t usMask[320];
png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN, 0x00000000);
png.getAlphaMask(pDraw, usMask, 1);
gfx->draw16bitRGBBitmapWithMask(xOffset, yOffset + pDraw->y, usPixels, usMask, pDraw->iWidth, 1);
}
// 初始化设置函数
void setup()
{
Serial.begin(9600);
// Serial.setDebugOutput(true);
// while(!Serial);
Serial.println("Arduino_GFX PNG图像查看器示例(ESP32 - LittleFS)");
#ifdef GFX_EXTRA_PRE_INIT
GFX_EXTRA_PRE_INIT();
#endif
// 初始化显示器
if (!gfx->begin())
{
Serial.println("gfx->begin()失败!");
}
gfx->fillScreen(BLACK);
w = gfx->width(), h = gfx->height();
gfx->fillScreen(BLACK);
for (int16_t x = 0; x < w; x += 5)
{
gfx->drawFastVLine(x, 0, h, PALERED);
}
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
if (!LittleFS.begin())
{
Serial.println(F("错误:LittleFS文件系统挂载失败!"));
gfx->println(F("错误:LittleFS文件系统挂载失败!"));
}
else
{
unsigned long start = millis();
int rc;
rc = png.open(PNG_FILENAME, myOpen, myClose, myRead, mySeek, PNGDraw);
if (rc == PNG_SUCCESS)
{
int16_t pw = png.getWidth();
int16_t ph = png.getHeight();
xOffset = (w - pw) / 2;
yOffset = (h - ph) / 2;
rc = png.decode(NULL, 0);
Serial.printf("绘制偏移量:(%d, %d),所用时间:%lu\n", xOffset, yOffset, millis() - start);
Serial.printf("图像规格:(%d x %d),%d bpp,像素类型:%d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
png.close();
}
else
{
Serial.println("png.open()失败!");
}
}
delay(5000); // 5秒钟
}
// 循环执行的函数
void loop()
{
unsigned long start = millis();
int rc;
rc = png.open(PNG_4BPP_FILENAME, myOpen, myClose, myRead, mySeek, PNGDraw);
if (rc == PNG_SUCCESS)
{
// 随机绘制位置
int16_t pw = png.getWidth();
int16_t ph = png.getHeight();
xOffset = random(w) - (pw / 2);
yOffset = random(h) - (ph / 2);
rc = png.decode(NULL, 0);
Serial.printf("绘制偏移量:(%d, %d),所用时间:%lu\n", xOffset, yOffset, millis() - start);
Serial.printf("图像规格:(%d x %d),%d bpp,像素类型:%d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
png.close();
}
else
{
Serial.println("png.open()失败!");
}
delay(1000); // 1秒钟
}