记住!没有简单的程序,只有头脑简单的程序员!
struct fb_ops { struct module *owner; //检查可变参数并进行设置 int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); //根据设置的值进行更新,使之有效 int (*fb_set_par)(struct fb_info *info); //设置颜色寄存器 int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); //显示空白 int (*fb_blank)(int blank, struct fb_info *info); //矩形填充 void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); //复制数据 void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); //图形填充 void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); };
struct fb_info { int node; struct fb_var_screeninfo var; /* Current var */ struct fb_fix_screeninfo fix; /* Current fix */ struct fb_videomode *mode; /* current mode */ struct fb_ops *fbops; struct device *device; /* This is the parent */ struct device *dev; /* This is this fb device */ char __iomem *screen_base; /* Virtual address */ unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ ………… };
struct fb_var_screeninfo { __u32 xres; /* visible resolution */ __u32 yres; __u32 xoffset; /* offset from virtual to visible */ __u32 yoffset; /* resolution */ __u32 bits_per_pixel; /* bits/pixel */ __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 hsync_len; /* length of horizontal sync */ __u32 vsync_len; /* length of vertical sync */ ………… };
struct fb_fix_screeninfo { char id[16]; unsigned long smem_start; /* 开始的framebuffer内存,这里是物理地址要注意 */ __u32 smem_len; /* 物理地址的长度 */ unsigned long mmio_start; /* 开始的物理地址映射 */ __u32 mmio_len; /* IO内存映射的长度 */ ………… };
4、struct fb_videomode *mode 这个结构体主要是设置LCD相应的模式,看看我写的注释就清楚了。 struct fb_videomode { const char *name; /* optional */ u32 refresh; /* optional */ u32 xres; // x分辨率 u32 yres; // y分辨率 u32 pixclock; // 像素时钟频率,即每个时钟周期显示一个像素点 u32 left_margin; // 行扫描开始脉冲到一行像素数据开始输出的延迟 hsync<==>DEN u32 right_margin; // 一行像素数据输出完毕到下一行的行扫描开始脉冲间的延迟 DEN <==>hsync u32 upper_margin; // 帧扫描开始脉冲到第一行像素数据开始输出的延迟 vsync<==>DEN(1st line) u32 lower_margin; // 最后一行像素数据输出结束到下一帧的那帧扫描开始脉冲间的延迟DEN(last line)<==>vsync u32 hsync_len; // 行扫描脉冲宽度,单位为pixclock u32 vsync_len; // 帧扫描脉冲宽度,单位为line u32 sync; // 各同步信号的极性定义,如hsync、vsync、DEN的极性等。 u32 vmode; // 显示模式,逐行还是隔行扫描 u32 flag; // 一般为0 };
5、struct fb_ops *fbops; 这个结构体是LCDframebuffer操作中最重要的一个,也就是说上面做了LCD的相关设置那只是在设置LCD中的硬件寄存器, 如果你想点亮LCD屏顺便操作它,那么这个结构体必不可少。 struct fb_ops { int (*fb_open)(struct fb_info *info, int user); int (*fb_release)(struct fb_info *info, int user); ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos); ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos); int (*fb_set_par)(struct fb_info *info); int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info) int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); …………… }
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #define RGB(r,g,b)((r<<16)|(g<<8)|b) #define WIDTH 1280 #define HIGHT 1024 static int Frame_fd ; static int *FrameBuffer = NULL ; static int W , H ; //写framebuffer int Write_FrameBuffer(const char *buffer); int main(void) { 1、设置长宽,打开fb设备 W = 1024 ; H = 768 ; Frame_fd = open("/dev/fb0" , O_RDWR); if(-1 == Frame_fd){ perror("open frame buffer fail"); return -1 ; } 2、对framebuffer进行内存映射mmap //头文件 <sys/mman.h> //函数原型:void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset); //start:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。 //length:映射区的长度。//长度单位是 以字节为单位,不足一内存页按一内存页处理 //prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起 //flags:相关的标志,就跟open函数的标志差不多的,自己百度去查 //fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时需要指定flags参数中的MAP_ANON,表明进行的是匿名映射。 //off_toffset:被映射对象内容的起点。 //PROT_READ //页内容可以被读取 //PROT_WRITE //页可以被写入 //MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。 FrameBuffer = mmap(0, 1280*1024*4 , PROT_READ | PROT_WRITE , MAP_SHARED , Frame_fd ,0 ); if(FrameBuffer == (void *)-1){ perror("memory map fail"); return -2 ; } 3、对framebuffer写数据 char buffer[WIDTH*HIGHT*3]; //我们要写入的数据 while(1) { Write_FrameBuffer(buffer); printf("count:%d \n" , count++); } 4、退出framebuffer munmap(FrameBuffer , W*H*4); //解除内存映射 close(Frame_fd); //关闭文件描述符 return 0 ; } //写framebuffer int Write_FrameBuffer(const char *buffer) { int row , col ; char *p = NULL ; //遍历分辨率1024*1280的所有像素点 for(row = 0 ; row <1024 ; row++){ for(col = 0 ; col < 1280 ; col++){ if((row < H) && (col < W)){ p = (char *)(buffer + (row * W+ col ) * 3); //转RGB格式 FrameBuffer[row*1280+col] = RGB((unsigned char)(*(p+2)),(unsigned char)(*(p+1)),(unsigned char )(*p)); } } } return 0 ; }
我的CSDN博客: http://blog.csdn.net/morixinguan/article/month/2015/12