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

相关文章

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

SpringShell命令行之交互式Shell应用开发方式

《SpringShell命令行之交互式Shell应用开发方式》本文将深入探讨SpringShell的核心特性、实现方式及应用场景,帮助开发者掌握这一强大工具,具有很好的参考价值,希望对大家有所帮助,如... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.