显示屏里面有一些自带的驱动寄存器,我们要操作显示器的亮灭显示及颜色等,其实就是对该显示器的寄存器进行操作,有一些寄存器是只读的,里面包含了该显示屏的一些基本且不可更改的信息,比如说该显示器实际的长和宽,还有一些信息是可以改变的,比如说屏幕的分辨率。
我们首先需要读取显示器找中的一些特定的信息,在程序的实现中是通过
ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
来实现读取硬件不可变的信息。
而通过
ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
则可以读取硬件的可变信息,然后再对这些读取到的信息进行调整,然后再写进去到屏幕的寄存器中即可改变显示器的设置
vinfo.xres = 1024;
vinfo.yres = 600;
vinfo.xres_virtual = 1024;
vinfo.yres_virtual = 1200;
ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);
而显示背景和显示字体颜色其实就是对某个像素点的地址进行写值,地址的不同决定了像素点的坐标不同,值的不同决定了该坐标像素点的颜色和亮度不同。首先需要获得该显示屏地址的基址,然后随着偏移地址累加会逐渐扫描各个像素点。我们只需要在里面赋相应的值即可。
pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
*(pfb + y * WIDTH + x) = color;
完整代码如下:
本程序参考朱友鹏老师视频程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define FBDEVICE "/dev/fb0"
//#define WIDTH 800
//#define HEIGHT 480
#define WIDTH 1024
#define HEIGHT 600
#define WHITE 0xffffffff // test ok
#define BLACK 0x00000000
#define RED 0xffff0000
#define GREEN 0xff00ff00 // test ok
#define BLUE 0xff0000ff
#define GREENP 0x0000ff00
void draw_back(unsigned int width, unsigned int height, unsigned int color);
void draw_line(unsigned int color);
unsigned int *pfb = NULL;
int main(void)
{
int fd = -1, ret = -1;
struct fb_fix_screeninfo finfo = {0};
struct fb_var_screeninfo vinfo = {0};
fd = open(FBDEVICE, O_RDWR);
if (fd < 0)
{
perror("open");
return -1;
}
printf("open %s success.\n", FBDEVICE);
ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo); //
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo); //
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
printf("bpp = %u.\n", vinfo.bits_per_pixel);
vinfo.xres = 1024;
vinfo.yres = 600;
vinfo.xres_virtual = 1024;
vinfo.yres_virtual = 1200;
ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
printf("bpp = %u.\n", vinfo.bits_per_pixel);
unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
printf("len = %ld\n", len);
pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //get address for back color
if (NULL == pfb)
{
perror("mmap");
return -1;
}
printf("pfb = %p.\n", pfb);
draw_back(WIDTH, HEIGHT, WHITE); //
draw_line(RED);
close(fd);
return 0;
}
void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
unsigned int x, y;
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
*(pfb + y * WIDTH + x) = color;
}
}
}
void draw_line(unsigned int color)
{
unsigned int x, y;
for (x=50; x<600; x++)
{
*(pfb + 200 * WIDTH + x) = color;
}
}