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

      首先来说,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 224



const 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的新手带来帮助,呵呵~~~,还有什么不懂的可以留言,大家共同讨论,共同进步~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值