FrameBuffer 原理、环境搭建、例子程序--大总结

来源:互联网 发布:voa在线收听软件 编辑:程序博客网 时间:2024/05/29 15:10

      首先来说,FrameBuffer能做什么?

      答:FrameBuffer可以在没有起动图形介面的系统上向屏幕上输出东西(自己的理解),最简单的例子就是,我们在字符介面上,也可以通过FrameBuffer在屏幕上显示美丽的图片、工整的文字。

一、原理

       官方的意思我也不太懂,以下是我在开发过程中,自己对FrameBuffer的理解,有不到之处,请大家多多指教。

       FrameBuffer 就像一张画布,使用什么样子的画笔,如何画画,还需要你自己动手完成。

       在我看来FrameBuffer其实就是一个设备文件,他一般存在/dev/这个目录下,第一个frambBuffer设备的文件名是fb0,即所在位置为:/dev/fb0,但是有人就问了,我的dev目录下怎么没有这个文件呢,别着急,下面会提到环境搭建,等环境搭起来之后,就有了。

        在编程人员眼里看来,FrameBuffer就是一块内存,而且是一块线性的内存,我们有个指针指向这块内存,想往哪个地放写数据就往哪个地方写数据。当我们打开FrameBuffer这个设备之后,得到的是一个整型的一维数组,每一个元素对应着屏幕上的一个象素点,如果我们的屏幕是1024*768的,那么我们应该得到一个长度为1024*768=786432的一维数组,在这个数组中,前1024个元素对应着屏幕上的第一行象素,接下来的1024个元素对应着屏幕上的第二行象素,以此类推....好了,如果上面的原理你理解了,那么不用说,你应该知道FrameBuffer怎么用了,我想让屏幕上的那个象素显示,就让哪个象素显示,这样,我们想显示汉字、图片也就没什么问题了,基本原理说白了,跟大街上的LED发光字,没有什么区别。


二、环境搭建

     在这里只需要四步,通过网上查资料自己总结了,具体每一步是什么含义,在这里就不多说了,正常情况下,只要照着做,就不会出问题!(ubuntu环境下)

    1打开/etc/initramfs-tools/modules文件,在末尾加上:fbconvesafb

   2、.打开/etc/modprobe.d/blacklist-framebuffer.conf,找到“blacklist vesafb”一行,在这一行前面加上“#”把它注释掉。

   3、打开/boot/grub/menu.lst,找到相应的kernel一行,加上 vga参数。

       例如我把分辨率设置为1024x768,对应的vga数值就是0x317。在我的机子上没有这个文件,是在/boot/grub /grub.cfg文件中修改的linux /boot/vmlinuz-2.6.22-14-generic root=UUID=3c51a0d7-d373-473b-830e-225b6d7aafdf ro quiet splash vga=0x317

   4、最后执行:sudo update-initramfs -u更新,重启一下。如果你禁用了图形界面登陆,应该就能看到漂亮一些的字符界面了;如果没有禁用,可以在桌面环境中按Ctrl+Alt+F1 ~ F6看看效果,按Ctrl+Alt+F7返回桌面环境,这个时候,你的/dev目录下应该有了fb0这个设备,说明配置成功!

   关于vga参数的设置,可以参照下表:


                        4bit       8bit            15bit      16bit       24bit      32bit

640x400           x       0x300         x              x              x            x

640x480           x       0x301        0x310    0x311    0x312     x

800x600           0x302  0x303    0x313    0x314    0x315    x

1024x768       x       0x305          0x316    0x317    0x318    x

1280x1024     x       0x307         0x319    0x31A    0x31B    x

1600x1200     x       0x31C        0x31D    0x31E    0x31F    x


三、例子


以下是一个利用FrameBuffer显示汉字的程序,不是我写的,经过测试可以运行

