Linux简单硬件控制之LCD

—>Linux常见标准函数接口见这篇<—

—>Linux常见系统IO函数接口见这篇<—

1.LCD基本概念和结构

  LCD(Liquid Crystal Display)名为液晶显示器,它的主要原理是灯管发出的光线经过彩色滤光片的滤光作用得到RGB即红绿蓝三原色,结合偏光片,使得RGB三原色在不同强弱叠加作用下显示出各种颜色。
在这里插入图片描述

我们知道显示图像的最小单位是像素(Pixel),而一张图片的宽像素数×高像素数就是分辨率,表示一张图片像素的多少。
色深bpp(bits per pixel)表示所能表示的颜色的丰富程度,每个像素点所占位数就是色深,比如24bit色深,RGB每一个颜色占了8bits,每种颜色的范围位0-2**8-1,那么三种颜色组合起来一共就有 2 8 2^8 28× 2 8 2^8 28× 2 8 2^8 28这么多种颜色,假设色深为1bit,那么RGB每种颜色的范围只有0,1两种,三种颜色组合起来就只有 2 1 2^1 21× 2 1 2^1 21× 2 1 2^1 21=8种,显然颜色就没有24位色深的颜色丰富了。除了RGB三种颜色外显示屏还有A(alpha透明度),而图片没有A透明度这一个参数。

2.LCD显示颜色

  在Linux系统下,字符设备硬件设备由相关驱动系统控制,而LCD屏的驱动系统是FrameBuffer(帧缓冲),安装完驱动后在Linux的/dev目录下会出现名为fbn(n=0~31)的设备文件,这个文件里存的是显示屏每个像素点的颜色信息,每一个像素点的颜色信息是一个4字节数(对应ARGB四个字节),我们想在显示屏上显示出对应图案就只需要把每个像素点对应的颜色信息写入到fb文件中即可。例如:我们想让一个分辨率 100 ∗ 100 100*100 100100的显示屏显示全屏蓝色,而像素点深蓝色的十六进制数是#000000FF, 100 ∗ 100 100*100 100100分辨率一共有10000个像素点,则需写入10000个#0000000FF,程序思路三步走——打开fb文件,写入fb文件,关闭fb文件。

  • 代码如下:
int main(int argc,const char*argv[]){
//1.打开fb0文件
int lcd_fb=open("/dev/fb0",O_RDWR);
if(-1==lcb_fb){
printf("open failed\n");
exit(-1);}
//2.向fb0写入颜色信息
int buff[100*100]={0};
for(int i=0;i<100*100;i++){
buff[i]=0x000000FF}
write(lcd_fb,buff,100*100*4)
//3.关闭fb0文件
close(lcd_fb)
return 0;
}

3.LCD屏幕硬件参数查询和修改

  我们已经知道LCD由FrameBuffer驱动控制,该驱动会获取显示屏的硬件信息并存在/usr/include/Linux/fb.h头文件中。
在这里插入图片描述
  fb.h头文件里定义了许多有关显示屏的参数有VSCREENINFO(virtual screen information)虚拟屏幕参数,这是可修改的,FSCREENINFO(fixed screen information)固定屏幕参数是硬件决定的,不能修改。还定义了三个重要的结构体:fb_fix_screeninfo,fb_bitfield,fb_var_screeninfo
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  要改变和显示与LCD相关参数需要用到ioctls函数接口,man手册里该函数的参数和返回值如下:

在这里插入图片描述
  函数第一个参数是打开LCD的fbn文件返回的文件描述符,第二个参数是上面fb.h头文件里定义的有关显示屏的参数宏定义,输入不同宏定义查看显示屏的不同参数,后面还有许多个参数,一般我们常用的就是结构体地址,用于存放获取到的显示相关参数。

  • 示例代码:
int main(int argc,const char*argv[]){
//1.打开fb0文件
int lcd_fb=open("/dev/fb0",O_RDWR);
if(-1==lcb_fb){
printf("open failed\n");
exit(-1);}
//2.获取显示屏虚拟参数
struct fb_var_screeninfo lcd_info;
ioctls(lcd_fb,FBIOGET_VSCREENINFO,&lcd_info);
//3.打印获取的参数
printf("width is %d",lcd_info.width);
printf("height is %d",lcd_info.height);
return 0;
}

4.提高LCD显示效率

  在用系统函数实现LCD屏幕显示时会发现在显示过程中有些像素会出现黑线,重新执行程序或重启后黑线就消失了,这是因为用系统函数接口将颜色分量信息写入fb文件过程中,需要经过从用户缓冲区到内核缓冲区,再到实际文件的过程,颜色变量数据的写入不是一步写入,效率有点低,那么怎么能提高效率呢?
答案是内存映射,将文件内容映射到进程的虚拟地址空间,对虚拟空间写入的数据直接就映射到文件中,简化过程,提高效率,其中需要用到mmap,munmap函数。
在man手册里函数参数和返回值如下:
在这里插入图片描述
start是映射区的开始地址,length是映射区的长度。
prot参数设定了映射内存的访问权限,该参数在下面四种选择一种或者其中的几个进行位或操作:

  • PRO_EXEC(可执行executed)
  • PROT_READ
  • PROT_WRITE
  • PROT_NONE
    flags是指定映射对象的类型,映射选项和映射页是否可以共享,fd是打开文件返回的文件描述符,offset是被映射对象内容的起点
    若成功映射,mmap返回值是被映射区的指针,否则返回MAP_FAILED(其为(void*)-1)。
    若成功解除映射munmap()返回0,否则返回-1。
  • 代码示例:
int main(){
    int lcd_fd = open("/dev/fb0",O_RDWR);
    if (-1 == lcd_fd)
    {printf("open lcd error\n");
        return -1;}
    //2.LCD内存映射
    int *lcd_mp = (int *)mmap(
                        NULL,
                        100*100*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 < 100*100; ++i)
    {
        lcd_mp[i] = 0x00FF0000;
    }

    //4.关闭LCD并解除内存映射
    munmap(lcd_mp,100*100*4);
    close(lcd_fd);
    return 0;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamerJoyFinder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值