LCD 横屏切换为竖屏-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

news2024/11/14 15:42:39

LCD 横屏切换为竖屏

在这里插入图片描述

横屏显示如何切换为竖屏显示

LCD 屏默认横屏显示

  • 开发板配套的 LCD 屏默认都是横屏显示,如 4.3 寸、7 寸和 10.1 寸的不同分辨率的 RGB LCD 屏

固定坐标体系

  • (以 800*480
    分辨率为例)横屏模式下的固定坐标:左上角(0, 0)、左下角(0, 479)、右上角(799, 0)、右下角(799, 479)

    • LCD 屏正向放置

显存地址计算

  • 假设显存基地址为(unsigned
    char *)base

  • 显存地址的计算公式是 base + (y * width + x) * pix_bytes

    • LCD 像素点与显存对应关系示意图
  • pix_bytes 表示一个像素点使用 pix_bytes 个字节来描述

竖屏坐标转换

  • 应用程序中竖屏显示时,左下角作为起点(0, 0),相应的坐标转换为左上角(479, 0)、右下角(0, 799)、右上角(479, 799)

    • 竖屏方式坐标分布
  • 这是应用程序认为的一种坐标分布,对于LCD 硬件来说,实际物理上的起点坐标依然左上角的位置

显存地址计算调整

  • 竖屏显示时,显存地址的计算公式变为 base + ((height - 1 - x) * width + y) * pix_bytes

  • 不同的竖屏方式需要不同的计算公式

代码编写

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>

#define argb8888_to_rgb565(color)   ({ \
            unsigned int temp = (color); \
            ((temp & 0xF80000UL) >> 8) | \
            ((temp & 0xFC00UL) >> 5) | \
            ((temp & 0xF8UL) >> 3); \
            })

static int lcd_width;                   //LCD X分辨率
static int lcd_height;                  //LCD Y分辨率
static int lcd_max_y;                   //*LCD Y坐标最大值
static int user_width;                  //*竖屏模式下X分辨率
static int user_height;                 //*竖屏模式下Y分辨率
static unsigned short *screen_base = NULL;      //映射后的显存基地址

/********************************************************************
 * 函数名称: lcd_draw_point
 * 功能描述: 打点
 * 输入参数: x, y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_point(unsigned int x, unsigned int y, unsigned int color)
{
    unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值

    /* 对传入参数的校验 */
    if (x >= user_width)
        x = user_width - 1;
    if (y >= user_height)
        y = user_height - 1;

    /* 填充颜色 */
    //竖屏显示时,显存地址的计算公式变为 base + ((height - 1 - x) * width + y) * pix_bytes
    screen_base[(lcd_max_y-x) * lcd_width + y] = rgb565_color;//*
}

/********************************************************************
 * 函数名称: lcd_draw_line
 * 功能描述: 画线(水平或垂直线)
 * 输入参数: x, y, dir, length, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_line(unsigned int x, unsigned int y, int dir,
            unsigned int length, unsigned int color)
{
    unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
    unsigned int end;
    unsigned long temp;

    /* 对传入参数的校验 */
    if (x >= user_width)
        x = user_width - 1;
    if (y >= user_height)
        y = user_height - 1;

    /* 填充颜色 */
    temp = (lcd_max_y-x) * lcd_width + y;//*
    if (dir) {  //水平线
        end = x + length - 1;
        if (end >= user_width)
            end = user_width - 1;

        for ( ; x <= end; x++, temp -= lcd_width)
            screen_base[temp] = rgb565_color;
    }
    else {  //垂直线
        end = y + length - 1;
        if (end >= user_height)
            end = user_height - 1;

        for ( ; y <= end; y++, temp++)
            screen_base[temp] = rgb565_color;
    }
}

