验证RA8875的硬件绘图与使用MCU软件绘图的速度差异

RA8875是一块LCD驱动芯片,支持RGB接口的LCD液晶屏,提供8080时序的MCU接口; RA8875内置了2D硬件加速功能,可以实现硬件绘制矩形,直线等功能;

本次测试就是为了验证RA8875的硬件绘图与使用MCU软件绘图的速度差异。

硬件环境:

CPU:STM32F407VE@168MHz

LCD:480x272x16bpp

测试方法:

计算1秒内填充整个屏幕的次数(FPS)

测试结果:

填充方式帧率(FPS)速度(Pixel/s)备注
软件逐点填充6783360
软件逐行填充638225280
软件矩形填充699008640
硬件逐行填充120126242560先绘图,等待空闲后退出函数
硬件逐行填充220727025920进入函数先等待空闲,再绘图
硬件矩形填充131240734720先绘图
硬件矩形填充231541126400先等待
emWin(5.30)12616441000自带驱动,支持硬件加速
FastGUI20126242560驱动为硬件逐行填充2
FlatGUI32442301440

说明:RA8875的硬件绘制功能,需要读取状态寄存器的BIT7,

如果该位为1说明硬件绘制没有完成,不能进行其它绘制,否则屏幕会显示不正常。

“先绘图”是指先发送硬件绘图指令,然后读取状态寄存器,等待BIT7清0后退出函数;

“先等待”是指先读取状态寄存器,等待BIT7清0后,再发送绘图指令;

测试结论:

由此可见使用RA8875的硬件绘图有着非常明显的速度优势,比使用软件绘图快了3-4倍。

附上RA8875的2D加速代码:

static void lcd_set_rect(int x1, int y1, int x2, int y2)
{
    //窗口起始位置
    lcd_command(0x30, x1);
    lcd_command(0x31, (x1 >> 8) & 0x3);
    lcd_command(0x32, y1);
    lcd_command(0x33, (y1 >> 8) & 0x01);

    //窗口结束位置
    lcd_command(0x34, x2);
    lcd_command(0x35, (x2 >> 8) & 0x03);
    lcd_command(0x36, y2);
    lcd_command(0x37, (y2 >> 8) & 0x01);
}

static void lcd_wseek(int x, int y)
{
    lcd_command(0x46, x);
    lcd_command(0x47, x >> 8);

    lcd_command(0x48, y);
    lcd_command(0x49, y >> 8);
}

static void lcd_rseek(int x, int y)
{
    lcd_command(0x4A, x);
    lcd_command(0x4B, x >> 8);

    lcd_command(0x4C, y);
    lcd_command(0x4D, y >> 8);
}

void lcd_set_pixel(int x, int y, int pixel)
{
    lcd_wait_ram();
    lcd_wseek(x, y);
    lcd_command(0x02, pixel);
}

int lcd_get_pixel(int x, int y)
{
    int data;
    lcd_rseek(x, y);
    LCD_CMD = 0x02;
    data = LCD_DATA;  //dummy read
    data = LCD_DATA;
    return data;
}

//BTE
static void bte_set_rect(int x, int y, int w, int h)
{
    lcd_command(0x58, x);
    lcd_command(0x59, (x >> 8) & 0x03);
    lcd_command(0x5A, y);
    lcd_command(0x5B, (y >> 8) & 0x01);

    lcd_command(0x5C, w);
    lcd_command(0x5D, (w >> 8) & 0x03);
    lcd_command(0x5E, h);
    lcd_command(0x5F, (h >> 8) & 0x03);
}

static void bte_set_bkcolor(int color)
{
    lcd_command(0x60, (color >> 11) & 0x1F);
    lcd_command(0x61, (color >> 5) & 0x3F);
    lcd_command(0x62, color & 0x1F);
}

static void bte_set_fgcolor(int color)
{
    lcd_command(0x63, (color >> 11) & 0x1F);
    lcd_command(0x64, (color >> 5) & 0x3F);
    lcd_command(0x65, color & 0x1F);
}

static void bte_set_colorkey(int color)
{
    lcd_command(0x67, (color >> 11) & 0x1F);
    lcd_command(0x68, (color >> 5) & 0x3F);
    lcd_command(0x69, color & 0x1F);
}

static void bte_open(int mode)
{
    lcd_command(0x51, lcd_rop_mask | mode);
    lcd_command(0x50, 0x80);
}

static void g2d_set_rect(int x, int y, int x2, int y2)
{
    lcd_command(0x91, x&0xFF);
    lcd_command(0x92, (x>>8)&0xFF);
    lcd_command(0x93, y&0xFF);
    lcd_command(0x94, (y>>8)&0xFF);
    
    lcd_command(0x95, x2&0xFF);
    lcd_command(0x96, (x2>>8)&0xFF);
    lcd_command(0x97, y2&0xFF);
    lcd_command(0x98, (y2>>8)&0xFF);
}

static void g2d_command(uint8_t cmd)
{
    lcd_command(0x90, cmd);
}

void lcd_set_rop(int mode)
{
    lcd_rop_mask = (mode & 0x0F) << 4;
}

void bte_fill_rect(int x, int y, int w, int h, int color)
{
    lcd_wait_bte();
    bte_set_rect(x, y, w, h);
    bte_set_fgcolor(color);
    bte_open(0x0C);
}

void g2d_fill_rect(int x, int y, int x2, int y2, int color)
{
    lcd_wait_ram();
    bte_set_fgcolor(color);
    g2d_set_rect(x, y, x2, y2);
    g2d_command(0xB0);
}