首页 > 技术知识 > 正文

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;//写入颜色值 }
审核编辑:汤梓红

猜你喜欢