在SylixOS和嵌入式Linux的界面编程上Qt是目前最主流的选择,面对复杂多样的嵌入式应用,Qt不见得在任何场合都合适。在很多领域需要轻量级的GUI,比如emwin、rttgui等单片机上使用的GUI。还有很多对现实效率要求非常高,而显示界面比较有规律的场合,不需要GUI就可以完成。因此需要了解下framebuffer的编程,以方便满足一下稀奇古怪的需求。
Framebuffer可以简单的理解成一块被映射到LCD显示器的内存区域。向这块内存写入什么数据,就会在LCD上显示什么界面。Framebuffer的概念不仅仅存在于SylixOS、Linux等这类操作系统中,在具备LCD控制器的单片机或其他CPU上概念和操作方法基本都一样。如果你是裸奔,只需要拿到framebuffer的指针,进行操作即可。但在SylixOS、Linux这种高级操作系统下,还是需要以流程才能够拿到framebuffer的指针。
1、打开framebuffer设备
2、获取framebuffer的一些参数,毕竟需要考虑程序的适应性,所以里面的参数应该能根据不同的LCD显示进行调整
3、为framebuffer分配内存,获取内存操作的地址指针
4、通过指针想内存写入数据,实现显示
为了便于使用,这里粘贴出完整的源码只需要拷贝、粘贴就可以使用了
int main (VOID) { INT ix; INT iFbFd; LW_GM_SCRINFO scrInfo; LW_GM_VARINFO varInfo; INT iError; VOID *pvFrameBuffer; /* 打开fb设备 */ iFbFd = open("/dev/fb0", O_RDWR, 0666); if (iFbFd < 0) { return 0; } /* 打开失败,则返回 */ /* 获取fb的大小等参数 */ iError = ioctl(iFbFd, LW_GM_GET_SCRINFO, &scrInfo); if (iError < 0) { close(iFbFd); return 0; } /* 参数获取失败返回*/ /* 获取fb行列信息等 */ iError = ioctl(iFbFd, LW_GM_GET_VARINFO, &varInfo); if (iError < 0) { close(iFbFd); return 0; } /*打开失败,则返回 */ /* 为framebuffer分配内存 并初始化 */ pvFrameBuffer = mmap(LW_NULL, scrInfo.GMSI_stMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, iFbFd, 0); if (pvFrameBuffer == MAP_FAILED) /* 内存分配失败失败,则返回 */ { close(iFbFd); return 0; } lib_memset(pvFrameBuffer,0xFF,scrInfo.GMSI_stMemSize); /*屏幕全白 */ lib_memset(pvFrameBuffer,0x00,scrInfo.GMSI_stMemSize/2);/*屏幕半黑 */ /* 绘制一条红色直线,这里调用了绘制点的函数 */ for(ix = 0;ix < varInfo.GMVI_ulXRes;ix++) { __lcdDrawPixel(pvFrameBuffer, &scrInfo, &varInfo,ix,50,0x00FF0000); } sleep(30); //延时30s后,程序退出 /* 程序退出时,删除占用的相关资源 */ munmap(pvFrameBuffer, scrInfo.GMSI_stMemSize); close(iFbFd); return 0; } |
绘制点的函数如下,理论上只有能够绘制一个点,就能够绘制任意界面,为了方便其他绘制调用,这里将绘制点的函数进行了封装。如果您使用的是ucos这类操作系统,这个函数稍微修改下就可以使用。
VOID __lcdDrawPixel (VOID *pvFrameBuffer, LW_GM_SCRINFO *scrInfo, LW_GM_VARINFO *varInfo, int x, int y, unsigned colidx) { /* 判断给出的绘制点坐标是否在LCD显示区域内 */ if ((x < 0) || (x >= varInfo->GMVI_ulXResVirtual) || (y < 0) || (y >= varInfo->GMVI_ulYResVirtual)) { return; } /*判断framebuffer一个像素对应的内存大小,这里只有2Byte和4Byte两种 */ switch (varInfo->GMVI_ulBitsPerPixel) { case 16: { UINT16 *pusFrameBuffer; pusFrameBuffer = (UINT16 *)((UINT8 *)pvFrameBuffer + y * scrInfo->GMSI_stMemSizePerLine); pusFrameBuffer[x] = ((colidx & 0xFF0000) >> 16 >> 3 << 11) | ((colidx & 0x00FF00) >> 8 >> 2 << 5) | ((colidx & 0x0000FF) >> 0 >> 3 << 0); } break; case 24: case 32: { UINT32 *puiFrameBuffer; puiFrameBuffer = (UINT32 *)((UINT8 *)pvFrameBuffer + y * scrInfo->GMSI_stMemSizePerLine); puiFrameBuffer[x] = colidx; } break; } } |
文章评论(0条评论)
登录后参与讨论