Framebuffer 应用编程

Frame的意思是帧,buffer的意思是缓冲区。Framebuffer就是一块内存(硬件设备),里面保存着一帧图像。

ioctl()函数解析

ioctl()函数非常强大。不同的驱动程序内部会实现不同的 ioctl() ,可以使用各种 ioctl() 跟驱动程序交互:可以传数据给驱动程序,也可以从驱

动程序中读出数据。

头文件:

#include <sys/ioctl.h>

函数原型:

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

函数说明:

① fd 表示文件描述符;

② request 表示与驱动程序交互的命令, 用不同的命令控制驱动程序输出我们需要的数据;

③ … 表示可变参数 arg, 根据 request 命令,设备驱动程序返回输出的数据。

④ 返回值: 打开成功返回0,失败将返回-1

实现步骤

1.获取framebuffer描述符

fd_fb = open("/dev/fb0", O_RDWR);  //可读可写
if(fd_fb == -1) {
printf("can not open /dev/fb0\n");
return -1;
}

2.获取屏幕可变参数

if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址。FBIOGET_VSCREENINFO是获取可变参数(fb.h)
printf("can not get var\n");
return -1;
}

3.计算framebuffer空间大小

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; //单位:字节
fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if(fb_base == (unsigned char*)-1) {
printf("can not mmap\n");
return -1;
}

4.不同的RGB格式转换

switch(var.bits_per_pixel)
{
case 8:
{
/*代码*/
break;
}
case 16:
{
/* 32位转换为RGB565 */
red = (color >> 16) & 0xff; //保留17-24位
green = (color >> 8) & 0xff; //保留8-16位
blue = (color >> 0) & 0xff; //保留0-8位
color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); //组合为16bit
*add_16 = color; //像素点对应的地址空间赋值
break;
}
case 32:
{
*add_32 = color;
break;
}
default:
printf("can't surport %dbpp\n", var.bits_per_pixel);
break;
}

完整程序如下:

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h> int fd_fb; //文件描述符
int screen_size; //屏幕总字节数(framebuffer的大小)
struct fb_var_screeninfo var;
unsigned char *fb_base;
unsigned int line_width; //行字节
unsigned int pixel_width; //像素字节 void lcd_put_pixel(int x, int y, unsigned int color) {
unsigned char *add_8 = fb_base + y*line_width + x*pixel_width; //像素点对应的内存地址
unsigned short *add_16;
unsigned int *add_32; unsigned int red, green, blue; add_16 = (unsigned short*)add_8; //8位转换为16位
add_32 = (unsigned int*) add_8; switch(var.bits_per_pixel)
{
case 8:
{
/*代码*/
break;
}
case 16:
{
/* 32位转换为RGB565 */
red = (color >> 16) & 0xff; //保留17-24位
green = (color >> 8) & 0xff; //保留8-16位
blue = (color >> 0) & 0xff; //保留0-8位
color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); //组合为16bit
*add_16 = color; //像素点对应的地址空间赋值
break;
}
case 32:
{
*add_32 = color;
break;
}
default:
printf("can't surport %dbpp\n", var.bits_per_pixel);
break;
} } int main(int argc, char **argv)
{
int i; /* 1.获取framebuffer描述符 */
fd_fb = open("/dev/fb0", O_RDWR); //可读可写
if(fd_fb == -1) {
printf("can not open /dev/fb0\n");
return -1;
} /* 2.获取屏幕可变参数 */
if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址
printf("can not get var\n");
return -1;
} /* 3.计算framebuffer空间大小 **/
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; //单位:字节
fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if(fb_base == (unsigned char*)-1) {
printf("can not mmap\n");
return -1;
} /* 清屏: 全部设为白色 */
memset(fb_base, 0xff, screen_size); /* 随便设置出100个为蓝色 */
for (i = 0; i < 100; i++)
lcd_put_pixel(var.xres/2+i, var.yres/2, 0x0000FF); munmap(fb_base , screen_size);
close(fd_fb); return 0;
}

