如果觉得有用,麻烦点赞收藏,您的支持是博主创作的动力。
1. 前言
在上一篇
one.h文件内容:
编码有点多,这里不贴出来。
2. 优化前ino代码
#include <TFT_eSPI.h>
#include <SPI.h>
#include <TJpg_Decoder.h>
#include <Arduino.h>
#include "one.h" //引入gif生成的.h文件
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
// LCD屏幕相关设置是什么屏幕什么驱动
// 引脚需配置tft_espi库中的 User_Setup.h文件
TFT_eSPI tft = TFT_eSPI();
//动画更新时间记录
int Amimate_reflash_Time = 0;
int Animate_key = -1; //初始化图标显示帧数
//从动图数组里面获取一帧图像数据
void imgAnim(const uint8_t **Animate_value, uint32_t *Animate_size){
Animate_key++;
*Animate_value = one[Animate_key];
*Animate_size = one_size[Animate_key];
if (Animate_key >= (sizeof(one)/sizeof(one[0])-1)) //gif动图帧数
Animate_key = -1;
}
// TFT屏幕输出函数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap){
if (y >= tft.height())
return 0;
tft.pushImage(x, y, w, h, bitmap);
return 1;
}
void setup(){
Serial.begin(115200);
tft.begin();
tft.invertDisplay(1); //反转所有显示颜色1反转0正常
tft.setRotation(0);
tft.fillScreen(0x0000);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
tft.fillScreen(TFT_BLACK);
}
void loop(){
const uint8_t *Animate_value; //指向关键帧的指针
uint32_t Animate_size; //指向关键帧大小的指针
if (millis() - Amimate_reflash_Time > 30){
Amimate_reflash_Time = millis();
imgAnim(&Animate_value, &Animate_size);
TJpgDec.drawJpg(0, 0, Animate_value, Animate_size);
}
}
3. 优化后ino代码
#include <TFT_eSPI.h>
#include <SPI.h>
#include <TJpg_Decoder.h>
#include <Arduino.h>
#include "one.h" //引入gif生成的.h文件
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
// LCD屏幕相关设置是什么屏幕什么驱动
// 引脚需配置tft_espi库中的 User_Setup.h文件
TFT_eSPI tft = TFT_eSPI();
//动画更新时间记录
int Amimate_reflash_Time = 0;
int Animate_key = -1; //初始化图标显示帧数
// DMA 双缓冲模式
// DMA 直接内存搬运技术,使数据不经过cpu,直接从内存搬运到spi的发送的寄存器里面,这样做的好处是减少cpu的负担,而且能大大提升显示屏的刷新速率
uint16_t dmaBuffer1[32 * 32]{}; // Toggle buffer for 32*32 MCU block, 1024bytes
uint16_t dmaBuffer2[32 * 32]{}; // Toggle buffer for 32*32 MCU block, 1024bytes
uint16_t *dmaBufferPtr = dmaBuffer1;
// 当前使用的DMA缓冲
bool dmaBufferSel = 0;
//从动图数组里面获取一帧图像数据
void imgAnim(const uint8_t **Animate_value, uint32_t *Animate_size){
Animate_key++;
*Animate_value = one[Animate_key];
*Animate_size = one_size[Animate_key];
if (Animate_key >= (sizeof(one)/sizeof(one[0])-1)) //gif动图帧数
Animate_key = -1;
}
// TFT屏幕输出函数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap){
if (y >= tft.height())
return 0;
if (dmaBufferSel) {
dmaBufferPtr = dmaBuffer2;
} else {
dmaBufferPtr = dmaBuffer1;
}
dmaBufferSel = !dmaBufferSel;
tft.pushImageDMA(x, y, w, h, bitmap, dmaBufferPtr);
return 1;
}
void setup(){
Serial.begin(115200);
tft.begin();
tft.invertDisplay(1); //反转所有显示颜色1反转0正常
tft.setRotation(0);
tft.initDMA();
tft.fillScreen(0x0000);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
tft.fillScreen(TFT_BLACK);
}
void loop(){
const uint8_t *Animate_value; //指向关键帧的指针
uint32_t Animate_size; //指向关键帧大小的指针
if (millis() - Amimate_reflash_Time > 30){
Amimate_reflash_Time = millis();
imgAnim(&Animate_value, &Animate_size);
// 必须先使用startWrite,以便TFT芯片选择保持低的DMA和SPI通道设置保持配置
tft.startWrite();
// 在左上角的0,0处绘制图像——在这个草图中,DMA请求在回调tft_output()中处理
TJpgDec.drawJpg(0, 0, Animate_value, Animate_size);
// 必须使用endWrite来释放TFT芯片选择和释放SPI通道
tft.endWrite();
}
}