Arduino方法使用深圳晶彩智能3.5寸彩色屏阅读唐诗-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 770|回复: 0

Arduino方法使用深圳晶彩智能3.5寸彩色屏阅读唐诗

[复制链接]
发表于 2022-9-4 01:23 | 显示全部楼层 |阅读模式
本帖最后由 topdog 于 2022-9-4 08:47 编辑

深圳晶彩智能3.5寸彩色屏采用分辨率480x320彩色液晶屏,驱动芯片是ST7796。唐代张若虚诗作《春江花月夜》是唐诗中最美的,那么用深圳晶彩智能3.5寸彩色屏研究一下中文显示,做一款中文提示器。主要用到的是u8g2针对彩屏文字显示推出的U8g2_for_Adafruit_GFX库和U8g2_for_TFT_eSPI库。通过实验后者速度明显快。


1,,Adafruit ST7796库地址:https://github.com/prenticedavid/Adafruit_ST7796S_kbv


2,U8g2_for_Adafruit_GFX库和U8g2_for_TFT_eSPI库用一个自定义中文字库见附录,非常感谢制作这个开源字库的创客。


3,U8g2_for_Adafruit_GFX库应用程序如下:
[pre]#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
#include "U8g2_for_Adafruit_GFX.h"
#include "gb2312.c"

#define BLACK   0x0000
#define WHITE   0xFFFF

const int TFT_CS = 15;
const int TFT_DC = 2;
const int TFT_MOSI = 13;
const int TFT_MISO = 12;
const int TFT_CLK = 14;
const int TFT_RST = -1;
const int TFT_BL = 27;

