1.优化
基于之前发布文章代码修改优化,具体细节前往->Arduino平台基于GFX库的滚动字幕消息显示UI设计 查看
使用硬件定时器实现滚动字幕的刷新,不影响其他代码,并且可以自定义同时刷新多个数据,不同长度的字符串之间的刷新互不影响
2.代码
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define TFT_CS 14 // 请替换为您的CS引脚号
#define TFT_DC 27 // 请替换为您的DC引脚号
#define TFT_RST 5 // 请替换为您的RST引脚号
//#define TFT_SCK 18 // 请替换为您的SCK引脚号
//#define TFT_MOSI 23 // 请替换为您的MOSI引脚号
//已经默认配置
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);//创建显示屏对象并初始化
hw_timer_t * timer = NULL; // 创建一个定时器对象
#define BACKGROUND_COLOUR ST7735_BLACK //背景颜色
#define RECT1_COLOUR ST7735_RED
#define TEXT1_COLOUR ST7735_GREEN
#define LINE1_COLOUR ST7735_RED
#define TEXT2_COLOUR ST7735_BLUE
#define RECT2_COLOUR ST7735_RED
#define TEXT3_COLOUR ST7735_GREEN
#define TEXT4_COLOUR ST7735_BLUE
//定义使用的颜色
#define SHOWDELAY_TIME 500 //字幕滚动速度
#define MAX_TEXT_COUNT 30 //输入文本最大字符数
#define MAX_SHOW_COUNT 12 //最大同时显示字符数
#define MAX_SHOW_STRING 6 //最大同时刷新字符串数量
int textShowX[MAX_SHOW_STRING] = {0};
int textShowY[MAX_SHOW_STRING] = {0};
int showCount[MAX_SHOW_STRING] = {0};//实际显示数量
int maxCount[MAX_SHOW_STRING] = {0};//需要显示数量
char textShowString[MAX_SHOW_STRING][MAX_SHOW_COUNT + 1] = {"null"} ;//实际显示的字符串
char textMaxString[MAX_SHOW_STRING][MAX_TEXT_COUNT] = {"null"};//需要显示的字符串
int showFlag[MAX_SHOW_STRING] = {0};//显示刷新标志位
void IRAM_ATTR onTimer() {
// 在定时器中断服务程序中更新屏幕显示
//开启滚动显示
static int i[MAX_SHOW_STRING] = {0};
for(int j = 0; j < MAX_SHOW_STRING; j++){
if(showFlag[j] == 1){//需要显示
if(i[j] <= maxCount[j] - showCount[j]){//滚动字幕显示
tft.fillRect(textShowX[j], textShowY[j], showCount[j] * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
strncpy(textShowString[j], textMaxString[j] + i[j],showCount[j]);//从textMaxString[j]的第i[j]个字符开始,拷贝showCount[j]个字符到textShowString[j]
textShowString[j][showCount[j]] = '\0'; // 添加字符串结束符
tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
tft.setTextSize(1);//设置字体大小
tft.setCursor(textShowX[j],textShowY[j]);//设置显示位置
tft.print(textShowString[j]);//显示Text4 Recived data!
i[j] += 1;
}
else{//滚动字幕显示结束 显示前showCount[j]个字符
tft.fillRect(textShowX[j], textShowY[j], showCount[j] * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
strncpy(textShowString[j], textMaxString[j],showCount[j]);//将textMaxString[j]的前showCount[j]个字符,拷贝到textShowString[j]
textShowString[j][showCount[j]] = '\0'; // 添加字符串结束符
tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
tft.setTextSize(1);//设置字体大小
tft.setCursor(textShowX[j],textShowY[j]);//设置显示位置
tft.print(textShowString[j]);//显示Text4 Recived data!
i[j] = 0;
showFlag[j] = 0;
//timerEnd(timer); // 关闭定时器
}
}
}
}
void setup() {
// 配置硬件定时器
timer = timerBegin(0, 80, true); // 使用定时器0,分频器80,计数上升沿触发中断
timerAttachInterrupt(timer, &onTimer, true); // 将中断服务程序与定时器关联
timerAlarmWrite(timer, SHOWDELAY_TIME * 1000, true); // 设置定时器触发时间为SHOWDELAY_TIME*1000(单位:微秒)默认为500us*1000 = 0.5s
//timerAlarmEnable(timer); // 启用定时器
messageShowUI(0,113 - 13 * 2,"txt1","txet2","3","text4");
messageShowUI(0,113 - 13 * 1,"From","ASRPRO","R","Recived data:Hello World!");
messageShowUI(0,113,"Goal","Fan","S","Send data:Hello World!");
}
void loop() {
// 在这里可以添加更多的显示内容或图形
}
void messageShowUI(const int x,const int y,char text1[],char text2[],char text3[],char text4[]){
const int RectX = x;//基准坐标 (矩形左上角)
const int RectY = y;//基准坐标
const int RectWight = 160;//宽160
const int RectHight = 14;//高14
const int Rect1x = RectX;//矩形框1x坐标
const int Rect1y = RectY;//矩形框1y坐标
const int Rect1w = RectWight - RectX;//矩形框1宽度
const int Rect1h = RectHight;//矩形框1高度
//tft.drawRect(Rect1x,Rect1y,Rect1w,Rect1h,RECT1_COLOUR);//绘制矩形框1 外部包围
const int Text1x = Rect1x +3;//Text1x坐标
const int Text1y = Rect1y +3;//Text1y坐标
const int Text1C = 4;//Text1字符数量
char Text1String[Text1C + 1];//Text1字符数组
strncpy(Text1String, text1,Text1C);//从text1拷贝Text1C个字符到Text1String
Text1String[Text1C] = '\0'; // 添加字符串结束符
const int Text1Size = 1;
const int Line1x = Text1x + Text1C * 6 + 3;//字符大小为6*8
const int Line1y = RectY;
const int Line1h = RectHight;
const int Text2x = Line1x + 3;//Text2x坐标
const int Text2y = Text1y;//Text2y坐标
const int Text2C = 6 ;//Text2字符数量
const int Text2Size = 1;
char Text2String[Text2C + 1];//Text2字符数组
strncpy(Text2String, text2,Text2C);//从text2拷贝Text2C个字符到Text2String
Text2String[Text2C] = '\0'; // 添加字符串结束符
const int Rect2x = Text2x + Text2C * 6 + 1;//矩形框2x坐标
const int Rect2y = RectY;//矩形框2y坐标
const int Rect2w = 14;//矩形框2宽度
const int Rect2h = 14;//矩形框2高度
const int Text3x = Rect2x + 5;//Text3x坐标
const int Text3y = Text1y;//Text3y坐标
const int Text3C = 1;//Text3字符数量
const int Text3Size = 1;
char Text3String[Text3C + 1];//Text3字符数组
strncpy(Text3String, text3,Text3C);//从text3拷贝Text3C个字符到Text3String
Text3String[Text3C] = '\0'; // 添加字符串结束符
const int Text4x = Rect2x + Rect2w + 3;//Text4x坐标
const int Text4y = Text1y ;//Text4y坐标
const int Text4Size = 1;
const int Text4C = (159 - Text4x)/6 ;//剩余空间可显示字符数量(以0,0作为起点最多显示12个字符)字符大小6*8
char Text4String[Text4C + 1];//Text4字符数组
int Text4Length = 0;//传入需要显示的字符数量
while (text4[Text4Length] != '\0') {//动态分配的数组不能使用sizeof来计算数组大小
Text4Length++;
}
static bool flag = true;
if(flag){
tft.initR(INITR_BLACKTAB); // 使用适当的初始化参数
tft.setRotation(1); // 设置显示方向,1表示顺时针旋转90度
tft.fillScreen(BACKGROUND_COLOUR);//设置背景颜色
flag = false; //初始化完成改变标志位防止重复初始化
}
tft.drawRect(Rect1x,Rect1y,Rect1w,Rect1h,RECT1_COLOUR);//绘制矩形框1:整体框架
tft.setTextColor(TEXT1_COLOUR);//设置文字颜色
tft.setTextSize(Text1Size);//设置字体大小
tft.setCursor(Text1x,Text1y);//设置起始位置
tft.print(Text1String);//显示Text1 From
tft.drawFastVLine(Line1x,Line1y,Line1h,LINE1_COLOUR);//绘制Text1后竖线
tft.setTextColor(TEXT2_COLOUR);//设置文字颜色
tft.setTextSize(Text2Size);//设置字体大小
tft.setCursor(Text2x,Text2y);//设置起始位置
tft.print(Text2String);//显示Text2 ASRPRO
//tft.drawFastVLine(Line2x,Line2y,Line2h,LINE2_COLOUR);//绘制Text2后竖线
tft.fillRect(Rect2x,Rect2y,Rect2w,Rect2h,RECT2_COLOUR);//绘制矩形框2:Text3包围框
tft.setTextColor(TEXT3_COLOUR);//设置文字颜色
tft.setTextSize(Text3Size);//设置字体大小
tft.setCursor(Text3x,Text3y);//设置起始位置
tft.print(Text3String);//显示Text3 R
tft.setTextWrap(false);//关闭超出范围自动换行 实现滚动字幕显示
if(Text4Length > Text4C){//需要显示的数据数量大于剩余空间可显示字符数量
//传递参数
for(int i = 0; i < MAX_SHOW_STRING ; i++){
if(showFlag[i] == 0){
showFlag[i] = 1;//标记已使用
showCount[i] = Text4C;//可显示的字符数
maxCount[i] = Text4Length;//需要显示的字符数
textShowX[i] = Text4x;
textShowY[i] = Text4y;
strcpy(textMaxString[i],text4);//传递需要显示的字符串
timerAlarmEnable(timer); // 启用定时器
//直接静态显示
strncpy(Text4String, text4,Text4C);//从text4拷贝Text4C个字符到Text4String
Text4String[Text4C] = '\0'; // 添加字符串结束符
tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
tft.setTextSize(Text4Size);//设置字体大小
tft.setCursor(Text4x,Text4y);//设置起始位置
tft.print(Text4String);//显示Text4 Recived data!
return ;//找到可显示位置即退出循环
}
}
}
else{//直接静态显示
strncpy(Text4String, text4,Text4C);//从text4拷贝Text4C个字符到Text4String
Text4String[Text4C] = '\0'; // 添加字符串结束符
tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
tft.setTextSize(Text4Size);//设置字体大小
tft.setCursor(Text4x,Text4y);//设置起始位置
tft.print(Text4String);//显示Text4 Recived data!
}
}
3.演示视频
多行滚动字幕显示测试