LCD属于硬件设备,所以需要通过驱动程序才能控制,而在Linux系统中是通过 Framebuffer驱动子系统来控制LCD的。Frame是帧的意思,buffer是缓冲的意思,所以Framebuffer也被称为帧缓冲。Linux系统下面有多个子系统,其中 Framebuffer子系统就是Linux系统为显示设备提供的一个驱动程序接口,用于驱动显示设备。
Framebuffer驱动子系统会从内存中申请一块空间用于保存一帧图像的颜色数据,这块内存会被映射到进程的地址空间,这样进程就可以直接进行对帧缓冲进行读写操作,并且写操作可以立即刷新到屏幕上。
可以理解为Framebuffer驱动子系统把屏幕上的每个像素点映射成一段线性内存空间,应用程序直接修改这段内存空间的数据就相当于改变屏幕上某一像素点的颜色。
在Linux系统下是利用Framebuffer子系统来驱动显示设备的,所以Framebuffer子系统会读取LCD屏的硬件信息并存储在内核空间中,
关于LCD的硬件参数都是定义在/usr/include/linux/fb.h头文件中。
通过fb.h可以看到头文件中存在三个比较重要的结构体,分别是struct fb_fix_screeninfo以及struct fb_var_screeninfo以及struct fb_bitfield,除了这三个结构体之外,可以发现头文件中存在大量的宏定义,用户可以通过这些宏定义来指定读取LCD的部分信息。
(1)struct fb_fix_screeninfo结构体
struct fb_fix_screeninfo结构体主要用于获取FrameBuffer的固定参数,用户无法在应用层修改这些参数,只能通过系统调用ioctl函数使用宏定义FBIOGET_FSCREENINFO去获取这些参数。
(2)struct fb_var_screeninfo结构体
struct fb_var_screeninfo结构体主要用于获取和设置FrameBuffer的可变屏幕参数,包括分辨率、像素位深、像素格式等。这些信息可以通过ioctl函数使用宏定义FBIOGET_VSCREENINFO获取,也可以通过宏定义FBIOPUT_VSCREENINFO修改。
练习:生成旗帜
点击查看代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/fb.h>
#include <sys/ioctl.h> int main(int argc, char const *argv[]) { // 1. 打开 LCD int lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd == -1) { printf("open lcd error\n"); return -1; } // 2. 获取屏幕参数 struct fb_var_screeninfo vinfo; if (ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { printf("ioctl error\n"); close(lcd_fd); return -1; } // 3. 动态分配缓冲区(short 类型,适配 16 位像素) short *colorbuf = malloc(1024 * 600 * sizeof(short)); if (colorbuf == NULL) { printf("malloc error\n"); close(lcd_fd); return -1; } // 4. 填色逻辑(RGB565 格式) // 上 200 行:黑(0x0000) int i = 0; for(; i<1024*200; i++){ colorbuf[i] = 0x0000; } // 中间 200 行:红(0xF800) for(i=1024*200; i<1024*400; i++){ colorbuf[i] = 0xF800; } // 下 200 行:黄(0xFFE0) for(i=1024*400; i<1024*600; i++){ colorbuf[i] = 0xFFE0; } // 5. 写入 LCD(长度 = 分辨率 * 2 字节) write(lcd_fd, colorbuf, 1024*600*sizeof(short)); // 6. 清理 free(colorbuf); close(lcd_fd); return 0;
}