im6ull学习总结(二)Framebuffer 应用编程

2023-12-28 21:28

本文主要是介绍im6ull学习总结(二)Framebuffer 应用编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 LCD操作原理

linux中通过framebuffer驱动程序来控制LCD。framebuffer中包含LCD的参数,大小为LCD分辨率xbpp。framebuffer 是一块内存 内存中保存了一帧图像。
关于图像的帧指的是在图像处理中,一帧(Frame)是指图像序列中的单个静止图像。当连续的图像以每秒多帧的速度播放时,就可以产生动画、视频或电影。每一帧都是由像素组成的二维网格,每个像素都包含颜色和亮度信息。通过在连续的帧之间进行快速切换,人眼会感知到连续的动态效果。因此,一帧是构成动画和视频的基本单元。
LCD的操作过程
1、驱动程序设置好LCD控制器
根据 LCD 的参数设置 LCD 控制器的时序、信号极性;
根据 LCD 分辨率、BPP 分配 Framebuffer。
2、APP 使用 ioctl 获得 LCD 分辨率、BPP
3、APP 通过 mmap 映射 Framebuffer,在 Framebuffer 中写入数据
在这里插入图片描述
假设需要设置 LCD 中坐标(x,y)处像素的颜色,首要要找到这个像素对应的内存,然后根据它的 BPP 值设置颜色。也就是找到内存所对应的地址然后给他赋值。假设 fb_base 是 APP 执行 mmap 后得到的 Framebuffer 地址(首地址)
在这里插入图片描述
计算公式
(x,y)像素起始地址=fb_base+(xres*bpp/8)y + xbpp/8
xres:x方向分辨率bpp每个像素的位数
/8:将位数换算成字节
y y坐标这里从第0行开始所以不用减1
x x坐标
bpp :每个像素的位数bits per pixel
有RGB888 565 555格式
在这里插入图片描述
对于 32BPP,一般只设置其中的低 24 位,高 8 位表示透明度,一般的 LCD都不支持。
对于 24BPP,硬件上为了方便处理,在 Framebuffer 中也是用 32 位来表示,效果跟 32BPP 是一样的。
对于 16BPP,常用的是 RGB565;很少的场合会用到 RGB555,这可以通过ioctl 读取驱动程序中的 RGB 位偏移来确定使用哪一种格式
这里补充一下寻址方式一般为字节寻址也就是说一个地址对应的一个储存单元能储存8位数据。

实验一 并画一条直线

#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
static struct fb_var_screeninfo var;
static int  fd_fb;
static unsigned int screen_size;
static unsigned int line_width;
static unsigned int pixel_width;
static unsigned char *fb_base;
static void  lcd_put_pixel(int x, int y,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;//printf("*pen_8= %d\n",*pen_8);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;// printf("*pen_16= %d\n",*pen_16);break;}case 32:{*pen_32 = color;// printf("*pen_32= %d\n",*pen_32);break;}default:{printf("can't surport %dbpp\n", var.bits_per_pixel);break;}}
}
int main(char argc, char **argv)
{int i;//这里我先提个问题如何确定设备驱动文件的/* 以只读方式打开驱动设备文件 */fd_fb = open("/dev/fb0", O_RDWR);if(fd_fb<0){printf("cannot open /dev/fb0 \n");return -1;}/* fd_fb:是一个打开的 Framebuffer 设备文件的文件描述符。
FBIOGET_VSCREENINFO:是一个常量宏,表示获取可见屏幕信息的操作。
&var:是一个指向 vscreeninfo 结构体的指针,用于接收获取到的可见屏幕信息。 */// ioctl成功返回 失败-1if (ioctl(fd_fb, FBIOGET_VSCREENINFO,&var)){printf("can not get var \n");return -1;}/* 一行的字节数 */line_width = var.xres *var.bits_per_pixel/8;/* bpp转换成字节 */pixel_width =  var.bits_per_pixel/8;screen_size = var.xres*var.yres*var.bits_per_pixel/8;printf("var.bits_per_pixel= %d\n",var.bits_per_pixel);/* MAP_SHARED 表示映射区域与其他进程共享。0:表示映射区域在文件中的偏移量,此处为从文件开头开始映射。*/fb_base=(unsigned char *)mmap(NULL  ,screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);/* mmap 调用失败,它会返回 MAP_FAILED(通常定义为 (void *)-1) */if(fb_base == (unsigned char *) -1){printf("can not mmap \n");return -1;}memset(fb_base, 0xff, screen_size);for ( i = 0; i < 100; i++){lcd_put_pixel(var.xres/2+i,var.yres/2,0xFF0000);}munmap(fb_base, screen_size);close(fd_fb);return 0;
}

实验效果
在屏幕中间从左至右画了一条横线
终端打印出:var.bits_per_pixel= 32
这里我有几个问题
1、mmap返回值转换成uchar*类型: 这时注意地址并没有变地址这个指针操作系统是多少位他就永远是多少位,他指向的内容也不会变,只是寻址方式发生变化
在这里插入图片描述
就比如我们看datasheet stm32 的一个寄存器偏移地址为0x00而下一个为0x04 他就是以四个字节递增的。
再比如我们从flash中读取一段数据 要区分半字读还是字读。

2、这引入了第二个问题
在这里插入图片描述
x++后地址偏移的字节数是根据pixel_width决定的 pixel_width = var.bits_per_pixel/8; var.bits_per_pixel 为32位那么一次偏移4个字节刚好32位存储32位数据
在这里插入图片描述
也就是说2进制编码中一个地址存放1位数据0/1 0x1000 到0x1004 则跨了四个字节32位能存储32位数据。

这篇关于im6ull学习总结(二)Framebuffer 应用编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/547357

相关文章

CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比

《CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比》CSS中的position属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布... css 中的 position 属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布局和层叠关

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Python使用Tkinter打造一个完整的桌面应用

《Python使用Tkinter打造一个完整的桌面应用》在Python生态中,Tkinter就像一把瑞士军刀,它没有花哨的特效,却能快速搭建出实用的图形界面,作为Python自带的标准库,无需安装即可... 目录一、界面搭建:像搭积木一样组合控件二、菜单系统:给应用装上“控制中枢”三、事件驱动:让界面“活”

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Python Flask 库及应用场景

《PythonFlask库及应用场景》Flask是Python生态中​轻量级且高度灵活的Web开发框架,基于WerkzeugWSGI工具库和Jinja2模板引擎构建,下面给大家介绍PythonFl... 目录一、Flask 库简介二、核心组件与架构三、常用函数与核心操作 ​1. 基础应用搭建​2. 路由与参