# 前置知识
LCD 操作原理
- 在 Linux 系统中通过 Framebuffer 驱动程序来控制 LCD。 Frame 是帧的意思, buffer 是缓冲的意思,这意味着 Framebuffer 就是一块内存,里面保存着一帧图像。 Framebuffer 中保存着一帧图像的每一个像素颜色值,假设 LCD 的分辨率是 1024x768,每一个像素的颜色用 32 位来表示,那么 Framebuffer 的大小就是: 1024x768x32/8=3145728 字节。
- 假设需要设置 LCD 中坐标(x,y)处像素的颜色,首要要找到这个像素对应的内存,然后根据它的 BPP(像素深度 bits per pixel) 值设置颜色。假设 fb_base 是 APP 执行 mmap 后得到的 Framebuffer 地址,可以用以下公式算出(x,y)坐标处像素对应的 Framebuffer 地址:
(x, y)像素起始地址=fb_base+(xres*bpp/8)*y + x*bpp/8
- 对于 32BPP,一般只设置其中的低 24 位,高 8 位表示透明度,一般的 LCD都不支持。
对于 24BPP,硬件上为了方便处理,在 Framebuffer 中也是用 32 位来表示,效果跟 32BPP 是一样的。
对于 16BPP,常用的是 RGB565;
API 函数
- ioctl 函数
ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。
int ioctl(int fd, unsigned long request, ...);
函数参数:
参数 | 描述 |
---|---|
fd | 文件描述符 |
cmd | 交互协议,设备驱动将根据 cmd 执行对应操作 |
… | 可变参数 arg,依赖 cmd 指定长度以及类型 |
返回值:
EBADF d is not a valid descriptor.
EFAULT argp references an inaccessible memory area.
EINVAL Request or argp is not valid.
ENOTTY d is not associated with a character special device.
ENOTTY The specified request does not apply to the kind of object that the descriptor d references.
- mmap函数
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函数参数:
返回值:
- 返回值类型:
int
- 若成功映射,将返回指向映射的区域的指针,失败将返回-1
# 结构体详解
struct fb_fix_screeninfo
主要用于获取FrameBuffer
的固定信息,这些信息无法在应用层被更改,只能通过ioctl
函数使用FBIOGET_FSCREENINFO
去获取。
struct fb_fix_screeninfo
定义
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
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; /* see FB_CAP_* */
__u16 reserved[2]; /* Reserved for future compatibility */
};
struct fb_fix_screeninfo
字段说明
表格中提到的宏如FB_TYPE_PACKED_PIXELS
、FB_VISUAL_TRUECOLOR
、FB_ACCEL_NONE
请查看 /usr/include/linux/fb.h 的相关定义。
字段名称 | 描述 | 附加说明 |
---|---|---|
id | 设备驱动名称 | |
smem_start | 显存起始物理地址 | |
smem_len | 显存大小 | |
type | 显卡类型 | 一般为 FB_TYPE_PACKED_PIXELS(值为0,表示像素值紧密排 列),查看fb.h的 FB_TYPE_* |
type_aux | 附加类型 | 查看fb.h的 FB_AUX_TEXT_MDA |
visual | 色彩模式 | 一般为 FB_VISUAL_TRUECOLOR(值为2,真彩色) |
xpanstep | 支持水平方向上的 PAN 显示: 0:不支持 非 0:支持,此时该值用于表示在水平方向上每步进的像素值 | 默认为 1 |
ypanstep | 支持垂直方向上的 PAN 显示: 0:不支持。 非 0:支持,此时该值用于表示在垂直方向上每步进的像素值。 | 默认为 1 |
ywrapstep | 该方式类似于 ypanstep,不同之处在于:当其显示到底部时,能回到显存的开始处进行显示。 | 默认为 0 |
line_length | 每行字节数 | |
mmio_start | 显存映射 I/O 首地址 | 默认为不支持 |
mmio_len | 显存映射 I/O 长度 | 默认为不支持 |
accel | 显示所支持的硬件加速设备 | 默认为 FB_ACCEL_NONE |
struct fb_var_screeninfo
定义
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* 0 = color, 1 = grayscale,*//* >1 = FOURCC*/
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync*/
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
struct fb_var_screeninfo
字段说明
表格中提到的宏和结构体请查看 /usr/include/linux/fb.h 的相关定义。
获取 fb_fix_screeninfo和fb_var_screeninfo信息
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
/* fb_var_screeninfo info */
static int fd_fb;
static struct fb_var_screeninfo var;
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;
/* fb_fix_screeninfo info */
static struct fb_var_screeninfo finfo;
int main(int argc, char **argv)
{
int i;
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
printf("can't open /dev/fb0\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
printf("can't get var\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &finfo) < 0)
{
fprintf(stderr, "ioctl FBIOGET_FSCREENINFO err \r\n");
return -1;
}
line_width = var.xres * var.bits_per_pixel / 8;
pixel_width = var.bits_per_pixel / 8;
screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
/* 映射 Framebuffer */
fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (fb_base == (unsigned char *)-1)
{
printf("can't mmap\n");
return -1;
}
munmap(fb_base , screen_size);
close(fd_fb);
return 0;
}