文章目录
- 前言
- 一、LCD操作原理
- 二、代码解析及编写程序的步骤
- 0.定义各类参数
- 1.打开LCD设备节点
- 2.获取触摸屏数据
- 3.mmap映射Framebuffer,在Framebuffer中写入数据
- 三、LCD操作函数解析
- 1.描点函数
- 2.显示字符函数
- 总结
前言
本篇文章将会介绍Linux下的Framebuffer编程,这里将会引用到百问网韦东山老师讲的一些知识。
一、LCD操作原理
在Linux系统中通过Framebuffer驱动程序来控制LCD。Frame是帧的意思,buffer是缓冲的意思,这意味着Framebuffer就是一块内存,里面保存着一帧图像。Framebuffer中保存着一帧图像的每一个像素颜色值,假设LCD的分辨率是1024x768,每一个像素的颜色用32位来表示,那么Framebuffer的大小就是:1024x768x32/8=3145728字节。
二、代码解析及编写程序的步骤
0.定义各类参数
下面这些参数后面我们会一 一介绍。
int fd_fb;
struct fb_var_screeninfo var; /* Current var */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;
1.打开LCD设备节点
这些的fd_fb就是打开LCD设备返回的文件句柄。
/dev/fb0 :LCD设备节点(根据自己板子上面的节点填写)
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
printf("can't open /dev/fb0\n");
return -1;
}
2.获取触摸屏数据
使用ioctl获取LCD的一些参数信息,并将这些参数的信息放入var结构体中。
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
printf("can't get var\n");
return -1;
}
var结构体解析:
这个结构体里面保存了LCD的相关信息,比如xres和yres就是代表了x方向的分辨率和y方向的分辨率。
大家的手机都有分辨率,最常见的就是1080×1920了。对应到xres和yres就是xres=1080,yres=1920。
大家只需要知道var这个结构体是用来保存ioctl获取到的LCD的参数信息即可。
bits_per_pixel:每一个像素的颜色用多少位表示
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 colorspace; /* colorspace for FOURCC-based modes */
__u32 reserved[4]; /* Reserved for future compatibility */
};
3.mmap映射Framebuffer,在Framebuffer中写入数据
line_width:var.xres * var.bits_per_pixel代表每一行有多少个像素
/8就代表了每一行有多少个字节
pixel_width :每一个像素多少个字节
screen_size :计算出整个屏幕所占字节的大小
fbmem :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;
fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (fbmem == (unsigned char *)-1)
{
printf("can't mmap\n");
return -1;
}
三、LCD操作函数解析
1.描点函数
pen_8 ,pen_16,pen_32参数代表的是起笔点,因为我使用的LCD每个像素是8位的,所以我这里只需要计算pen_8 即可,其他两个只需要进行一次转换即可。
pen_8 的计算
void lcd_put_pixel(int x, int y, unsigned int color)
{
unsigned char *pen_8 = fbmem+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:
{
/* 565 */
red = (color >> 16) & 0xff;
green = (color >> 8) & 0xff;
blue = (color >> 0) & 0xff;
color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
*pen_16 = color;
break;
}
case 32:
{
*pen_32 = color;
break;
}
default:
{
printf("can't surport %dbpp\n", var.bits_per_pixel);
break;
}
}
}
2.显示字符函数
void lcd_put_ascii(int x, int y, unsigned char c, unsigned int color)
{
unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
int i, b;
unsigned char byte;
for (i = 0; i < 16; i++)
{
byte = dots[i];
for (b = 7; b >= 0; b--)
{
if (byte & (1<<b))
{
/* show */
lcd_put_pixel(x+7-b, y+i, color); /* 白 */
}
else
{
/* hide */
lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
}
}
}
}
总结
本篇文章就介绍到这里,Framebuffer编程的编程其实并不算很难,大家只要理清楚这些参数即可。具体的代码请参考百问网,这里我只做重要部分介绍。