最近脑抽了,买了块开发板rp2040,再加上一块240*240的屏幕、传感器小零件来玩。屏幕驱动是St7789的。
找了个驱动,看了驱动代码,核心就是实现了如何定位一个像素点,然后写像素点。弄好后跑起来了,然而。。。。那速度实在感人。心想,不应该啊,像lvgl之类的图列库,如果是这么驱动屏幕的话,怎么玩得起?
主要代码:
// 写数据到屏幕
void st7789_write(const void* data, size_t len)
{
if (!st7789_data_mode) {
st7789_ramwr();
if (st7789_cfg.gpio_cs > -1) {
spi_set_format(st7789_cfg.spi, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
} else {
spi_set_format(st7789_cfg.spi, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
}
st7789_data_mode = true;
}
spi_write16_blocking(st7789_cfg.spi, data, len / 2);
}
// 写像素
void st7789_put(uint16_t pixel)
{
st7789_write(&pixel, sizeof(pixel));
}
// 列范围设定
void st7789_caset(uint16_t xs, uint16_t xe)
{
uint8_t data[] = {
xs >> 8,
xs & 0xff,
xe >> 8,
xe & 0xff,
};
// CASET (2Ah): Column Address Set
st7789_cmd(0x2a, data, sizeof(data));
}
// 行范围设定
void st7789_raset(uint16_t ys, uint16_t ye)
{
uint8_t data[] = {
ys >> 8,
ys & 0xff,
ye >> 8,
ye & 0xff,
};
// RASET (2Bh): Row Address Set
st7789_cmd(0x2b, data, sizeof(data));
}
// 定位坐标
void st7789_set_cursor(uint16_t x, uint16_t y)
{
st7789_caset(x, st7789_width);
st7789_raset(y, st7789_height);
}
于是找了数据手册,研究了代码,才清楚应该是使用方式错了。如果真的是使用st7789_set_cursor 和 st7789_put 两个函数的话,真的是跑不起,每个像素都通过st7789_set_cursor来定位的话,大量时间都花费在定位上了。
改个方式吧,于是将st7789驱动包装了一下,思路就是通过 st7789_caset 和 st7789_raset 设定了一个全屏的更新范围,再将全屏的数据一次性写入屏幕。首先,给屏幕准备数据内存,根据尺寸和颜色,内存大小应该是 240*240*2 = 115200 字节。也就是大概115K。用malloc分配内存。
包装完代码后,跑起来了,果然在这种情况下,屏幕的刷新无比顺滑,像素的写入,都事先写在准备好的内存中,再复杂的图像,也丝毫没有卡顿。不过问题来了。。。。屏幕更新只更新到了200多行,丢失了10多行左右。检查了代码,始终没有发现什么问题。
难道是malloc有问题?于是,试一下,直接用 uint8_t buf[115200] 方式暴力分配块内存,编译。。。。。报错了!关键错误信息: section `.bss' will not fit in region `RAM' 。参考了些资料猜测应该是可怜的pico内存太小的原因,没办法连续分配那么大的内存。
继续改,内存拆开两块,给它两个 uint8_t buf[57600],加起来也是115200大小,但绘制屏幕的时候,分两步,先绘制上半屏,再绘制下半屏。
改完再跑,果然没问题了,屏幕刷新仍然无比顺滑,而且不会丢失部分屏幕。根据丢失的那部分屏幕大小,预计能连续分配的最大内存,应该也就100K左右。
屏幕更新的问题解决了,但想了想,发现了个更严肃的问题:假如我要在屏幕上绘制个背景图,在背景图上再绘制些内容,怎么办?除了原先屏幕内存已经占了115K,还得再准备个115K的内存来放背景图,可。。。。pico的RAM总共只有256K,这还能玩得起??之前曾经试过移植lvgl到pico上,但编译的时候也给了个section `.bss' will not fit in region `RAM' 的错误提示。看来还是内存太小的原因,瞬间无比嫌弃这块开发板起来。
看来这玩意,还不配玩lcd屏幕,还是搞块oled来玩吧
另外:lvgl移植到pico,我真是试了很多次都没成功,但摆毒到有能移植成功的文章,我到底是哪步错了?有没有大神指点一下。