/********************************************************************
 * 函数名称: lcd_draw_rectangle
 * 功能描述: 画矩形
 * 输入参数: start_x, end_x, start_y, end_y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_rectangle(unsigned int start_x, unsigned int end_x,
            unsigned int start_y, unsigned int end_y,
            unsigned int color)
{
    int x_len = end_x - start_x + 1;
    int y_len = end_y - start_y - 1;

    lcd_draw_line(start_x, start_y, 1, x_len, color);//上边
    lcd_draw_line(start_x, end_y, 1, x_len, color); //下边
    lcd_draw_line(start_x, start_y + 1, 0, y_len, color);//左边
    lcd_draw_line(end_x, start_y + 1, 0, y_len, color);//右边
}

/********************************************************************
 * 函数名称: lcd_fill
 * 功能描述: 将一个矩形区域填充为参数color所指定的颜色
 * 输入参数: start_x, end_x, start_y, end_y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_fill(unsigned int start_x, unsigned int end_x,
            unsigned int start_y, unsigned int end_y,
            unsigned int color)
{
    unsigned short rgb565_color = argb8888_to_rgb565(color);//得到RGB565颜色值
    unsigned long temp;
    unsigned long step_size_count;//*记录当前步骤的大小计数
    int x;

    /* 对传入参数的校验 */
    if (end_x >= user_width)
        end_x = user_width - 1;
    if (end_y >= user_height)
        end_y = user_height - 1;

    /* 填充颜色 */
    temp = (lcd_max_y-start_x) * lcd_width + start_y;//*
    for ( ; start_y <= end_y; start_y++, temp++) {

        step_size_count = 0;//*
        for (x = start_x; x <= end_x; x++, step_size_count += lcd_width)//*
            screen_base[temp - step_size_count] = rgb565_color;//*
    }
}

int main(int argc, char *argv[])
{
    struct fb_fix_screeninfo fb_fix;
    struct fb_var_screeninfo fb_var;
    unsigned int screen_size;
    int fd;

    /* 打开framebuffer设备 */
    if (0 > (fd = open("/dev/fb0", O_RDWR))) {
        perror("open error");
        exit(EXIT_FAILURE);
    }

    /* 获取参数信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;//*计算 framebuffer 的总大小(即屏幕缓冲区的大小)
    lcd_width = fb_var.xres;//*获取 LCD 宽度
    lcd_height = fb_var.yres;//*获取 LCD 高度
    lcd_max_y = lcd_height - 1;//*计算 Y 轴最大值
    user_width = fb_var.yres;//*竖屏下的宽度
    user_height = fb_var.xres;//*竖屏下的高度

    /* 将显示缓冲区映射到进程地址空间 */
    screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fd);
        exit(EXIT_FAILURE);
    }

    /* 画正方形方块 */
    int w = user_height * 0.25;//*方块的宽度为1/4屏幕高度
    lcd_fill(0, user_width-1, 0, user_height-1, 0x0); //清屏(屏幕显示黑色)
    lcd_fill(0, w, 0, w, 0xFF0000); //红色方块
    lcd_fill(user_width-w, user_width-1, 0, w, 0xFF00);   //绿色方块
    lcd_fill(0, w, user_height-w, user_height-1, 0xFF);   //蓝色方块
    lcd_fill(user_width-w, user_width-1, user_height-w, user_height-1, 0xFFFF00);//黄色方块

    /* 画线: 十字交叉线 */
    lcd_draw_line(0, user_height * 0.5, 1, user_width, 0xFFFFFF);//白色水平线
    lcd_draw_line(user_width * 0.5, 0, 0, user_height, 0xFFFFFF);//白色垂直线

    /* 画矩形 */
    unsigned int s_x, s_y, e_x, e_y;
    s_x = 0.25 * user_width;
    s_y = w;
    e_x = user_width - s_x;
    e_y = user_height - s_y;

    for ( ; (s_x <= e_x) && (s_y <= e_y);
            s_x+=5, s_y+=5, e_x-=5, e_y-=5)
        lcd_draw_rectangle(s_x, e_x, s_y, e_y, 0xFFFFFF);

    /* 退出 */
    munmap(screen_base, screen_size);  //取消映射
    close(fd);  //关闭文件
    exit(EXIT_SUCCESS);    //退出进程
}

