framebuffer驱动详解1——应用层编码实践

以下内容源于朱有鹏嵌入式课程的学习,如有侵权,请告知删除。


一、使用步骤

(1)打开设备文件 /dev/fb0

(2)获取设备信息 #include

(3)mmap做映射

(4)填充framebuffer


二、应用编程实践

1、打开设备

2、获取设备信息

(1)LCD的硬件信息在头文件fb.h中

framebuffer驱动详解1——应用层编码实践_第1张图片

(2)不可变的信息FSCREENINFO,对应使用ioctl的FBIOGET_FSCREENINFO名。不可变的信息,如物理分辨率。

framebuffer驱动详解1——应用层编码实践_第2张图片

(3)可变的信息VSCREENINFO,使用ioctl的FBIOGET_VSCREENINFO名。可变的信息,如屏幕的分辨率。

framebuffer驱动详解1——应用层编码实践_第3张图片

3、mmap做映射

  • 即把内核中那段作为显示缓冲区的内存,映射给当前进程的用户空间。做完了mmap后,fb在当前进程中就已经就绪了,随时可以去读写LCD显示器了。

(1)包含头文件#include

(2)mmap函数的讲解

  • 第一个参数表示映射到哪个物理地址,写NULL表示自动分配;
  • 第二个参数表示被映射的内存的大小;
  • 第三个参数表示权限;
  • 第四个参数表示当前的映射结果能否被多个进程共享;
  • 第五个参数表示文件节点;
  • 第六个参数表示偏移量。
  • 返回值表示映射结果的内存的开始地址

4、填充framebuff的例子

(1)映射之后fb显示之刷背景

  • 四个字节表示一个像素。xx xx xx xx,后三者表示RGB,前一表示透明度?
  • draw_back()函数来实现,参数为屏幕的长度和宽度。

void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
	unsigned int x, y;
	
	for (y=0; y

(2)写字、画线、图片显示等

参考http://blog.csdn.net/oqqhutu12345678/article/details/71941527#t12


5、在应用程序中设置分辨率

(1)可视分辨率(即实际分辨率)、虚拟分辨率

framebuffer驱动详解1——应用层编码实践_第4张图片


(2)实验及结果

vinfo.xres = 1024;
vinfo.yres = 600;//不可以修改

vinfo.xres_virtual = 1024;
vinfo.yres_virtual = 1200;//可以修改

ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);

  • 实验结果是只能修改虚拟分辨率,不能修改可见分辨率。
  • 原因要去驱动里找,正确的做法是在驱动中去修改参数,然后重新编译运行,才能解决。


三、代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 宏定义
#define FBDEVICE	"/dev/fb0"

// 旧开发板
//#define WIDTH		800	
//#define HEIGHT		480
// 新开发板
#define WIDTH		1024	
#define HEIGHT		600

#define WHITE		0xffffffff			// test ok
#define BLACK		0x00000000
#define RED			0xffff0000
#define GREEN		0xff00ff00			// test ok
#define BLUE		0xff0000ff			

#define GREENP		0x0000ff00			// 一样,说明前2个ff透明位不起作用


// 函数声明
void draw_back(unsigned int width, unsigned int height, unsigned int color);
void draw_line(unsigned int color);
// 全局变量
unsigned int *pfb = NULL;

int main(void)
{
	int fd = -1, ret = -1;
	
	struct fb_fix_screeninfo finfo = {0};
	struct fb_var_screeninfo vinfo = {0};
	
	// 第1步:打开设备
	fd = open(FBDEVICE, O_RDWR);
	if (fd < 0)
	{
		perror("open");
		return -1;
	}
	printf("open %s success.\n", FBDEVICE);
	
	// 第2步:获取设备的硬件信息
	ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
	
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	printf("bpp = %u.\n", vinfo.bits_per_pixel);

	// 修改驱动中屏幕的分辨率
	vinfo.xres = 1024;
	vinfo.yres = 600;
	vinfo.xres_virtual = 1024;
	vinfo.yres_virtual = 1200;
	ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	
	// 再次读出来检验一下
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("修改过之后的参数:\n");
	printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	printf("bpp = %u.\n", vinfo.bits_per_pixel);
	
	
	// 第3步:进行mmap
	unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
	printf("len = %ld\n", len);
	pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (NULL == pfb)
	{
		perror("mmap");
		return -1;
	}
	printf("pfb = %p.\n", pfb);
	
	//第4步,填充framebuff
	draw_back(WIDTH, HEIGHT, WHITE);
	draw_line(RED);
	
	close(fd);

	return 0;
}

void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
	unsigned int x, y;
	
	for (y=0; y


你可能感兴趣的:(驱动学习)