Linux帧缓冲注册OLED驱动(上)

描述

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;//写入颜色值
}
 审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分