原创 SylixOS framebuffer编程

2015-7-11 11:30 1301 12 12 分类: 软件与OS 文集: SylixOS应用开发

SylixOS和嵌入式Linux的界面编程上Qt是目前最主流的选择,面对复杂多样的嵌入式应用,Qt不见得在任何场合都合适。在很多领域需要轻量级的GUI,比如emwinrttgui等单片机上使用的GUI。还有很多对现实效率要求非常高,而显示界面比较有规律的场合,不需要GUI就可以完成。因此需要了解下framebuffer的编程,以方便满足一下稀奇古怪的需求。

Framebuffer可以简单的理解成一块被映射到LCD显示器的内存区域。向这块内存写入什么数据,就会在LCD上显示什么界面。Framebuffer的概念不仅仅存在于SylixOSLinux等这类操作系统中,在具备LCD控制器的单片机或其他CPU上概念和操作方法基本都一样。如果你是裸奔,只需要拿到framebuffer的指针,进行操作即可。但在SylixOSLinux这种高级操作系统下,还是需要以流程才能够拿到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条评论)

登录后参与讨论
我要评论
0
12
关闭 站长推荐上一条 /2 下一条