LCD显示原理及应用
Linux环境下LCD显示原理及应用
1. LCD原理概述
LCD(Liquid Crystal Display)液晶显示器是一种广泛应用于各种电子设备中的显示技术,它利用液晶分子在电场作用下的排列状态来控制光的透过,从而实现图像显示。
2. LCD驱动原理
LCD显示屏的驱动通常需要硬件和软件两方面的支持:
- 硬件支持: LCD显示屏需要与嵌入式系统的硬件平台进行连接,通常需要考虑接口协议(如RGB、MIPI DSI)、电源管理、时序控制等。
- 软件支持: 驱动程序负责控制LCD显示屏的初始化、数据传输、显示内容更新等操作。在Linux系统中,LCD驱动程序通常以设备驱动的形式存在,与内核紧密结合。
3. LCD驱动开发流程
LCD驱动的开发通常涉及以下几个主要步骤:
- 1. 硬件平台支持: 确保嵌入式系统的硬件平台能够正确连接LCD显示屏,包括电源、信号线等连接。
- 2. 内核配置: 确保Linux内核已经正确配置了LCD显示屏相关的驱动选项,如内核配置中的Framebuffer支持、LCD显示屏驱动支持等。
- 3. 驱动程序编写: 编写LCD显示屏的驱动程序,包括初始化、数据传输、显示内容更新等功能。驱动程序通常以C语言编写,并且需要注册到Linux内核中。
- 4. 设备树配置: 在设备树(Device Tree)中配置LCD显示屏的信息,包括连接的接口、时序、分辨率等信息,以便Linux内核正确识别和初始化LCD设备。
- 5. 软件集成与测试: 将编写的LCD驱动程序集成到Linux内核中,编译生成新的内核镜像,并在目标平台上进行测试验证,确保LCD显示功能正常。
像素(pixel)
像素(pixel)是图像的最小单位,是由数字、颜色和位置组成的基本元素。它是英文“picture element”的缩写,是数字图像的构成要素之一。在数字图像中,每个像素都有其特定的位置坐标和对应的颜色值,这些颜色值通常由红、绿、蓝
三原色的不同组合来表示,也称为RGB值。
像素的特征
位置坐标: 每个像素都有其在图像中的位置坐标,通常用行号和列号表示,如(x,y)。
颜色值: 每个像素都有其对应的颜色值,用来表示在该位置显示的颜色,常见的颜色表示方式包括RGB、CMYK等。
大小: 像素的大小通常由图像的分辨率决定,分辨率越高,每英寸所包含的像素点就越多,像素点的大小就越小。
密度: 像素密度指的是在一定区域内像素的数量,通常以每英寸的像素数量(dpi,dots per inch)来衡量。
分辨率(imageResolution)
分辨率(image resolution)是指数字图像中每个单位长度包含的像素数量,通常以水平方向和垂直方向的像素数来表示。分辨率决定了图像的清晰度和细节程度,是评估图像质量的重要指标之一。
分辨率的表示方法
绝对分辨率: 绝对分辨率指的是图像的实际像素数量,通常以水平像素数和垂直像素数表示,如1920x1080。
相对分辨率: 相对分辨率指的是图像的像素数量与物理尺寸之间的关系,通常以每英寸的像素数量(dpi,dots per inch)来表示。
分辨率对图像质量的影响
清晰度: 分辨率越高,图像中包含的像素数量越多,图像显示得越清晰。
细节度: 高分辨率图像能够显示更多的细节和纹理,使图像更加逼真。
打印质量: 对于打印图像,分辨率越高,打印出的图像质量越好,细节更加清晰。
分辨率的选择
屏幕显示: 选择合适的分辨率可以提高屏幕显示的清晰度和细节度,但也会增加系统资源的消耗。
打印输出: 对于打印输出,要根据打印机的分辨率和输出尺寸选择合适的图像分辨率,以保证打印质量。
网络传输: 在网络传输图像时,可以根据传输带宽和目标显示设备的分辨率选择合适的图像分辨率,以节省传输时间和带宽。
色彩深度(BPP,bit per pixel)
色彩深度(BPP,bit per pixel)是指数字图像中每个像素用多少位来表示其颜色信息。它决定了图像能够显示的颜色数量和色彩范围,是评估图像质量的重要指标之一。常见的色彩深度包括1位(单色)、8位(256色)、24位(真彩色)等。
色彩深度 | 描述 | 能表示的颜色数量 | 色彩范围 |
---|---|---|---|
1位 | 单色 | 2(黑白) | 黑、白 |
8位 | 灰度 | 256 | 0~255个灰度级 |
16位 | 高彩色 | 65536 | 65536种颜色 |
24位 | 真彩色 | 16777216 | 256×256×256种颜色 |
32位 | 真彩色 + Alpha通道 | 16777216 | 256×256×256种颜色 + 透明度 |
驱动架构 Framebuffer
Framebuffer(帧缓冲)是计算机图形显示系统中用于存储图像数据的内存区域。在Linux系统中,Framebuffer驱动提供了一种通用的图形显示接口,允许应用程序直接访问图形硬件,而不必了解特定硬件设备的细节。
Framebuffer驱动在Linux系统中属于底层机制,抽象了各种显示设备的具体细节,提供了一个干净、抽象的编程接口。它将显卡硬件抽象成可直接操作的内存,并提供了封装好的各种操作和设置,大大提高了内核开发的效率。Framebuffer驱动将屏幕上的每个像素点映射成一段线性内存空间,应用程序可以直接修改这段内存空间的数据,从而改变屏幕上的像素颜色。
LCD屏在Linux系统下属于字符设备,需要通过Framebuffer驱动程序进行控制。Framebuffer驱动安装后会在 /dev
目录下生成名为 fbn
(n = 0 ~ 31)的设备文件,如LCD屏的设备文件名通常为 /dev/fb0
。
在Linux系统中硬件设备主要分为两种:一种是字符设备(LCD、触摸屏、键盘......),另一种是块设备(硬盘、U盘......),这两种类型的硬件设备都需要由驱动程序(xxx.ko)控制,当驱动程序安装完成后会自动生成硬件的设备文件,用户才可以通过设备文件去访问硬件。
window系统的硬件驱动安装完成后会在设备管理器中生成设备文件,而Linux系统的硬件驱动安装完成后会自动在 /dev****目录下生成设备文件。
硬件参数
在Linux系统下是利用Framebuffer子系统来驱动显示设备的,所以Framebuffer子系统会读取LCD屏的硬件信息并存储在内核空间中,关于LCD的硬件参数都是定义在/usr/include/linux/fb.h头文件中。
** 三个重要的结构体**
// struct fb_fix_screeninfo
struct fb_fix_screeninfo {
char id[16]; // 设备id
unsigned long smem_start; // 显存起始地址(实际物理地址)
__u32 smem_len; // 显存大小
__u32 type; // 像素构成
__u32 type_aux; // 交叉扫描方案
__u32 visual; // 色彩构成
__u16 xpanstep; // x轴平移步长(若支持)
__u16 ypanstep; // y轴平移步长(若支持)
__u16 ywrapstep; // y轴循环步长(若支持)
__u32 line_length; // 扫描线大小(字节)
unsigned long mmio_start; // 缺省映射内存地址(物理地址)
__u32 mmio_len; // 缺省映射内存大小
__u32 accel; // 当前显示加速器芯片
__u16 reserved[3]; // 保留
};
// struct fb_bitfield
struct fb_bitfield {
__u32 offset; // 色彩位域偏移量
__u32 length; // 色彩位域长度
__u32 msb_right;
};
// struct fb_var_screeninfo
struct fb_var_screeninfo {
__u32 xres; // 可见区的宽度分辨率
__u32 yres; // 可见区的高度分辨率
__u32 xres_virtual; // 虚拟区的宽度分辨率
__u32 yres_virtual; // 虚拟区的高度分辨率
__u32 xoffset; // 虚拟区到可见区的宽度偏移量
__u32 yoffset; // 虚拟区到可见区的高度偏移量
__u32 bits_per_pixel; // 色彩深度
__u32 grayscale; // 灰阶(若为非0)
struct fb_bitfield red; // 红色色彩位域构成
struct fb_bitfield green; // 绿色色彩位域构成
struct fb_bitfield blue; // 蓝色色彩位域构成
struct fb_bitfield transp; // 透明属性
__u32 nonstd; // 非标准像素格式(若为非0)
__u32 activate; // 设置参数合适生效
__u32 height; // 图片高度(单位毫米)
__u32 width; // 图片宽度(单位毫米)
__u32 accel_flags; // 显示卡选项
};
以上结构体在Linux系统的
/usr/include/linux/fb.h
中定义。struct fb_fix_screeninfo
保存显示设备不能被修改的信息,struct fb_var_screeninfo
保存显示设备可以被调整的信息,而struct fb_bitfield
保存了色彩构成具体方案。
xres_virtual和yres_virtual决定了虚拟区的大小,而xres和yres决定了屏幕上可见区域的大小,如果虚拟区比可见区大,我们还可以调整xoffset和yoffset来显示不同的 部分,比如,让yoffset逐渐变大,从显示效果上看来,就好像一张图片平滑地向上移动。
代码练习
利用系统IO接口函数显示纯色
练习:利用系统IO的相关接口实现在LCD屏幕上显示一种纯色(红色),注意LCD屏每个像素点都是4字节(ARGB),一般是把颜色以十六进制形式写入到LCD屏像素点中,进行程序设计。
//假设让LCD显示红色,这个程序需要在开发板中运行 需要交叉编译 arm-linux-gcc
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main(int argc, char const *argv[])
{
//1.打开LCD 设备文件路径 "/dev/fb0" O_RDWR
int lcd_fd = open("/dev/fb0",O_RDWR);
if (-1 == lcd_fd)
{
printf("open lcd error\n");
return -1;
}
//2.对LCD进行内存映射 mmap函数 记得接收返回值
int *lcd_mp = (int *)mmap(
NULL,
800*480*4,
PROT_READ|PROT_WRITE,
MAP_SHARED,
lcd_fd,
0
);
if (MAP_FAILED == lcd_mp)
{
printf("mmap for lcd is error\n");
return -1;
}
//3.把颜色分量写入到申请的映射内存空间中,通过地址偏移实现访问
for (int i = 0;i < 800*480; ++i)
{
lcd_mp[i] = 0x00FF0000; //红色的RGB为0XFF0000
}
//4.关闭LCD并解除内存映射
munmap(lcd_mp,800*480*4);
close(lcd_fd);
return 0;
}
利用ioctl函数获取LCD的硬件参数
练习:设计程序,利用ioctl函数获取LCD的硬件参数,把LCD屏幕的宽和高以及色深的位数输出到屏幕,下载程序到开发板并进行验证。 提示:必须包含该头文件 <linux/fb.h> !!!!
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/fb.h>
int main(int argc, char const *argv[])
{
//1.打开LCD
int lcd_fd = open("/dev/fb0",O_RDWR);
//2.利用ioctl函数获取LCD硬件参数
struct fb_var_screeninfo lcd_vinfo;
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&lcd_vinfo);
//3.输出LCD的宽、高、色深
printf("lcd height= %-5d\n", lcd_vinfo.yres); //480
printf("lcd width= %-5d\n", lcd_vinfo.xres); //800
printf("lcd bpp=%-5d\n",lcd_vinfo.bits_per_pixel); //32
return 0;
}
检测LCD屏幕坏点刷新屏幕
练习:LCD每隔一秒显示一种单色,用来检测LCD屏幕有没有坏点。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)