知识点-lcd显示1->frame buffer、字库

一、frame buff 帧缓冲

1、概念:

        帧缓存(fps一秒多少帧)

        是一种图形硬件抽象层,它将显示设备的显存映射到系统内存中,使得应用程序可以直接通过读写内存来控制屏幕上的像素显示。这段代码实现了打开帧缓冲设备、获取设备的相关参数(如分辨率、位深度等),并将显存映射到用户空间的功能。

2、相关概念:

  • 分辨率:宽高(广泛理解)
    • 例如:imx6ull 板子的分辨率为:800*480(4.3寸)
  • 色深:颜色空间、颜色深度、位深度(位越高,颜色越细腻)
    • 类型:RGB、yuv、HSV
      • 例如:imx6ull 板子的色深:RGB,888,24bit(位越高,颜色越细腻)
      • imx6ull 板子的触屏接I2C
  • 一秒三十帧画面
    • 大小34M =800*480*3(RGB)*30(一秒30帧)
    • 太大,所以采用并行传输(距离不能太远、速度越快越受到干扰)

3、lcd绘制:

        实际屏幕对应一块显存,内存映射过来是一个长条,应用不能直接操作硬件,linux,驱动,合法手段内存映射mmap;如图所示

4、代码实现

void *pmem;                //存储显存映射到用户后的起始地址
struct fb_var_screeninfo vinf;        //结构体:存储:设备分辨率、色深等..

//打开字符串为devname的帧缓冲设备

int init_fb(char *devname)
{
    //1. 以读写模式打开帧缓冲设备文件
    int fd = open(devname, O_RDWR);    
    if (-1 == fd)
    {
        perror("fail open fb");
        return -1;
    }
    
    //2、获取显示设备相关参数 分辨率 位深度
    int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
    if (-1 ==ret)
    {
        perror("fail ioctl");
        return -1;
    }
    
    printf("xres = %d, yres = %d\n", vinf.xres, vinf.yres);
    printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);
    printf("bits_per_pixel : %d\n", vinf.bits_per_pixel);

    size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;


    //3, 建立显存和用户空间的映射关系(将显存映射到用户空间)
    pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if ((void *)-1 == pmem)
    {
        perror("fail mmap");
        return -1;
    }
    
    return fd;
}

表格总结

步骤函数调用作用i.MX6ULL 特殊考量
1open("/dev/fb0", ...)打开帧缓冲设备文件需确认设备节点为 /dev/fb0 或 /dev/fb1
2ioctl(FBIOGET_VSCREENINFO)获取屏幕参数(分辨率/色深)需匹配芯片的显示控制器(如 DCSS/EPDC)
3mmap()将显存映射到用户空间物理地址需对齐 MX6ULL 的 MMU 配置
4返回文件描述符供后续绘图操作使用需保持打开状态直到程序结束

5、显示点

//显示点

//传入点的位置,以及颜色
void draw_point(int x, int y, unsigned int col)
{

    //若超出边界则直接返回
    if (x >= vinf.xres || y >= vinf.yres)
    {
        return ;
    }

     //若色深为RGB 888 执行以下画点
    if (vinf.bits_per_pixel == RGB888_FMT)
    {

        //定义指针
        unsigned int *p = pmem;

        //指向点位置(高度*一行的像素点+宽度)
        *(p + y * vinf.xres_virtual + x) = col;
    }
    else if (vinf.bits_per_pixel == RGB565_FMT)
    {
        unsigned short *p  = pmem;    
        *(p + y * vinf.xres_virtual + x) = col;
    }
    return ;
}

main.c调用

    draw_point(400, 300, 0x00ff0000);

6、显示图片

//显示图片

  • int x, int y,        图片位置
  • char *picname,存放源图片的路径
  • int w, int h         图片的长宽

void draw_bmp(int x, int y, char *picname, int w, int h)
{
    int fd = open(picname, O_RDONLY);
    if (-1 == fd)
    {
        perror("fail open bmp");
        return ;
    }
    
    lseek(fd, 54, SEEK_SET);

    unsigned char r, g, b;

    unsigned char *buff = malloc(w*h*3);
    read(fd, buff, w*h*3);
    
    unsigned char *p = buff;
    for (int j = h-1; j >= 0; j--)
    {
        for (int i = 0; i < w; i++)
        {

            b = *p; p++;
            g = *p; p++;
            r = *p; p++;
            if (vinf.bits_per_pixel == RGB888_FMT)
            {
                unsigned int col = (r << 16) | (g << 8) | (b << 0);
                draw_point(i+x, j+y, col);
            }
            else if (vinf.bits_per_pixel == RGB565_FMT)
            {
                unsigned short col = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
                draw_point(i+x, j+y, col);
            }
        }
    }

    free(buff);
    close(fd);
}

main.c 调用

    draw_bmp(0, 0, "./res/3.bmp", 800, 480);

  • 显示的图片还需要进行预处理(在window绘图软件进行)
    • 将图片的长宽尺寸转为板子的分辨率(长800;宽480)
    • 将图片另存为bmp:bit map(原始像素存储:前54byte 照片属性(长宽高))
    • 将图片复制进虚拟机内部,并给图片读写权限
      • 右键进入Properties
      • 将其内的Permissions 的Access权限打开为:Read and Write
    • 即可调用函数实现

7、显示字

1)字模创建(软件如图):

2)构建数组

        复制字模软件生成的取模点阵,按照下面格式写成数组

3)函数调用

4)代码实现

  • //显示字
    • //int x, int y,    在哪显示
    • //unsigned char *word,    字体的字模
    • //int w, int h,     字体大小
    • //unsigned int col    字体颜色

void draw_word(int x, int y, unsigned char *word, int w, int h, unsigned int col)
{

    for (int j = 0; j < h; j++)
    {
        for (int i = 0; i < w; i++)
        {
            unsigned char tmp = word[i+j*w];
            for (int k = 0; k < 8; k++)
            {
                if (tmp & 0x80)
                {
                    draw_point(i*8+k+x, j+y, col);
                }
                else
                {
                    //文字的背景色
                }
                tmp = tmp << 1;
            }
        }
    }
}
 

main.c 调用

    draw_word(300, 300, dan, 24/8, 22, 0x00ff0000);

  • 24/8 :
    • 24->宽(最好是8的整数倍,一般字模软件生成会调整)
    • 8 固定
  •  22:高

8、显示一段话(字库)

        一段话一直一个单个字取模很麻烦,所以引入字库;

        linux:一个汉字、两个字节

1)创建字库(软件如图):

2)初始化字库

3)查看字库权限

4)调用函数

5)代码实现

//显示一段话

int draw_utf8_str(UTF8_INFO *info, int arg_x, int arg_y,  char* zi, unsigned int col, unsigned int col1)
{
    char* temp = zi;
    unsigned int x = arg_x ;
    unsigned int y =  arg_y;

    while(*temp != '\0')
    {
        int ret = draw_utf8(info, x, y, temp, col, col1);
        x += info->width;
        if(x > vinf.xres)
        {
            x = 0;
            y += info->height;
            if(y > vinf.yres)
            {
                y = 0;
            }
        }

        temp += ret;
    }
    return 0;
}
 

main.c 调用

//初始化utf8字库
    UTF8_INFO utf8_info;
    bzero(&utf8_info, sizeof(UTF8_INFO));
    strcpy(utf8_info.path, ZIKUK_FILE_BIG);
    utf8_info.width = 32;
    utf8_info.height = 32;
    init_utf8(&utf8_info);

//调用

    draw_utf8_str(&utf8_info, 100, 100, "2025年10月8号", 0x00ff0000, 0x00ffffff);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值