Linux帧缓冲注册OLED驱动(上)
1.帧缓冲Framebuff
在 linux 系统中 LCD 这类设备称为帧缓冲设备,英文 frameBuffer 设备。
frameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。
帧缓冲( framebuffer)是 Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
用户可以将 Framebuffer 看成是显示内存的一个映像, 将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。
帧缓冲驱动是字符类设备的一种,主设备号为29,生成的设备节点为/dev/fb*。
使用帧缓冲完成屏幕驱动注册,应用层只需调用open函数打开失败,再通过ioctl函数获取屏幕的参数信息,再调用mmap函数将屏幕显存地址映射到进程空间,接下来对地址的写入即是对屏幕的刷。
2.帧缓冲Framebuff应用编程
帧缓冲应用层编程步骤
打开LCD设备open(“/dev/fb0”,2);
获取固定参数和可变参数ioctl;
将屏幕缓冲区映射到进程空间mmap;
实现屏幕最核心函数画点函数;
2.1 帧缓冲Framebuff设备节点
通过帧缓冲完成屏幕驱动注册,会在/dev下生成设备节点,主设备号为29,注册的一个设备驱动为/dev/fb0,第二个为/dev/fb1,依此类推,最大可以注册32个设备。
2.2 固定参数
通过ioctl函数,命令参数为FBIOGET_FSCREENINFO,固定参数结构体为struct fb_fix_screeninfo。在固定参数可获得的屏幕信息有:smem_len屏幕缓冲区大小、line_length一行的字节数。
#define FBIOGET_FSCREENINFO 0x4602 /*获取屏幕固定参数*/
/*固定参数结构体*/
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 */
};
2.3 可变参数
通过ioctl函数,命令参数为FBIOGET_VSCREENINFO,固定参数结构体为struct fb_fix_screeninfo。在固定参数可获得的屏幕信息有:屏幕宽度xres、屏幕高度yres、颜色位数bits_per_pixel。
#define FBIOGET_VSCREENINFO 0x4600 /*获取屏幕可变参数*/
/*可变参数结构体*/
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 */
};
2.4 将屏幕缓冲区映射到进空间
#include
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函数功能: 将文件映射到进程空间
形参: addr --映射的虚拟地址,一般填NULL,有系统自行分配
length --要映射的空间大小
prot --PROT_READ可读;PROT_WRITE可写
flags --MAP_SHARED可读写,读写内容同步到文件;MAP_PRIVATE修改的内容不会同步到文件
fd --文件描述符
offset --一般填0,表示映射整个文件
返回值: 成功返回映射的地址
失败返回-1
int munmap(void *addr, size_t length);
形参: addr --mamp函数返回值
length --映射空间大小
2.5 帧缓冲获取固定参数和可变参数示例
int main()
{
/*1.打开设备*/
int fd=open("/dev/fb0", 2);
if(fd<0)
{
printf("打开设备失败n");
}
/*2.获取固定参数*/
memset(&fb_fix,0, sizeof(fb_fix));
ioctl(fd,FBIOGET_FSCREENINFO,&fb_fix);
printf("屏幕缓存大小:%dn",fb_fix.smem_len);
printf("一行的字节数:%dn",fb_fix.line_length);
/*3.获取屏幕可变参数*/
memset(&fb_var,0, sizeof(fb_var));
ioctl(fd,FBIOGET_VSCREENINFO,&fb_var);
printf("屏幕尺寸:%d*%dn",fb_var.xres,fb_var.yres);
printf("颜色位数:%dn",fb_var.bits_per_pixel);
/*4.将屏幕缓冲区映射到进程空间*/
lcd_p=mmap(NULL,fb_fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
if(lcd_p==(void *)-1)
{
printf("内存映射失败n");
return 0;
}
memset(lcd_p,0xff,fb_fix.smem_len);//将屏幕清空为白色
//取消映射
munmap(lcd_p,fb_fix.smem_len);
return 0;
}
/*画点函数实现*/
static inline void LCD_DrawPoint(int x,int y,int c)
{
//获取要绘制的点的地址
unsigned int *p= (unsigned int *)(lcd_p+y*fb_fix.line_length+x*fb_var.bits_per_pixel/8);
*p=c;//写入颜色值
}
-
OLED
+关注
关注
119文章
6171浏览量
223662 -
Linux
+关注
关注
87文章
11204浏览量
208701
发布评论请先 登录
相关推荐
评论