Linux下的Framebuffer编程

简介: Linux下的Framebuffer编程

前言

本篇文章将会介绍Linux下的Framebuffer编程,这里将会引用到百问网韦东山老师讲的一些知识。


一、LCD操作原理

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


二、代码解析及编写程序的步骤

0.定义各类参数

下面这些参数后面我们会一 一介绍。

int fd_fb;
struct fb_var_screeninfo var; /* Current var */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;

1.打开LCD设备节点

这些的fd_fb就是打开LCD设备返回的文件句柄。

/dev/fb0 :LCD设备节点(根据自己板子上面的节点填写)

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


  if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
  {
    printf("can't get var\n");
    return -1;
  }

var结构体解析:

这个结构体里面保存了LCD的相关信息,比如xres和yres就是代表了x方向的分辨率和y方向的分辨率。

大家的手机都有分辨率,最常见的就是1080×1920了。对应到xres和yres就是xres=1080,yres=1920。

大家只需要知道var这个结构体是用来保存ioctl获取到的LCD的参数信息即可。

bits_per_pixel:每一个像素的颜色用多少位表示

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.mmap映射Framebuffer,在Framebuffer中写入数据

line_width:var.xres * var.bits_per_pixel代表每一行有多少个像素

/8就代表了每一行有多少个字节

pixel_width :每一个像素多少个字节

screen_size :计算出整个屏幕所占字节的大小

fbmem :Framebuffer是存在于驱动程序当中的,在应用程序中不可直接使用,需要使用mmap将驱动程序的内存映射到应用程序中才可进行操作。

  line_width  = var.xres * var.bits_per_pixel / 8;
  pixel_width = var.bits_per_pixel / 8;
  screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
  fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
  if (fbmem == (unsigned char *)-1)
  {
    printf("can't mmap\n");
    return -1;
  }

三、LCD操作函数解析

1.描点函数

pen_8 ,pen_16,pen_32参数代表的是起笔点,因为我使用的LCD每个像素是8位的,所以我这里只需要计算pen_8 即可,其他两个只需要进行一次转换即可。

pen_8 的计算

0bdf3f4457604ee9bb4eb0a1ef057695.png

void lcd_put_pixel(int x, int y, unsigned int color)
{
  unsigned char *pen_8 = fbmem+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.显示字符函数

void lcd_put_ascii(int x, int y, unsigned char c, unsigned int color)
{
  unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
  int i, b;
  unsigned char byte;
  for (i = 0; i < 16; i++)
  {
    byte = dots[i];
    for (b = 7; b >= 0; b--)
    {
      if (byte & (1<<b))
      {
        /* show */
        lcd_put_pixel(x+7-b, y+i, color); /* 白 */
      }
      else
      {
        /* hide */
        lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
      }
    }
  }
}

总结

本篇文章就介绍到这里,Framebuffer编程的编程其实并不算很难,大家只要理清楚这些参数即可。具体的代码请参考百问网,这里我只做重要部分介绍。

相关文章
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
11月前
|
安全 算法 Ubuntu
Linux(openssl)环境:编程控制让证书自签的技巧。
总结:在Linux环境中,OpenSSL是一个非常实用的工具,可以帮助我们轻松地生成自签名证书。通过上述三个简单步骤,即可为内部网络、测试环境或开发环境创建自签名证书。但在公共访问场景下,建议购买经过权威认证机构签发的证书,以避免安全警告。
582 13
|
JavaScript Ubuntu Linux
如何在阿里云的linux上搭建Node.js编程环境?
本指南介绍如何在阿里云Linux服务器(Ubuntu/CentOS)上搭建Node.js环境,包含两种安装方式:包管理器快速安装和NVM多版本管理。同时覆盖全局npm工具配置、应用部署示例(如Express服务)、PM2持久化运行、阿里云安全组设置及外部访问验证等步骤,助你完成开发与生产环境的搭建。
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
279 26
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
304 17
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
714 13
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
989 6
|
Shell Linux Python
python执行linux系统命令的几种方法(python3经典编程案例)
文章介绍了多种使用Python执行Linux系统命令的方法,包括使用os模块的不同函数以及subprocess模块来调用shell命令并处理其输出。
1018 0