热度 12
2015-7-11 11:30
1301 次阅读|
0 个评论
在 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 = ((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 = colidx; } break; } }