简单描述一下framebuffer的使用,它其实就相当于将屏幕上的像素映射到内存中,改变内存中的内容后屏幕自动就变颜色了。
首先要调用open("/dev/fb0", O_RDWR);打开帧缓冲设备文件,获得文件描述符,然后使用mmap将文件内容映射到内存中,具体映大小取决于屏幕大小,初始化程序如下:
1 typedef unsigned short color_t; /* 根据实际情况修改,此处为unsigned short是565的屏 */ 2 3 static struct fb_var_screeninfo __g_vinfo; /* 显示信息 */ 4 static color_t *__gp_frame; /* 虚拟屏幕首地址 */ 5 6 int framebuffer_init (void) 7 { 8 int fd = 0; 9 10 fd = open("/dev/fb0", O_RDWR); 11 if (fd == -1) { 12 perror("fail to open /dev/fb0\n"); 13 return -1; 14 } 15 16 ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo); /* 获取显示信息 */ 17 printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel); /* 得到一个像素点对应的位数 */ 18 19 __gp_frame = mmap(NULL, /* 映射区的开始地址,为NULL表示由系统决定映射区的起始地址 */ 20 __g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8, /* 映射区大小 */ 21 PROT_WRITE | PROT_READ, /* 内存保护标志(可读可写) */ 22 MAP_SHARED, /* 映射对象类型(与其他进程共享) */ 23 fd, /* 有效的文件描述符 */ 24 0); /* 被映射内容的偏移量 */ 25 if (__gp_frame == NULL) { 26 perror("fail to mmap\n"); 27 return -1; 28 } 29 30 return 0; 31 }
初始化成功后对__gp_frame指针操作就相当于对屏幕进行操作了。附上完整测试程序:
1 /** 2 * filename: framebuffer.c 3 * author: Suzkfly 4 * date: 2021-07-28 5 * platform: S3C6410或Ubuntu 6 * 编译程序并运行,屏幕上间隔1s显示红绿蓝三种不同颜色。 7 */ 8 9 #include <stdio.h> 10 #include <linux/fb.h> 11 #include <sys/types.h> 12 #include <sys/stat.h> 13 #include <fcntl.h> 14 #include <sys/mman.h> 15 16 /**< \brief 根据实际情况修改,此处为unsigned short是565的屏,根据程序打印出的 17 bits_per_pixel的值可以判断出输出格式是565还是888 */ 18 typedef unsigned short color_t; /* 565的屏 */ 19 #define BLUE 0x001F /* 蓝色 */ 20 #define GREEN 0x07E0 /* 绿色 */ 21 #define RED 0xF800 /* 红色 */ 22 //typedef unsigned int color_t; /* 888的屏 */ 23 //#define BLUE 0x000000FF /* 蓝色 */ 24 //#define GREEN 0x0000FF00 /* 绿色 */ 25 //#define RED 0x00FF0000 /* 红色 */ 26 27 28 static struct fb_var_screeninfo __g_vinfo; /* 显示信息 */ 29 static color_t *__gp_frame; /* 虚拟屏幕首地址 */ 30 31 int framebuffer_init (void) 32 { 33 int fd = 0; 34 35 fd = open("/dev/fb0", O_RDWR); 36 if (fd == -1) { 37 perror("fail to open /dev/fb0\n"); 38 return -1; 39 } 40 41 ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo); /* 获取显示信息 */ 42 printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel); /* 一个像素点对应的位数,如果值为16则为565格式输出,如果值为32则为888格式输出 */ 43 printf("xres_virtual = %d\n", __g_vinfo.xres_virtual); /* 虚拟x轴像素点数 */ 44 printf("yres_virtual = %d\n", __g_vinfo.yres_virtual); /* 虚拟y轴像素点数 */ 45 printf("xres = %d\n", __g_vinfo.xres); /* x轴像素点数 */ 46 printf("yres = %d\n", __g_vinfo.yres); /* y轴像素点数 */ 47 48 __gp_frame = mmap(NULL, /* 映射区的开始地址,为NULL表示由系统决定映射区的起始地址 */ 49 __g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8, /* 映射区大小 */ 50 PROT_WRITE | PROT_READ, /* 内存保护标志(可读可写) */ 51 MAP_SHARED, /* 映射对象类型(与其他进程共享) */ 52 fd, /* 有效的文件描述符 */ 53 0); /* 被映射内容的偏移量 */ 54 if (__gp_frame == NULL) { 55 perror("fail to mmap\n"); 56 return -1; 57 } 58 59 return 0; 60 } 61 62 /** 63 * \brief 填充整屏 64 */ 65 void full_screen (color_t color) 66 { 67 int i; 68 color_t *p = __gp_frame; 69 70 for (i = 0; i < __g_vinfo.xres_virtual * __g_vinfo.yres_virtual; i++) { 71 *p++ = color; 72 } 73 } 74 75 int main(int argc, const char *argv[]) 76 { 77 if (framebuffer_init()) { 78 printf("framebuffer_init failed\n"); 79 return 0; 80 } 81 82 while (1) { 83 full_screen(RED); /* 填充红色 */ 84 sleep(1); 85 full_screen(GREEN); /* 填充绿色 */ 86 sleep(1); 87 full_screen(BLUE); /* 填充蓝色 */ 88 sleep(1); 89 } 90 91 return 0; 92 }
执行程序后屏幕交替显示红绿蓝三种颜色。