02-基于GEC6818开发板的画正方形、画圆的操作——使用mmap映射提高效率

news2025/2/5 4:54:37

02-基于GEC6818开发板的画正方形、画圆的操作——使用mmap映射提高效率

本文主要是在01-基于粤嵌GEC6818实现屏幕的显示固定颜色进行自动切换-点击前往的基础上进行了进一步的更改,之前那个在切换时会有一定的花屏,是因为其效率低的原因,本文就对其将进行了优化。
包括实例:
1.使用mmap函数优化切换不同屏幕颜色的效率
2.在屏幕上画正方形
3.在屏幕上画一个圆形

文章目录

  • 02-基于GEC6818开发板的画正方形、画圆的操作——使用mmap映射提高效率
    • 一、 效率提高
      • 1.1 mmap 映射
      • 1.2 munmap 取消映射
    • 二、 练习使用
      • 2.1 练习1:使用mmap函数优化切换不同屏幕颜色的效率
      • 2.2 练习2:在屏幕上画正方形
      • 2.3 练习3: 在屏幕上画一个圆形

一、 效率提高

需要进行状态切换(内核态——应用态)以及需要从应用层到fb0到底层hardware,需要进行两次搬砖,所以导致效率低下,会在颜色切换的时候有异色横线。
解决方案:
映射

1.1 mmap 映射

NAME
       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS
       #include <sys/mman.h>

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

mmap函数

  • 功能:将一个文件或设备映射到进程的地址空间。
  • 参数
    • addr:期望的映射起始地址。通常设置为NULL,让系统选择一个合适的地址。(如果自己设计则需要选择内存为空闲的地址,自己难以知道确定)
    • length:映射的长度。文件有多大就设置多大,注意要以页为单位,一页就是 4K。不足一页会补齐一页。
    • prot:保护标志(权限)。指定了内存映射区域的保护模式,如读、写、执行等。一般这个权限要根据fd进行设置。
        PROT_EXEC  Pages may be executed.

       PROT_READ  Pages may be read.

       PROT_WRITE Pages may be written.

       PROT_NONE  Pages may not be accessed.
  • 续参数
    • flags:控制映射的各种属性,如共享性、映射标志等。
      • MAP_SHARED 公有映射-对内核的操作直接影响文件
      • MAP_PRIVATE 私有映射-开辟一个自己的空间,不会影响文件
    • fd:文件描述符,指向要映射的文件。
    • offset:文件中的偏移量,从这个偏移量开始映射。
  • 返回值:成功后会返回映射后的首地址;失败返回NONE,同时Errno被设置。

1.2 munmap 取消映射

munmap函数

  • 功能:取消映射一个之前由mmap创建的内存区域。
  • 参数
    • addr:要取消映射的内存区域的起始地址。
    • length:要取消映射的长度。
      使用mmapmunmap,您可以实现高效的文件和设备访问,同时还可以利用内存映射的特性,如零拷贝、共享内存等。

需要注意的是,使用这些函数时应谨慎处理,确保内存映射的正确性和安全性。在使用这些函数时,通常需要考虑与其他系统调用和操作系统接口的交互,以确保程序的正确性和稳定性。

二、 练习使用

2.1 练习1:使用mmap函数优化切换不同屏幕颜色的效率

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>

#define WIDTH 800
#define HEIGHT 480

int main() {
    int fd = open("/dev/fb0", O_RDWR);
    if (fd == -1) {
        perror("open file error");
        exit(1);
    }

    // 计算需要映射的大小
    size_t screensize = WIDTH * HEIGHT * 4;

    // 使用mmap映射到内核空间
    int *fbp = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ((intptr_t)fbp == -1) {
        perror("mmap error");
        exit(1);
    }

    int color1[WIDTH * HEIGHT];
    int color2[WIDTH * HEIGHT];
    int i;
    for (i = 0; i < WIDTH * HEIGHT; i++) {
        color1[i] = 0x00FF00;  // green
        color2[i] = 0xFF0000;  // red
    }

    while (1) {
        // 将color1写入映射的内存
        memcpy(fbp, color1, screensize);
        sleep(1);

        // 将color2写入映射的内存
        memcpy(fbp, color2, screensize);
        sleep(1);
    }

    // 取消映射并关闭文件描述符
    munmap(fbp, screensize);
    close(fd);

    return 0;
}

2.2 练习2:在屏幕上画正方形

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>


int lcd_fd = -1;//全局的lcd描述符

unsigned int* plcd = NULL ;

void lcdinit()
{
    lcd_fd = open("/dev/fb0", O_RDWR);
    if (-1 == lcd_fd)
    {
        perror("open fb0 error");
        exit(1);
    }
    plcd = mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (plcd == MAP_FAILED) {
        perror("mmap error");
        return;
}


}
void lcd_destory()
{
    munmap(plcd,800*400*4);
    close(lcd_fd);
}


/*画点函数
* 传入参数:
* (x,y)需要画点的坐标
*   color:(x,y)点的颜色
*/
void point(int x,int y, unsigned int color)
{
    if(x>0&&x<800&&y>=0&&y<480)
    {
        *(plcd+y*800+x)=color;//给这个点赋值color
    }
}