由FrameBuffer 应用编程改写,主要是一些逻辑上的变化

LCD 显示效果

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

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

相关文章

【JavaScript】深入理解 `let`、`var` 和 `const`

文章目录 一、var 的声明与特点二、let 的声明与特点三、const 的声明与特点四、let、var 和 const 的对比五、实战示例六、最佳实践 在 JavaScript 中&#xff0c;变量声明是编程的基础&#xff0c;而 let、var 和 const 是三种常用的变量声明方式。本文将详细介绍这三种变量声…

Blackbox AI-跨时代AI产物,你的私人编程助手

1. 引言 随着人工智能技术的飞速发展&#xff0c;我们的生活方式正在经历前所未有的变革。从智能家居到自动驾驶&#xff0c;AI已经渗透到我们生活的方方面面。而在这场科技革命中&#xff0c;Blackbox 网站凭借其先进的技术和全面的功能&#xff0c;成为了众多AI产品中的佼佼者…

基于单片机控制的锂电池组电路的设计

摘 要: 提 出 一 种 基 于 单 片 机 控 制 的 锂 电 池 组 电 路 设计 方 案 . 采 用 8 位 CMOS 闪 存 单 片 机 PIC16F886 作 为主控芯 片 , 电 路 设计 中 含 有 S-8254 芯 片 的 一 次 保 护 电 路 、 S-8244 芯 片 的 二 次 保 护 电 路 和 MCU 的 辅 助 保 护 功…

photoshop学习笔记——选区3 快速选择工具

快速选择工具 W shift W 在3种快速选择工具之间切换 对象选择工具 photoshop CC中没有这个工具&#xff0c;利用AI&#xff0c;将款选中的对象快速的提取选区&#xff0c;测试了一下&#xff0c;选区制作的非常nice快速选择工具 跟磁性套索类似&#xff0c;自动识别颜色相似…

qt初入门9:qt记录日志的方式,日志库了解练习(qInstallMessageHandler,qslog, log4qt)

项目中用到qt&#xff0c;考虑有需要用到去记录日志&#xff0c;结合网络&#xff0c;整理一下&#xff0c;做记录。 简单了解后&#xff0c;qt实现日志模块思考&#xff1a; 1&#xff1a;借助qt自带的qInstallMessageHandler重定向到需要的目的地。 2&#xff1a;自己封装一…

JAVA SE 类和对象

类和对象 类定义和使用类的定义格式 类的实例化什么是实例化 this 引用this引用的特性 对象的构造及初始化如何初始化对象构造方法概念特性 在这里插入图片描述 **注意**&#xff1a; 封装封装的概念封装扩展之包导入包中的类自定义包包的访问权限控制举例 static成员static修饰…

MOZHE SQL手工注入漏洞测试(MySQL数据库)

主界面URL没有参数&#xff0c;无法判断是否有注入点 点击公告 【浏览器不便于查看返回包可以用burp】 测试URL 参数后加上单引号&#xff0c;报错&#xff0c;说明存在注入点 http://124.70.64.48:40021/new_list.php?id1 获取表列数 order by 4 返回200 order by 5 …

鸿蒙应用框架开发【N-Body模拟程序】

N-Body模拟程序 介绍 在本示例中&#xff0c;使用ArkTS编程语言开发了业界编程语言基准测试项目[Benchmarks Game]中的[N体问题模拟程序]&#xff0c;实现类木星体轨道计算。 本示例用到了ohos.taskpool和ohos.worker 接口。示例中的程序可以用于AOT(Ahead Of Time)等性能测…

计科录取75人!常州大学计算机考研考情分析!

常州大学&#xff08;Changzhou University&#xff09;&#xff0c;简称“常大”&#xff0c;位于江苏省常州市&#xff0c;是江苏省人民政府与中国石油天然气集团有限公司、中国石油化工集团有限公司及中国海洋石油集团有限公司共建的省属全日制本科院校&#xff0c;为全国深…

