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

topdog 发表于 2022-9-4 01:23

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

本帖最后由 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库应用程序如下:
#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 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;      // 每行最多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() {}

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

TFT_eSPI 库自带的字体没有用到,为了节约存储空间加快编译速度,涉及字体的键值对没有被引用。
#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_WIDTH320
#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_FREQUENCY65000000

// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY20000000

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

#define USE_HSPI_PORT

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

extern const uint8_t chinese_gb2312 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;      // 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() {}

6,效果图:



7,附件在这里呀!











































页: [1]
查看完整版本: Arduino方法使用深圳晶彩智能3.5寸彩色屏阅读唐诗