hz.c文件:

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <linux/fb.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include "ziku.h"#define FB_DEV "/dev/fb0"int fb_open(char *fb_device);int fb_close(int fd);void *fb_mmap(int fd,unsigned int screensize);int fb_munmap(void *start,size_t length);int fb_16pixel(unsigned char *fbmem,int width,int height,int x,int y,unsigned short color);void char_hz(char ch,unsigned char *fbmem,unsigned int width,unsigned int height,unsigned int x1,unsigned y1);int main(int argc,char *argv[]){int fbdev;char *fb_device;unsigned char *fbmem;unsigned int screensize;unsigned int fb_width;unsigned int fb_height;unsigned int fb_depth;unsigned int x;unsigned int y;unsigned int ii;if((fb_device = getenv("FRAMEBUFFER")) == NULL){fb_device = FB_DEV;fbdev = fb_open(fb_device);}else printf("%s",fb_device);fb_width = 1024;fb_height = 768;fb_depth = 16;screensize = fb_width * fb_height *(fb_depth / 8);//fbmem = fb_mmap(fbdev,screensize);//memset (fbmem, 0, screensize);//for(ii=0;ii<7;ii++)//{char_hz(ii,fbmem,fb_width,fb_height,30+ii*16,30);}fb_munmap(fbmem,screensize);fb_close(fbdev);return (0);}void char_hz(char ch,unsigned char *fbmem,unsigned int width,unsigned int height,unsigned int x1,unsigned int y1){int i,j,k,n;unsigned char list;n = ch * 32;for(i = 0;i < 16;i++,n++){list = fontdata_16x16[n];for(j=0;j<8;j++){         if(list&(1<<(7-j))){fb_16pixel(fbmem,width,height,y1+j,x1+i, 0x1C3B);}      }n++;list = fontdata_16x16[n];for(j=0;j<8;j++){         if(list&(1<<(7-j))){fb_16pixel(fbmem,width,height,y1+8+j,x1+i,0x1C3B);}      }}}int fb_open(char *fb_device){int fd;if((fd = open(fb_device,O_RDWR)) < 0){perror(__func__);return (-1);}return (fd);}void *fb_mmap(int fd,unsigned int screensize){void*  fbmem;if((fbmem = mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){perror(__func__);return (void *)(-1);}return (fbmem);}int fb_munmap(void *start,size_t length){return (munmap(start,length));}int fb_close(int fd){return (close(fd));}//int fb_16pixel(unsigned char *fbmem, int width,int height,int x,int y,unsigned short color){if((x > width)||(y > height))return (-1);unsigned short *dst = ((unsigned short *)fbmem + y * width + x);*dst = color;return (0);}

ziku.h文件:

#define FONTDATAMAX 224const unsigned char fontdata_16x16[FONTDATAMAX] ={/*我*/0x04,0x80,0x0E,0xA0,0x78,0x90,0x08,0x90,0x08,0x84,0xFF,0xFE,0x08,0x80,0x08,0x90,0x0A,0x90,0x0C,0x60,0x18,0x40,0x68,0xA0,0x09,0x20,0x0A,0x14,0x28,0x14,0x10,0x0C,/*是*/0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x00,0x04,0xFF,0xFE,0x01,0x00,0x09,0x20,0x09,0xF0,0x09,0x00,0x15,0x00,0x23,0x06,0x40,0xFC,/*大*/0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x04,0xFF,0xFE,0x01,0x00,0x02,0x80,0x02,0x80,0x02,0x40,0x04,0x40,0x04,0x20,0x08,0x10,0x10,0x0E,0x60,0x04,0x00,0x00,/*聪*/0x05,0x04,0xFE,0xCC,0x24,0x50,0x24,0x04,0x3D,0xFE,0x25,0x04,0x25,0x04,0x25,0x04,0x3D,0xFC,0x25,0x44,0x24,0x20,0x24,0xA4,0xFD,0x8A,0x06,0x8A,0x04,0x78,0x04,0x00,//中0x01,0x00,0x01,0x00,0x01,0x04,0x7F,0xFE,0x41,0x04,0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x41,0x04,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,//国0x00,0x04,0x7F,0xFE,0x40,0x24,0x5F,0xF4,0x41,0x04,0x41,0x04,0x41,0x44,0x4F,0xE4,0x41,0x04,0x41,0x44,0x41,0x24,0x41,0x04,0x5F,0xF4,0x40,0x04,0x7F,0xFC,0x40,0x04,//人0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x80,0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x0E,0x40,0x04};

运行上面程序,会在屏幕上显示 “我是大聪中国人” 字样

好啦,到此FrameBuffer已经总结完毕,敲了这么大半天,希望对正在研究FrameBuffer的新手带来帮助,呵呵~~~,还有什么不懂的可以留言,大家共同讨论,共同进步~~

原创粉丝点击