目录
一、LCD显示的基本原理
1、认识 FrameBuffer
2、理解LCD的分辨率和深度
二、接口函数 ioctl
1、函数声明
2、结构体介绍
三、获取LCD屏的信息(分辨率、深度)
一、LCD显示的基本原理
1、认识 FrameBuffer
FrameBuffer 是帧缓冲,可以看做是一块内存,帧缓冲是一种显示驱动接口,该接口屏蔽了显示设备(如LCD)硬件层面的实现。在应用层看来,显示设备就是一块内存,操作这块内存就相当于在操作显示设备。
在Linux 系统中,显示设备也叫做 FrameBuffer 设备,LCD就是 FrameBuffer 设备,FrameBuffer 设备对应的设备文件为 /dev/fdX(X=0、1、2 ...),一般 /dev/fb0 代表LCD显示屏。应用程序读写 /dev/fbX 就相当于读写显示设备的显存(显示缓冲区)
2、理解LCD的分辨率和深度
说到显示设备或者图片,我们经常会提到 分辨率 和 像素深度 的概念
- 分辨率:一行有多少个像素点,一列有多少个像素点
- 像素深度:每个像素点要用多少bit来表示
假设LCD 的分辨率是 800*480,每个像素点用 RGB565 来表示。
800*480 | 每行有 800 个像素点,每列有 480 个像素点 |
RGB565 | 每个像素点由R、G、B三种颜色表示 - R 占 5 bit - G 占 6 bit - B 占 5 bit |
前面说到,显示设备其实可以看做是显示缓冲区,显示缓冲区的大小 = 分辨率 * 像素深度
二、接口函数 ioctl
1、函数声明
ioctl 的用途会根据其传入的参数发生变化,ioctl函数声明如下:
第一个参数是文件描述符,即FrameBuffer 设备对应的设备文件 /dev/fdX(X=0、1、2 ...)
第二个参数需传入一个宏,第二个参数决定了 ioctl 函数的用途
第二个参数 | 含义 |
FBIOGET_VSCREENINFO | 获取 FrameBuffer 设备的可变参数信息 |
FBIOPUT_VSCREENINFO | 设置 FrameBuffer 设备的可变参数信息 |
FBIOGET_FSCREENINFO | 获取 FrameBuffer 设备的固有参数信息 |
第三个参数所传入的类型会随着第二个参数变化。
第二个参数 | 第三个参数类型 |
FBIOGET_VSCREENINFO | struct fb_var_screeninfo * |
FBIOPUT_VSCREENINFO | struct fb_var_screeninfo * |
FBIOGET_FSCREENINFO | struct fb_fix_screeninfo * |
// 获取设备可变参数信息
struct fb_var_screeninfo fb_var;
int fd = 0;
if((fd = open("/dev/fb0", O_RDWR) < 0))
{
perror("open fb failed");
exit(-1);
}
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
2、结构体介绍
上面第三个参数中涉及到多种结构体 struct fb_var_screeninfo、struct fb_fix_screeninfo ,我们如果要获取到可变参数的信息,势必需要了解对应结构体包含的成员变量。
struct fb_var_screeninfo
struct fb_var_screeninfo {
__u32 xres; /* 可视区域,一行有多少个像素点,X 分辨率 */
__u32 yres; /* 可视区域,一列有多少个像素点,Y 分辨率 */
__u32 bits_per_pixel; /* 每个像素点使用多少个 bit 来描述,也就是像素深度 bpp */
__u32 grayscale; /* =0 表示彩色, =1 表示灰度, >1 表示 FOURCC 颜色 */
/* 用于描述 R、G、B 三种颜色分量分别用多少位来表示以及它们各自的偏移量 */
struct fb_bitfield red; /* Red 颜色分量色域偏移 */
struct fb_bitfield green; /* Green 颜色分量色域偏移 */
struct fb_bitfield blue; /* Blue 颜色分量色域偏移 */
struct fb_bitfield transp; /* 透明度分量色域偏移 */
// ... ...
};
其中 struct fb_bitfield 结构体的声明如下。下面的 “偏移量” 可以参考本文最后一部分的结果分析
struct fb_bitfield {
__u32 offset; /* 偏移量 */
__u32 length; /* 长度 */
__u32 msb_right; /* != 0 : Most significant bit is right */
}
struct fb_fix_screeninfo
struct fb_fix_screeninfo {
char id[16]; /* 字符串形式的标识符 */
unsigned long smem_start; /* 显存的起始地址(物理地址) */
__u32 smem_len; /* 显存的长度 */
__u32 type;
__u32 type_aux;
__u32 visual;
__u16 xpanstep;
__u16 ypanstep;
__u16 ywrapstep;
__u32 line_length; /* 一行的字节数 */
unsigned long mmio_start; /* Start of Memory Mapped I/O(physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which specific chip/card we have */
__u16 capabilities;
__u16 reserved[2];
};
三、获取LCD屏的信息(分辨率、深度)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
int main(int args, char **argv)
{
struct fb_fix_screeninfo fb_fix; // 固定参数信息
struct fb_var_screeninfo fb_var; // 可变参数信息
int fd = open("/dev/fb0", O_RDWR);
if (fd < 0)
{
perror("open fb failed");
return -1;
}
ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix); // 获取固定参数信息
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var); // 获取可变参数信息
printf(
"分辨率:%d * %d \n" \
"像素深度:%d bit \n" \
"像素格式: R<%d %d> G<%d %d> B<%d %d>\n", \
fb_var.xres, fb_var.yres, \
fb_var.bits_per_pixel, \
fb_var.red.offset, fb_var.red.length, \
fb_var.green.offset, fb_var.green.length, \
fb_var.blue.offset, fb_var.blue.length
);
close(fd);
return 0;
}
分辨率:每行有 800 个像素点,每列有 480 个像素点
像素深度:用 16bit 来表示每个像素点
像素格式:使用的格式是 RGB565,红色(R)占 5 bit,绿色(G)占 6 bit,蓝色(B)占 5 bit