以下文章来源于嵌入式小书虫 ,作者FledgingSu 支离苏
1、Arm-2D是什么
Arm-2D是arm公司开源的一个嵌入式软件,专门为小资源单片机提供显示驱动,此软件的github 地址如下:
https://github.com/ARM-software/EndpointAI
那它为什么可以为小资源单片机提供显示驱动呢?
这主要是他提供了一个简单通用的PFB技术,这样就可以根据资源的大小灵活的分配显示缓冲区的大小了。
那么PFB是什么呢?
2、部分帧缓存PFB(Partial Frame Buffer)
很多单片机的ram通常都不会很大(4K ~ 32K),然而一个常见的320 * 240 的16位色的LCD屏幕的完整缓存就需要153.6KB RAM,这时候小资源单片机拥有一块完整的缓存就不可能了,部分帧缓存PFB技术就是为了解决这个问题。而Arm-2D的PFB技术是可以支持任意大小的,哪怕只有8 x 8大小的PFB也可以支持任意大小的屏幕,最关键的是用户界面API是不用关心PFB的大小的,Arm-2D都为我们弄好了,我们可以假装拥有完整的Frame Buffer。
3、部署Arm-2D与PFB性能测试
Arm-2D 的PFB技术这么好,还省RAM,那他有什么不足吗?显而易见的就是性能问题,我们用的PFB越小,屏幕刷新的速率就越慢,因为他本身就是用时间来换空间的。好,接下来我们就测试下不同的PFB大小对性能的影响到底有多大。
Arm-2D的部署教程如下:
一网打尽Arm-2D的部署教程
我们的测试硬件如下:
在app_cfg.h中修改PFB的大小,如下:
#define PFB_BLOCK_WIDTH 240
#define PFB_BLOCK_HEIGHT 240
- 我们很容易发现PFB越大,所需的ZI-data越多,FPS越大,性能越好。
- 性能和PFB大小的关系不是成倍的,比如前两行,PFB变为四分之一,而性能却只下降了1FPS。
- 第三行PFB(12 * 12)是整个屏幕的400分之一,性能才下降了一半,是不是感觉PFB技术还是挺不错的。
- 注意,在实际使用时, 要自己根据硬件进行测试,选择合适 的PFB,不仅节省内存,性能也不会下降太多。
4、绘制方块和设置dirty List并显示字符
dirty List脏矩阵列,简单说就是一个由用户指定的刷新区域列表——你让PFB只刷哪些区域,它就只刷哪些区域,也就是局部刷新。因为我们每次不会修改整个屏幕的数据,一般都是局部修改,有了这个dirty List,我们就可以只刷新修改了的区域,这样就可以节省刷屏时间,提升性能。
设置dirty List的程序如下:
void display_task(void)
{
/*! define dirty regions */
||定义一个dirty List链表
IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions, const static)
||添加一个128*64 的区域
ADD_REGION_TO_LIST(s_tDirtyRegions,
.tLocation = {
.iX = 20,
.iY = 20,
},
.tSize = {
.iWidth = 128,
.iHeight = 64,
},
),
||添加第二个128*64 的区域
ADD_REGION_TO_LIST(s_tDirtyRegions,
.tLocation = {
.iX = 20,
.iY = 100,
},
.tSize = {
.iWidth = 128,
.iHeight = 64,
},
),
||添加第三个(也是最后一个)240*64 的区域
/* a region for the status bar on the bottom of the screen */
ADD_LAST_REGION_TO_LIST(s_tDirtyRegions,
.tLocation = {0,170},
.tSize = {
.iWidth = 240,
.iHeight = 64,
},
),
||添加完成调用宏
END_IMPL_ARM_2D_REGION_LIST();
||刷新dirty List区域
//! call partial framebuffer helper service
while(arm_fsm_rt_cpl != arm_2d_helper_pfb_task(
&s_tExamplePFB,
(arm_2d_region_list_item_t *)s_tDirtyRegions));
}
- 注意最后一个区域要用ADD_LAST_REGION_TO_LIST宏添加。
- 函数arm_2d_helper_pfb_task第二个参数传人dirty List就可以局部刷新了。
在区域中显示字符的函数如下:
void example_gui_refresh(const arm_2d_tile_t *ptTile, bool bIsNewFrame)
{
arm_2d_region_t tBox = {
.tLocation = {20,20},
.tSize = {128, 64},
};
static int16_t xx = 0;
||填充黑色背景
arm_2d_rgb16_fill_colour(ptTile, NULL, GLCD_COLOR_BLACK);
||在第一块区域中显示字符
arm_2d_rgb16_fill_colour(ptTile, &tBox, GLCD_COLOR_BLACK);
LCD_donghua();
//! 在box指定的区域填充蓝色,并且使用 50%(128/255)的透明效果
arm_2d_rgb565_fill_colour_with_alpha(
ptTile,
&tBox,
(arm_2d_color_rgb565_t){GLCD_COLOR_BLUE},
58); //!< 透明度
||在第二块区域中显示字符
if (bIsNewFrame) {
tBox.tLocation.iX = 20;
tBox.tLocation.iY = 100;
}
arm_2d_rgb16_fill_colour(ptTile, &tBox, GLCD_COLOR_BLACK);
LCD_donghua2();
||在第三块区域中显示汉字
for(uint8_t i = 0; i < 6; i++){
print_chinese(ptTile,"嵌入式小书虫", xx);
}
xx--;
if(xx < -288){
xx = 239;
}
}
- arm_2d_rgb16_fill_colour函数为填充一个矩形。
- arm_2d_rgb565_fill_colour_with_alpha函数为带透明度填充一个矩形。
首发:裸机思维
作者:FledgingSu 支离苏
专栏推荐文章
如果你喜欢我的思维,欢迎订阅裸机思维