/*函数:画一个方块
* 传入参数:
* w: 正方形的宽
* h: 正方形的高
* x0: 需要画在x0的位置
* y0: 需要画在y0的位置
* color : 需要画的颜色
* 返回值:NULL
*/
void display_sql(int w,int h, int x0, int y0,int color)
{
    int x,y;
    for(y=0;y< h;y++)
    {
        for(x=0;x<w;x++)
        {
            point(x+x0,y+y0,color);//在x0,y0开始的位置开始画点
        }
    }
}
int main()
{
    int  r1,r2;
    lcdinit();
    //操作屏幕
    display_sql(200,200,100,100,0xff0000);
    display_sql(200,200,400,100,0xff);
    lcd_destory();
    return 0;
}


2.3 练习3: 在屏幕上画一个圆形

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <math.h> 

int lcd_fd = -1; // 全局的lcd描述符
unsigned int* plcd = NULL;

void lcdinit() {
    lcd_fd = open("/dev/fb0", O_RDWR);
    if (-1 == lcd_fd) {
        perror("open fb0 error");
        exit(1);
    }
    plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (plcd == MAP_FAILED) {
        perror("mmap error");
        return;
    }
}

void lcd_destory() {
    munmap(plcd, 800 * 480 * 4);
    close(lcd_fd);
}

void point(int x, int y, unsigned int color) {
    if (x >= 0 && x < 800 && y >= 0 && y < 480) {
        *(plcd + y * 800 + x) = color;
    }
}

void display_sql(int w, int h, int x0, int y0, int color) {
    int x, y;
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            point(x + x0, y + y0, color);
        }
    }
}

void fill_circle(int xc, int yc, int r, unsigned int color) {
    int x = 0, y = r;
    int d = 3 - 2 * r;

    while (x <= y) {
        // 画圆弧上的水平线
        for (int i = xc - x; i <= xc + x; i++) {
            point(i, yc - y, color);
            point(i, yc + y, color);
        }

        // 画圆弧上的垂直线
        for (int i = xc - y; i <= xc + y; i++) {
            point(i, yc - x, color);
            point(i, yc + x, color);
        }

        if (d < 0) {
            d = d + 4 * x + 6;
        } else {
            d = d + 4 * (x - y) + 10;
            y--;
        }
        x++;
    }
}

int main() {
    lcdinit();

    display_sql(200, 200, 100, 100, 0xff0000);
    display_sql(200, 200, 400, 100, 0xff);

    // 画一个填充的黄色圆形
    fill_circle(300, 240, 50, 0xffff00);

    lcd_destory();
    return 0;
}

实现效果图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1328291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

猜数字游戏 C语言xdoj490

问题描述 猜数字游戏是令游戏机随机产生一个 100 以内的正整数&#xff0c;用户输入一个数对其进行猜测&#xff0c;需要你编写程序自动对其与随机产生的被猜数进行比较&#xff0c;并提示大了&#xff08;“Too big”&#xff09;&#xff0c;还是小了&#xff08;“Too smal…

GBASE南大通用数据库提供的高可用负载均衡功能

GBASE南大通用GBase 8a ODBC 提供的高可用负载均衡功能是指&#xff0c;GBase 8a ODBC 会将客户 端请求的数据库集群连接平均分摊到集群所有可用的节点上。 GBASE南大通用数据库负载均衡的使用方法 GBASE南大通用GBase 8a ODBC 提供两种方式来使用高可用负载均衡。一种是配置数…

Ubuntu 20.4镜像国内地址下载较快

Ubuntu20.04版本比较稳定&#xff0c;部署OJ大都用这个版本。 推荐阿里云镜像点&#xff0c;点进去根据你的电脑版本下载iso后缀那个 ubuntu-releases-20.04安装包下载_开源镜像站-阿里云 下载速度较快 其他版本 http://mirrors.aliyun.com/ubuntu-releases/ 如果使用云服务…

图像畸变校正解决方案,无畸变的高质量视觉体验

摄像头已经成为我们生活中不可或缺的一部分。然而&#xff0c;由于摄像头的物理特性和环境因素&#xff0c;采集到的图像往往存在径向和切向畸变&#xff0c;导致画面扭曲&#xff0c;影响视觉效果。为了解决这个问题&#xff0c;美摄科技推出了一款先进的图像畸变校正解决方案…

Java网络编程---UDP