嵌入式Linux—Framebuffer应用编程的更多相关文章

  1. 嵌入式linux的网络编程(1)--TCP/IP协议概述

    嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...

  2. 嵌入式Linux下Camera编程--V4L2【转】

    转自:http://blog.csdn.net/fwqlzz/article/details/51126653 版权声明:本文为博主原创文章,未经博主允许不得转载. USB video class(又 ...

  3. 嵌入式Linux串口编程简介

    文章目录 简介 用到的API函数 代码 简介 嵌入式Linux下串口编程与Linux系统下的编程没有什么区别,系统API都是一样的.嵌入式设备中串口编程是很常用的,比如会对接一些传感器模块,这些模块大 ...

  4. 常见的嵌入式linux学习和如何选择ARM芯片问答

    常见的ARM嵌入式学习问答,设计者和学习者最关心的11个问题: 1.          ARM嵌入式是学习硬件好还是学习软件好? 2.          嵌入式软件和硬件,哪一种职位待遇更高?或者说, ...

  5. 嵌入式linux多进程编程

    嵌入式linux多进程编程 在主程序显示文本菜单.提供例如以下服务.要求每一个服务都通过生成子进程来提供. 服务包含:日历信息显示,日期信息显示,推断闰年服务,文件复制功能,数字排序功能.退出功能. ...

  6. 从裸机编程到嵌入式Linux编程思想的转变------分而治之:驱动和应用程序

    笔者学习嵌入式Linux也有一段时间了,很奇怪的是很多书讲驱动编程方面的知识,也有很多书将ARM9方面的知识,但是从以前51形式的(对寄存器直接操作,初始化芯片的功能模块)编程方法,和思维模式,变换为 ...

  7. 《嵌入式linux应用程序开发标准教程》笔记——6.文件IO编程

    前段时间看APUE,确实比较详细,不过过于详细了,当成工具书倒是比较合适,还是读一读这种培训机构的书籍,进度会比较快,遇到问题时再回去翻翻APUE,这样的效率可能更高一些. <嵌入式linux应 ...

  8. Yocto开发笔记之《嵌入式linux libcurl编程》(QQ交流群:519230208)

    开了一个交流群,欢迎爱好者和开发者一起交流,转载请注明出处. QQ群:519230208,为避免广告骚扰,申请时请注明 “开发者” 字样 =============================== ...

  9. Linux Framebuffer驱动剖析之一—软件需求

    嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT两方面的原创技术分享,稍后会发布嵌入式企鹅圈的2 ...

  10. 嵌入式linux GUI--DirectFB + GTK至尊秘笈

    前言 数年前,曾经开发过一个嵌入式的产品,如今市场依然存在,但由于电子产品的升级换代很快,许多元器件都采购不到了,为了延续产品的生命周期,计划在linux平台上开发新的版本.而在linux上的GUI上 ...

随机推荐

  1. HMM算法python实现

    基础介绍,后5项为基础5元素 Q = ['q0', 'q1', 'q2', 'q3'] # 状态集合 States,共 N 种状态 V = ['v0', 'v1'] # 观测集合 Observatio ...

  2. perl使用print输入数据到文件

    #!usr/bin/perl use utf8; #引入utf8模块 脚本内的字符串使用utf8作为编码格式 binmode(STDOUT,":encoding(gbk)"); # ...

  3. 一文详解GaussDB(DWS) 的并发管控和内存管控

    摘要:DWS的负载管理分为两层,第一层为cn的全局并发控制,第二层为资源池级别的并发控制. 本文分享自华为云社区<GaussDB(DWS) 并发管控&内存管控>,作者: fight ...

  4. C温故补缺(七):函数指针与回调函数

    函数指针与回调函数 函数指针就是指向函数调用栈地址的指针,定义时须和函数的返回值类型,参数类型相同 如: #include<stdio.h> int max(int x,int y){ r ...

  5. 8 STL-stack

    ​ 重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦!  生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦! 写在前面,本篇章主要介绍S ...

  6. 基于jenkins+kubernetes的cicd流程实践一:环境搭建及方案原理实现

    1.基础环境:Centos7.9,kubernetes:v1.21.5 node-1@112(master):docker,containerd,harbornginx(80),git,etcd no ...

  7. 【每日一题】【BFS&Lambda&重建二叉树】2022年2月15日-根据先序中序重建并输出二叉树的右视图

    描述 请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图 思路:重建&层次遍历记录最后一个&Lambda表达式 答案: import java.util.*; publ ...

  8. live-player live-pusher惨案

    昨天遇到的问题,旧项目: 一个页面同时使用live-player和live-pusher时候遇到的问题,live-pusher正常,live-player无效,没有任何报错 打log 所有livepl ...

  9. docker部署项目

    @ 目录 前言 一.下载安装docker: 1.前提工作 1.1 查看linux版本 1.2 yum包更新到最新 1.3 安装工具包 1.4 设置yum源并更新yum包索引 2.安装docker 2. ...

  10. Linux开发板连接WPA加密的AP路由器

    Linux目前有两种方法配置网络: wireless-tools wpa_supplicant iw支持的驱动较多,但只支持WEP加密:wpa_supplicant有部分驱动支持不完善,但支持WEP. ...