Arduino平台基于GFX库的滚动字幕消息显示UI设计(定时器实现刷新)

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.演示视频

多行滚动字幕显示测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值