⼤模型在⽹络安全⽅⾯的应⽤汇总

引⾔ ⼤语⾔模型&#xff08;Large Language Models, LLMs&#xff09;的横空出世&#xff0c;为传统计算机科学的各个细分领域带来了颠覆性的变⾰。这种变⾰的浪潮同样席卷了⽹络安全领域&#xff0c;引发了⼀系列深刻的变化和影响。GPT-4、Gemini、Llama 2 等⼤模型以其卓越的…

7月22日学习笔记 文件共享服务nfs,SAMBA文件共享与DNS域名服务

任务背景 由于业务驱动&#xff0c;为了提⾼⽤户的访问效率&#xff0c;现需要将原有web服务器上的静态资源 ⽂件分离出来&#xff0c;单独保存到⼀台⽂件服务器上。 任务要求 1. ⼀台应⽤服务器web-server部署apache&#xff0c;静态⽹⻚资源存放在另外⼀台NFS服 务器上 …

深入理解计算机系统 CSAPP 家庭作业11.7

静态内容是指在不同请求中访问到的数据都相同的静态文件。例如&#xff1a;图片、视频、网站中的文件&#xff08;html、css、js&#xff09;、软件安装包、apk文件、压缩包文件等。 /** get_filetype - derive file type from file name*/ void get_filetype(char *filename,…

12_TypeScript 模块 以及 模块化封装DB 库

TypeScript 模块 1、模块中暴露方法12、模块中暴露方法23、模块中暴露方法34、封装[上一节的db 库](https://blog.csdn.net/qq_46143850/article/details/140664100)5、TypeScript 命名空间 模块的概念&#xff08;官方&#xff09;&#xff1a; 关于术语的一点说明&#xff1a…

Linux网络-wget命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

【工具推荐】强大的JS渗透测试工具:URLFinder

一、下载地址 https://github.com/pingc0y/URLFinder 二、工具原理 从表现中JS中提取URL或者敏感数据&#xff0c;一款用于快速提取检测页面中JS与URL的工具。功能类似于JSFinder&#xff0c;但JSFinder好久没更新了。 三、工具介绍 1、下载解压出来包含下面两个文件 2、直…

内网渗透—内网穿透工具NgrokFRPNPSSPP

前言 主要介绍一下常见的隧道搭建工具&#xff0c;以此来达到一个内网穿透的目的。简单说一下实验滴环境吧&#xff0c;kali作为攻击机&#xff0c;winserver2016作为目标靶机。 kali 192.168.145.171 winserver2016 10.236.44.127 显然它们处于两个不同的局域网&#xff0c…

SQLException:Operation not allowed after ResultSet closed

运行代码时出现的错误&#xff1a; 这是在运行简单的JDBC访问数据库时出现的问题&#xff0c;原因是在ResultSet方法中添加了close()关闭方法,如图&#xff1a; ResultSet 是通过 query 方法获得的&#xff0c;并且在 try-catch 块中没有显式地关闭它。这实际上是 一个常见的…

ServletContainerInitializer接口详解

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhlServletContainerInitializer概述 ServletContainerInitializer是Servlet 3.0规范中引入的一个接口,它的主要目的是允许开发者在Servlet容器(如Tomcat、Jetty等)启动时执行一些自定义的初始化代…

池化层pytorch最大池化练习

神经网络构建 class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()self.maxpool1 MaxPool2d(kernel_size3, ceil_modeFalse)def forward(self, input):output self.maxpool1(input)return output Tensorboard 处理 writer SummaryWriter("./l…

Linux系统上安装Redis

百度网盘&#xff1a; 通过网盘分享的文件&#xff1a;redis_linux 链接: https://pan.baidu.com/s/1ZcECygWA15pQWCuiVdjCtg?pwd8888 提取码: 8888 1.把安装包拖拽到/ruanjian/redis/文件夹中&#xff08;自己选择&#xff09; 2.进入压缩包所在文件夹&#xff0c;解压压缩…