Linux 应用基础 Framebuffer应用编程

简介: 在 Linux应用基础中,Framebuffer 驱动程序主要用来控制 LCD。今天带大家来了解一下如何通过 Framebuffer 来编程 LCD。在此之前,我们要先了解一下 Framebuffer 和 LCD。

前言


在 Linux应用基础中,Framebuffer 驱动程序主要用来控制 LCD。今天带大家来了解一下如何通过 Framebuffer 来编程 LCD。

在此之前,我们要先了解一下 Framebuffer 和 LCD。


一、了解Framebuffer


Frame是帧的意思,buffer是缓冲的意思,这意味着 Framebuffer 就是一块内存,里面保存着一帧图像。Framebuffer 中保存着一帧图像的每一个像素颜色值,假设LCD的分辨率是1024x768,每一个像素的颜色用32位来表示,那么Framebuffer的大小就是:1024x768x32/8=3145728字节。


二、了解LCD


1.LCD的操作原理


① 根据LCD分辨率、BPP分配Framebuffer

② APP使用ioctl获得LCD分辨率、BPP

③ APP通过mmap映射Framebuffer,在Framebuffer中写入数据


2.LCD坐标

1879f22b89ba737512dbafd66c5580f.png



假设 fb_base 是APP执行 mmap 后得到的Framebuffer地址,可以用以下公式算出(x,y)坐标处像素对应的Framebuffer地址:

(x,y)像素起始地址=fb_base + (xres*bpp/8) * y + x * bpp / 8


三. Framebuffer 程序分析


1. 打开设备:(open)


open (const char pathname, int flags) ;

pathname: 表示打开文件的路径。


73      fd_fb = open("/dev/fb0", O_RDWR);
74      if (fd_fb < 0)
75      {
76              printf("can't open /dev/fb0\n");
77              return -1;
78      }


fd_fb: 打开 LCD 设备返回的文件句柄。

/dev/fb0 :LCD的设备节点。

Flags表示打开文件的方式。


2. 获取LCD参数 : ( ioctl )


ioctl ( int fd, unsigned long request, …);

fd : 文件句柄。


12 static struct fb_var_screeninfo var; /* Current var */
……
79      if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
80      {
81              printf("can't get var\n");
82              return -1;
83      }


FBIOGET_VSCREENINFO : 它表示get var screen info,获得屏幕的可变信息.

获取 lcd 屏幕的信息,并将其存放在 var 结构体中。以下是 var 结构体:


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. 映射 framebuffer: ( mmap )

void *mmap ( void *addr, size_t length, int prot, int flags, int fd, off_t offset);


要映射一块内存,需要知道它的地址──这由驱动程序来设置,需要知道它的大小──这由应用程序决定。


85      line_width  = var.xres * var.bits_per_pixel / 8;
86      pixel_width = var.bits_per_pixel / 8;
87      screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
88      fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
89      if (fb_base == (unsigned char *)-1)
90      {
91              printf("can't mmap\n");
92              return -1;
93      }


screen_size : 代表整个 framebuffer 的大小。

fb_base : framebuffer 是存在于驱动程序中的,在应用程序中无法使用。则需要使用 mmap 将驱动程序的内存映射到应用程序中。


四. 描点函数: ( lcd_put_pixel )


大家在 lcd 上显示字符时,需要进行描点。pen_8,pen_16,pen_32都是起笔点。不同的只需要将pen_8变换一下即可。

void lcd_put_pixel(int x, int y, unsigned int color)
{
  unsigned char *pen_8 = fb_base+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月前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
8天前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
26 5
|
21天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
23天前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
2月前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
2月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
95 6
|
2月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
140 3
|
2月前
|
Shell Linux Python
python执行linux系统命令的几种方法(python3经典编程案例)
文章介绍了多种使用Python执行Linux系统命令的方法,包括使用os模块的不同函数以及subprocess模块来调用shell命令并处理其输出。
36 0
|
3月前
|
项目管理 敏捷开发 开发框架
敏捷与瀑布的对决:解析Xamarin项目管理中如何运用敏捷方法提升开发效率并应对市场变化
【8月更文挑战第31天】在数字化时代,项目管理对软件开发至关重要,尤其是在跨平台框架 Xamarin 中。本文《Xamarin 项目管理:敏捷方法的应用》通过对比传统瀑布方法与敏捷方法,揭示敏捷在 Xamarin 项目中的优势。瀑布方法按线性顺序推进,适用于需求固定的小型项目;而敏捷方法如 Scrum 则强调迭代和增量开发,更适合需求多变、竞争激烈的环境。通过详细分析两种方法在 Xamarin 项目中的实际应用,本文展示了敏捷方法如何提高灵活性、适应性和开发效率,使其成为 Xamarin 项目成功的利器。
53 1
|
3月前
|
网络协议 Linux Shell
探索Linux操作系统:从基础到高级编程
【8月更文挑战第31天】本文旨在为读者提供一条清晰的路径,从Linux操作系统的基础知识出发,逐步深入到高级编程技巧。我们将一起揭开Linux神秘的面纱,了解其内部工作原理,并通过实际代码示例加深理解。无论你是初学者还是有一定经验的开发者,这篇文章都将为你带来新的视角和技能提升。