客户端 import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner;public class Client {public static void main(String[] args) throws Exception {//1.创建客户端对象DatagramSocket socket new Datagra…

node实现简单的数据爬虫

前言 我使用的是墨迹天气的页面&#xff0c;因为这个使用的链接简单 页面结构简单并且大都是文字形式 第一步 打开墨迹天气网址 随便点开一个页面 点击F12或者鼠标右键点击检查 查看页面的信息 分析页面内容 使用文字所在的class和标签来定位 编写代码 配置express环境 …

vscode中vue项目报错

当在vscode中写代码时&#xff0c;报错报错报错......... 已经头大&#xff0c;还没写就报错&#xff0c; 这是因为eslint对语法的要求太过严格导致的编译时&#xff0c;出现各种语法格式错误 我们打开vue.config.js&#xff0c;加上这句代码&#xff0c;就OK啦 lintOnSave:…

Python基本数据类型详解,新手小白入门必学

文章目录 1.注释2.输出3.变量4.命名规范5.变量的定义方式1.字符串类型2.数字类型3.List列表类型4.tuple 元组类型的定义5.Dict字典类型6.set集合类型7.数据类型转换8.自动类型转换9.强制类型转换Python技术资源分享1、Python所有方向的学习路线2、学习软件3、入门学习视频4、实…

关于“Python”的核心知识点整理大全35

目录 13.3.4 重构 create_fleet() game_functions.py 13.3.5 添加行 game_functions.py alien_invasion.py 13.4 让外星人群移动 13.4.1 向右移动外星人 settings.py alien.py alien_invasion.py game_functions.py 13.4.2 创建表示外星人移动方向的设置 13.4.3 检…

2023 英特尔On技术创新大会直播 | AI魅力的生活化

目录 前言正文 前言 依稀记得去年的直播大会&#xff0c;主要展现了其灵活、加速和半集成化的独特优势&#xff0c;广泛应用于人工智能、5G通信、边缘计算以及视觉图像处理等领域&#xff0c;不断提供领先的性能、能效和可编程性的创新。 如今又带来一些不一样的特色&#xf…

大一C语言作业题目1

目录 字符串和字符数组&#xff1f; %s found的变化&#xff1a; 7-1 学生成绩录入及查询 学生成绩表中&#xff0c;一名学生的信息包含如下信息&#xff1a; 学号(11位)、姓名、数学成绩、英语成绩、程序设计成绩、物理成绩。 本题要求编写程序&#xff0c;录入N条学生的…

IDEA 设置 SpringBoot logback 彩色日志(附配置文件)

1、背景说明 最开始使用 SpringBoot 时&#xff0c;控制台日志是带彩色的&#xff0c;让人眼前一亮&#x1f604; 后来彩色莫名丢失&#xff0c;由于影响不大&#xff0c;一直没有处理。 2、配置彩色 最近找到了解决方法&#xff08;其实是因为自定义 logback.xml&#xff0…

任天堂,steam游戏机通过type-c给VR投屏与PD快速充电的方案 三type-c口投屏转接器

游戏手柄这个概念&#xff0c;最早要追溯到二十年前玩FC游戏的时候&#xff0c;那时候超级玛丽成为了许多人童年里难忘的回忆&#xff0c;虽然长大了才知道超级玛丽是翻译错误&#xff0c;应该是任天堂的超级马里奥&#xff0c;不过这并不影响大家对他的喜爱。 当时FC家用机手柄…

电容内容介绍

0 Preface/Foreword 电容&#xff0c;Capacitance&#xff0c;i.e. 电容量&#xff0c;指在给定电位差下自由电荷的储存量&#xff0c;符号为C&#xff0c;单位为F&#xff08;法拉&#xff09;。 电容&#xff0c;指容纳电荷的能力。任何静电场都是由许多电容组成&#xff0…

Linux---进程状态

目录 一、系统进程状态介绍 1.运行状态 2.阻塞状态 3.挂起状态 二、Linux中的进程状态 1.R (running) 2.S (sleeping) 3.D&#xff08;disk sleep&#xff09; 4.T&#xff08;stopped&#xff09; 5.t&#xff08;tracing stop&#xff09; 6.X&#xff08;dead&am…

Spring AOP入门指南:轻松掌握面向切面编程的基础知识

面向切面编程 1&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念 2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知类配给…

短剧分销平台搭建,稳占短剧市场

近两年&#xff0c;短剧一时火爆出圈&#xff0c;凭借着跌宕起伏的剧情成为了影视观众的新宠。短剧的剧情非常短&#xff0c;但每一集都能有一个高潮部分&#xff0c;非常吸引大众观看。 为了解锁更多短剧&#xff0c;观众更是对其进行付费充值&#xff0c;甚至还出现了24小时…

Java:打印当前线程的堆栈信息到错误流(error stream)

使用java.lang.Thread的静态方法dumpStack()&#xff0c;可以打印当前线程的堆栈信息到错误流&#xff08;error stream&#xff09;。 代码示例&#xff1a; package com.thb;public class Test5 {public static void main(String[] args) {Thread.dumpStack();}}运行输出&a…

基于SpringBoot的考研专业课程管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…

JFreeChart 生成图表,并为图表标注特殊点、添加文本标识框

一、项目场景&#xff1a; Java使用JFreeChart库生成图片&#xff0c;主要场景为将具体的数据 可视化 生成曲线图等的图表。 本篇文章主要针对为数据集生成的图表添加特殊点及其标识框。具体包括两种场景&#xff1a;x轴为 时间戳 类型和普通 数值 类型。&#xff08;y轴都为…