Linux通过Framebuffer驱动程序来控制LCD,其中保存着单帧图像的全部像素点颜色值。
LCD的操作原理:
①驱动程序设定好LCD控制器:
根据LCD的参数设置LCD控制器的时序、信号极性;
根据LCD分辨率、BPP分配Framebuffer;
②应用程序使用ioctl获得LCD分辨率、BPP;
③应用程序通过mmap映射Framebuffer,在Framebuffer中写入数据;
BPP(bits per pixel):每个像素用多少位来表示颜色值
假设更改LCD中位置为(x,y)的像素点的颜色值,则其内存位为:base+(y*x_res+x)*bpp/8
Framebuffer程序:
#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> static int fd_fb; static struct fb_var_screeninfo var; /* Current var */ static int screen_size; static unsigned char *fb_base; static unsigned int line_width; static unsigned int pixel_width; int main(int argc, char **argv) { int i; 1.打开设备节点——open函数 fd_fb = open("/dev/fb0", O_RDWR); if (fd_fb < 0) { printf("can't open /dev/fb0\n"); return -1; } 2.获取LCD参数——ioctl函数 if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { printf("can't get var\n"); return -1; } 3.映射Framebuffer——mmap函数 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; } /* 清屏: 全部设为白色 */ memset(fb_base, 0xff, screen_size); /* 随便设置出100个为红色 */ for (i = 0; i < 100; i++) lcd_put_pixel(var.xres/2+i, var.yres/2, 0xFF0000); munmap(fb_base , screen_size); close(fd_fb); return 0; }
描点函数 void lcd_put_pixel(int x, int y, unsigned int color) //color传入格式0x00RRGGBB { unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width; unsigned short *pen_16; unsigned int *pen_32; unsigned int red, green, blue; pen_16 = (unsigned short *)pen_8; pen_32 = (unsigned int *)pen_8; switch (var.bits_per_pixel) { case 8: { *pen_8 = color; break; } case 16: { red = (color >> 16) & 0xff; green = (color >> 8) & 0xff; blue = (color >> 0) & 0xff; //先抽离R、G、B color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); //取R高5位,G高6位,B高5位(RGB565) *pen_16 = color; break; } case 32: { *pen_32 = color; break; } default: { printf("can't surport %dbpp\n", var.bits_per_pixel); break; } } }
tip:需要使用open/ioctl/mmap函数,可通过man指令来查找头文件和函数原型;