extern const uint8_t chinese_gb2312[254049] U8G2_FONT_SECTION("chinese_gb2312");
Adafruit_ST7796S_kbv display = Adafruit_ST7796S_kbv(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

const char c_str[] =
  "Chun Jiang Hua Yue Ye\n\n"
  "春江花月夜\n"
  "唐代张若虚诗作\n"
  "春江潮水连海平,海上明月共潮生。\n"
  "滟滟随波千万里,何处春江无月明!\n"
  "江流宛转绕芳甸,月照花林皆似霰。\n"
  "空里流霜不觉飞,汀上白沙看不见。\n"
  "江天一色无纤尘,皎皎空中孤月轮。\n"
  "江畔何人初见月?江月何年初照人?\n"
  "人生代代无穷已,江月年年望相似。\n"
  "不知江月待何人,但见长江送流水。\n"
  "白云一片去悠悠,青枫浦上不胜愁。\n"
  "谁家今夜扁舟子?何处相思明月楼?\n"
  "可怜楼上月徘徊,应照离人妆镜台。\n"
  "玉户帘中卷不去,捣衣砧上拂还来。\n"
  "此时相望不相闻,愿逐月华流照君。\n"
  "鸿雁长飞光不度,鱼龙潜跃水成文。\n"
  "昨夜闲潭梦落花,可怜春半不还家。\n"
  "江水流春去欲尽,江潭落月复西斜。\n"
  "斜月沉沉藏海雾,碣石潇湘无限路。\n"
  "不知乘月几人归,落月摇情满江树。\n";


char buf[48];      // 每行最多8个汉字,最大字体大小为8*3 = 24

uint8_t total_lines;    // 故事的总台词数
uint8_t i;        // 行循环变量
uint8_t line_cnt;   //要绘制的线条数,通常等于lines_per_draw
uint8_t start_line;   //最上面的可见行,派生自top_window_pos
uint8_t lines_per_draw; //根据字体和显示高度在屏幕上画多少行
uint16_t glyph_height;  // 字形的高度
uint16_t glyph_width;

uint16_t top_window_pos;    // 定义文本中以像素为单位的显示位置
uint16_t total_height;      // 总高度(以像素为单位),由字体高度和total_lines派生
uint16_t top_offset;     // 第一个可见线与显示器之间的偏移量


uint8_t u8x8_GetStringLineCnt(const char *str)
{
  char e;
  uint8_t line_cnt = 1;
  if ( str == NULL )
    return 0;
  for (;;)
  {
    e = *str;
    if ( e == '\0' )
      break;
    str++;
    if ( e == '\n' )
      line_cnt++;
  }
  return line_cnt;
}


const char *u8x8_GetStringLineStart(uint8_t line_idx, const char *str )
{
  char e;
  uint8_t line_cnt = 1;

  if ( line_idx == 0 )
    return str;

  for (;;)
  {
    e = *str;
    if ( e == '\0' )
      break;
    str++;
    if ( e == '\n' )
    {
      if ( line_cnt == line_idx )
        return str;
      line_cnt++;
    }
  }
  return NULL;  /* line not found */
}


void u8x8_CopyStringLine(char *dest, uint8_t line_idx, const char *str)
{
  if ( dest == NULL )
    return;
  str = u8x8_GetStringLineStart( line_idx, str );
  if ( str != NULL )
  {
    for (;;)
    {
      if ( *str == '\n' || *str == '\0' )
        break;
      *dest = *str;
      dest++;
      str++;
    }
  }
  *dest = '\0';
}


void setup() {
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
  display.begin();
  display.setRotation(0);
  display.fillScreen(BLACK);
  u8g2_for_adafruit_gfx.begin(display);                 // connect u8g2 procedures to Adafruit GFX

  u8g2_for_adafruit_gfx.setFont(chinese_gb2312);
  u8g2_for_adafruit_gfx.setForegroundColor(WHITE);      // apply Adafruit GFX color

  /* 按行计算文本的长度 */
  total_lines = u8x8_GetStringLineCnt(c_str);

  /* 得到符号的高度 */
  //glyph_height = u8g2_for_adafruit_gfx.getMaxCharHeight();
  glyph_height = u8g2_for_adafruit_gfx.u8g2.font_info.max_char_height;
  glyph_width = u8g2_for_adafruit_gfx.u8g2.font_info.max_char_width;

  /* 计算文本的像素高度 */
  total_height = (uint16_t)total_lines * (uint16_t)glyph_height;


  /* 计算屏幕上必须画多少条线 */
  lines_per_draw = display.height() / glyph_height;
  lines_per_draw += 3;

  /*从文本的顶部开始 */
  top_window_pos = 0;

  start_line = top_window_pos / glyph_height;
  top_offset = top_window_pos % glyph_height;

  line_cnt = total_lines - start_line;
  if ( line_cnt > lines_per_draw )
    line_cnt = lines_per_draw;

  //display.clearDisplay();                               // 清除graphcis缓冲区
  for ( i = 0; i < line_cnt; i++ )
  {
    /* 将文本的一行复制到本地缓冲区*/
    u8x8_CopyStringLine(buf, i + start_line, c_str);

    /* 绘制本地缓冲区的内容 */   
    u8g2_for_adafruit_gfx.drawUTF8(0, i * glyph_height - top_offset + glyph_height, buf);
  }
}

void loop() {}[/pre]

4,TFT_eSPI 库User_Setup.h设置修改如下:

TFT_eSPI 库自带的字体没有用到,为了节约存储空间加快编译速度,涉及字体的键值对没有被引用。
[pre]#define ST7796_DRIVER  // Full configuration option, define additional parameters below for this display

//#define TFT_RGB_ORDER TFT_RGB  // Colour order Red-Green-Blue
#define TFT_RGB_ORDER TFT_BGR  // Colour order Blue-Green-Red

#define TFT_WIDTH  320
#define TFT_HEIGHT 480

#define TFT_BACKLIGHT_ON HIGH  // Level to turn ON back-light (HIGH or LOW)
#define TFT_MISO 12
#define TFT_MOSI 13 // In some display driver board, it might be written as "SDA" and so on.
#define TFT_SCLK 14
#define TFT_CS   15  // Chip select control pin
#define TFT_DC   2  // Data Command control pin
#define TFT_RST  -1  // Reset pin (could connect to Arduino RESET pin)
#define TFT_BL   27  // LED back-light

#define TOUCH_CS 33     // Chip select pin (T_CS) of touch screen
#define SD_CS    5

#define SPI_FREQUENCY  65000000

// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY  20000000

// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY  2500000  //2500000

#define USE_HSPI_PORT[/pre]

5,U8g2_for_TFT_eSPI库应用程序如下:
[pre]#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"
#include "gb2312.c"

extern const uint8_t chinese_gb2312[254049] U8G2_FONT_SECTION("chinese_gb2312");

TFT_eSPI tft = TFT_eSPI();   // tft instance
U8g2_for_TFT_eSPI u8f;       // U8g2 font instance

const char c_str[] =
  "Chun Jiang Hua Yue Ye\n\n"
  "春江花月夜\n"
  "唐代张若虚诗作\n"
  "春江潮水连海平,海上明月共潮生。\n"
  "滟滟随波千万里,何处春江无月明!\n"
  "江流宛转绕芳甸,月照花林皆似霰。\n"
  "空里流霜不觉飞,汀上白沙看不见。\n"
  "江天一色无纤尘,皎皎空中孤月轮。\n"
  "江畔何人初见月?江月何年初照人?\n"
  "人生代代无穷已,江月年年望相似。\n"
  "不知江月待何人,但见长江送流水。\n"
  "白云一片去悠悠,青枫浦上不胜愁。\n"
  "谁家今夜扁舟子?何处相思明月楼?\n"
  "可怜楼上月徘徊,应照离人妆镜台。\n"
  "玉户帘中卷不去,捣衣砧上拂还来。\n"
  "此时相望不相闻,愿逐月华流照君。\n"
  "鸿雁长飞光不度,鱼龙潜跃水成文。\n"
  "昨夜闲潭梦落花,可怜春半不还家。\n"
  "江水流春去欲尽,江潭落月复西斜。\n"
  "斜月沉沉藏海雾,碣石潇湘无限路。\n"
  "不知乘月几人归,落月摇情满江树。\n";

char buf[48];      // there are at most 8 chinese glyphs per line, max buf size is 8*3 = 24

uint8_t total_lines;    // the total number of lines in the story
uint8_t i;        // loop variable for the lines
uint8_t line_cnt;   // number of lines to draw, usually equal to lines_per_draw
uint8_t start_line;   // topmost visible line, derived from top_window_pos
uint8_t lines_per_draw; // how many lines to draw on the screen, derived from font and display height
uint16_t glyph_height;  // height of the glyphs
uint16_t glyph_width;

uint16_t top_window_pos;    // defines the display position in pixel within the text
uint16_t total_height;      // total height in pixel, derived from font height and total_lines
uint16_t top_offset;     // offset between the first visible line and the display


uint8_t u8x8_GetStringLineCnt(const char *str)
{
  char e;
  uint8_t line_cnt = 1;
  if ( str == NULL )
    return 0;
  for(;;)
  {
    e = *str;
    if ( e == '\0' )
      break;
    str++;
    if ( e == '\n' )
      line_cnt++;
  }
  return line_cnt;
}

/*
    Assumes strings, separated by '\n' in "str".
    Returns the string at index "line_idx". First strng has line_idx = 0
    Example:
      Returns "xyz" for line_idx = 1 with str = "abc\nxyz"
    Support both UTF8 and normal strings.
*/
const char *u8x8_GetStringLineStart(uint8_t line_idx, const char *str )
{
  char e;
  uint8_t line_cnt = 1;
  
  if ( line_idx == 0 )
    return str;

  for(;;)
  {
    e = *str;
    if ( e == '\0' )
      break;
    str++;
    if ( e == '\n' )
    {
      if ( line_cnt == line_idx )
  return str;
      line_cnt++;
    }
  }
  return NULL;  /* line not found */
}

/* copy until first '\n' or '\0' in str */
/* Important: There is no string overflow check, ensure */
/* that the destination buffer is large enough */
void u8x8_CopyStringLine(char *dest, uint8_t line_idx, const char *str)
{
  if ( dest == NULL )
    return;
  str = u8x8_GetStringLineStart( line_idx, str );
  if ( str != NULL )
  {
    for(;;)
    {
      if ( *str == '\n' || *str == '\0' )
  break;
      *dest = *str;
      dest++;
      str++;
    }
  }
  *dest = '\0';
}


void setup() {
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  u8f.begin(tft);                         // connect u8g2 procedures to TFT_eSPI

  u8f.setFont(chinese_gb2312);
  u8f.setForegroundColor(TFT_WHITE);      // apply color
  
  /* calculate the length of the text in lines */
  total_lines = u8x8_GetStringLineCnt(c_str);
  
  /* get the height of the glyphs */
  //glyph_height = u8f.getMaxCharHeight();
  glyph_height = u8f.u8g2.font_info.max_char_height;
  glyph_width = u8f.u8g2.font_info.max_char_width;

  /* calculate the height of the text in pixel */
  total_height = (uint16_t)total_lines * (uint16_t)glyph_height;
  

  /* calculate how many lines must be drawn on the screen */
  lines_per_draw = tft.height() / glyph_height;
  lines_per_draw += 2;

  /* start at the top of the text */
  top_window_pos = 0;

  start_line = top_window_pos / glyph_height;
  top_offset = top_window_pos % glyph_height;
  
  line_cnt = total_lines - start_line;
  if ( line_cnt > lines_per_draw )
    line_cnt = lines_per_draw;

  for( i = 0; i < line_cnt; i++ )
  {
    /* copy a line of the text to the local buffer */
    u8x8_CopyStringLine(buf, i+start_line, c_str);
   
    /* draw the content of the local buffer */   
    u8f.drawUTF8(0, i*glyph_height-top_offset +glyph_height, buf);   
  }  
}

void loop() {}[/pre]

6,效果图:
微信图片_20220904083706.jpg


7,附件在这里呀!
tangshi.rar (446.62 KB, 下载次数: 0)










































您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 01:23 , Processed in 0.119699 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表