一段小修改,让我的LCD显示字符速率翻倍

  • 02/26 11:20
  • 1136

1、前言

之前曾经介绍过在TFTLCD显示屏中使用DMA传输可以大幅度的提升传输效率。

但是当时只修改了原先全屏刷新的算法以及图片刷新的LCD算法。

今天测试在显示字符的时候,依旧效率低下。

于是自己查看了一下字符显示的算法,尝试能不能提高一下效率。

2、字符显示

void ST7789_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor){  uint32_t i, b, j;  ST7789_Select();  ST7789_SetAddressWindow(x, y, x + font.width - 1, y + font.height - 1);  for (i = 0; i < font.height; i++) {    b = font.data[(ch - 32) * font.height + i];    for (j = 0; j < font.width; j++) {      if ((b << j) & 0x8000) {        uint8_t data[] = {color >> 8, color & 0xFF};        ST7789_WriteData(data, sizeof(data));      }      else {        uint8_t data[] = {bgcolor >> 8, bgcolor & 0xFF};        ST7789_WriteData(data, sizeof(data));      }    }  }  ST7789_UnSelect();}

ST7789_WriteData这条命令是利用DMA传输的,因此影响效率的主要原因是显示字符算法的效率。

函数参数传递进来的是一个字符、坐标、字体定义、前景色和背景色,我们逐行来分析这个函数。

ST7789_Select();ST7789_SetAddressWindow(x, y, x + font.width - 1, y + font.height - 1);

该部分用于SPI通讯选中,并且设置显示窗口的地址。

  for (i = 0; i < font.height; i++) {    for (j = 0; j < font.width; j++) {      }    }  }

两个for循环代表着这个函数采用的逐行逐列刷新像素的方式将字符描出来。

if ((b << j) & 0x8000) {   uint8_t data[] = {color >> 8, color & 0xFF};   ST7789_WriteData(data, sizeof(data));}else {   uint8_t data[] = {bgcolor >> 8, bgcolor & 0xFF};   ST7789_WriteData(data, sizeof(data));}

这段在显示每个像素点数据的时候,利用将字模数据的每一行(存放在变量b)判断每个像素点的掩膜值来确定这个像素是显示前景色还是背景色。

当然这里最大的一个问题还是,该方法是每个像素逐点刷新的,会频繁的调用ST7789_WriteData这个命令。

3、优化方式

我们注意到,SPI的传输是可以多个数据包一起发送的,因此我们尝试修改一下刷新方式,可以创建一个缓存区存放一个字符区域的整体内容(前景色背景色处理完之后的数据),之后利用硬件SPI统一发送,而不是像原先那样子对每个字符。

void ST7789_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor){    uint32_t i, j;    uint16_t *pixel_buffer;  // 缓冲区,用于存储像素数据    uint16_t width = font.width;    uint16_t height = font.height;    // 计算像素数据缓冲区的大小:每像素 2 字节(16 位颜色),宽 × 高    uint16_t buffer_size = width * height;    uint8_t buffer[2 * buffer_size];  // 2 × 16-bit = 32-bit per pixel    // 填充缓冲区    for (i = 0; i < height; i++)     {        uint16_t row_data = font.data[(ch - 32) * height + i];        for (j = 0; j < width; j++)         {            uint32_t index = (i * width + j) * 2;            if ((row_data << j) & 0x8000)             {                buffer[index] = color >> 8;                buffer[index + 1] = color & 0xFF;            }             else             {                buffer[index] = bgcolor >> 8;                buffer[index + 1] = bgcolor & 0xFF;            }        }    }
    // 写入数据    ST7789_Select();    ST7789_SetAddressWindow(x, y, x + width - 1, y + height - 1);    ST7789_WriteData(buffer, sizeof(buffer));    ST7789_UnSelect();}

这种办法虽然会牺牲临时变量,需要更多的空间,但是实际上使用中极大的提升了刷新速度。

人工客服
(售后/吐槽/合作/交友)