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

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

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

代码编写

c 复制代码
#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 显示效果

相关推荐
z千鑫4 小时前
【C/C++】数据库链接入门教程:从零开始的详细指南!MySQL集成与操作
c语言·数据库·c++
脸ル粉嘟嘟4 小时前
linux(redhat8)如何安装mysql8.0之rpm&tar双版本(最新版)(内网)(离线)
linux·运维·adb
Mephisto.java5 小时前
【大数据学习 | Spark-Core】RDD的五大特性(包含宽窄依赖)
大数据·学习·spark
weixin_446260856 小时前
AI大模型学习
人工智能·学习
行然梦实6 小时前
学习日记_20241126_聚类方法(Affinity Propagation)
学习·聚类
GivemeAK6 小时前
[Foc学习记录00]导览
学习
zmd-zk7 小时前
kafka命令的使用——主题命令(topic)
大数据·分布式·学习·kafka
Octopus20777 小时前
【Linux】vim的使用
linux·笔记·学习·vim
一个假的前端男7 小时前
VMware安装CentOS 9 及mysql的安装
linux·运维·centos
red_redemption8 小时前
自由学习记录(25)
学习·lua