• hud项目lcd调试


    lcd规格:

    像素:480x280

    bpp:16

    pix_format:RGB565

    在开发板终端中执行:

    ls /dev/fb0 -l ---> crw-rw----    1 root     video      29,   0 Jan  1  1970 /dev/fb0

    /dev/fb0就是FrameBuffer的设备文件

    然后我们就可以操作这个设备文件了

    cat /dev/fb0 > screensnap  // 把设备文件/dev/fb0的内容保存到sreesnap文件中

    ls -l screensnap

    -rw-r--r--    1 root     root        268800 Nov 10 17:22 screensnap

    我们得到了一个268800字节的文件,再做下面的操作:

    清屏:dd if=/dev/zero of=/dev/fb0

    把刚刚显示的内容重新再lcd上显示:cat /dev/screensnap >  /dev/fb0

    通过以上的操作,可以推测。文件/dev/fb0就是控制屏幕上的每一点的颜色的文件。

    我们可以写程序来改变这个文件的内容,就可以方便的在屏幕上画图了

    测试代码:

        #include <unistd.h>
        #include <stdio.h>
        #include <fcntl.h>
        #include <linux/fb.h>
        #include <sys/mman.h>
    
        int main()
        {
            int fbfd = 0;
            struct fb_var_screeninfo vinfo;
            struct fb_fix_screeninfo finfo;
            struct fb_cmap cmapinfo;
            long int screensize = 0;
            char *fbp = 0;
            int x = 0, y = 0;
            long int location = 0;
                int b,g,r;
            // Open the file for reading and writing
            fbfd = open("/dev/fb0", O_RDWR);                    // 打开Frame Buffer设备
            if (fbfd < 0) {
                        printf("Error: cannot open framebuffer device.%x
    ",fbfd);
                        exit(1);
            }
            printf("The framebuffer device was opened successfully.
    ");
    
            // Get fixed screen information
            if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {            // 获取设备固有信息
                        printf("Error reading fixed information.
    ");
                        exit(2);
            }
                printf(finfo.id);
            printf("
    type:0x%x
    ", finfo.type );                            // FrameBuffer 类型,如0为象素
            printf("visual:%d
    ", finfo.visual );                        // 视觉类型:如真彩2,伪彩3
            printf("line_length:%d
    ", finfo.line_length );        // 每行字节长度
            printf("
    smem_start:0x%x,smem_len:%d
    ", finfo.smem_start, finfo.smem_len ); // 显存起始地址和显存大小
            printf("mmio_start:0x%x ,mmio_len:%d
    ", finfo.mmio_start, finfo.mmio_len );
            
            // Get variable screen information
            if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {            // 获取设备可变信息
                        printf("Error reading variable information.
    ");
                        exit(3);
            }
            printf("%dx%d, %dbpp
    ", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
            // Figure out the size of the screen in bytes
            screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; // 申请存放整个屏幕颜色数据的内存大小
            // Map the device to memory 通过mmap系统调用将framebuffer内存映射到用户空间,并返回映射后的起始地址
            fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
                 fbfd, 0);
            if ((int)fbp == -1) {
                        printf("Error: failed to map framebuffer device to memory.
    ");
                        exit(4);
            }
            printf("The framebuffer device was mapped to memory successfully.
    ");
            
            vinfo.xoffset = (480-240)/2; // (计算屏幕图像在屏幕中间一块区域显示)Where we are going to put the pixel (x坐标偏移量:120) 要分清一块屏有宽和高,宽即用x坐标表示,高用y表示,和直角坐标系一样
            vinfo.yoffset = (280-140)/2; // (y坐标偏移量:70) 即该区域的左上角的像素点坐标为(x,y)=(120,70),右下角的坐标为(x,y)= (120+240,70+140)
                 b = 10; // 即blue : 0000 0010
                 g = 100; // A little green 即green: 0000 0100
                 r = 100; // A lot of red 即red : 0000 0100
            // Figure out where in memory to put the pixel
            for ( y = 0; y < 140; y++ )                // 行扫描
                for ( x = 0; x < 240; x++ ) {            // 列扫描
            
                 location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +    // 定位到具体哪一行的第几个像素
                     (y+vinfo.yoffset) * finfo.line_length; //定位到哪一行(即该行的第一个像素的地址) 这两句即是实现求某一个像素的地址的功能
            
                 if ( vinfo.bits_per_pixel == 32 ) {        //        
                                *(fbp + location) = b; // Some blue
                                *(fbp + location + 1) = g;             // A little green
                                *(fbp + location + 2) = r;             // A lot of red
                                *(fbp + location + 3) = 0;     // No transparency
                 } else {          //16bpp: r:g:b=5:6:5                                                //assume 16bpp
            
                                unsigned short int t = r<<11 | g << 5 | b;
                                *((unsigned short int*)(fbp + location)) = t;
                 }
            
                }
            munmap(fbp, screensize);
            close(fbfd);
            return 0;
        }

    运行结果如下:

    open framebuffer device successfully
    DISP3 BG
    type:0x0
    visual:2
    line_length:960

    smem_start:0x3c080000,smem_len:268800
    mmio_start:0x0 ,mmio_len:0
    pixel:480x280, bits_per_pixel:16bpp
    success to map framebuffer device to memory

    分析如下:

    struct fb_var_screeninfo 和 struct fb_fix_screeninfo 两个数据结构是在/usr/include/linux/fb.h中定义的:(都是无符号32位的整数)
    在fb_fix_screeninfo中有,这里的值不能改变
    __u32 smem_len 是这个/dev/fb0的大小,也就是内存大小。
    __u32 line_length 是屏幕上一行的点在内存中占有的空间,不是一行上的点数。
    在fb_var_screeninfo 中有,这里的值可以改变
    __u32 xres ,__u32 yres 是x和y方向的分辨率,就是两个方向上的点数。
    __u32 bits_per_pixel 是每一点占有的内存空间。

    其中line_length:960 ---> 每行字节数,屏幕分辨率480x280,而且bpp为16(即两个字节表示一个像素点),所以一行共有480x2=960字节(一行480个像素,一个像素2字节表示)

    smem_len:可以看到内存长度为268800字节,与上面ls screensnap -l显示大小一样

    细心的你可能已经发现有些不对。屏幕上的点有480x280=134400个像素点,每个点占有两字节(16bpp)。屏幕一共的占有内存数为2x134400=268800 字节,恰好与smem_len内存长度一样。

    参考:http://www.360doc.com/content/17/0705/17/45105951_669116458.shtml

    参考中有一段内容是这样的:

    内存长度smem_len是6M,分辨率是1024x768,色彩深度是32位。细心的你可能已经发现有些不对。屏幕上的点有1024x768=786432个,每个点占有32比特。屏幕一共的占有内存数为32x786432=25165824 就是3145728字节,恰好是3M但是上面的程序告诉我们有6M的存储空间。这是因为在现代的图形系统中大多有缓冲技术,显存中存有两页屏幕数据,这是方便快速的改变屏幕内容实现动画之类比较高的要求。关于这种缓冲技术有点复杂,我们目前先不讨论。对于我们来说只有这3M内存来存放这一个屏幕的颜色数据。

    所以注意:smem_len:内存大小不一定就等于屏幕占有的内存数

  • 相关阅读:
    Java类加载器总结
    Java程序编译和运行的过程
    Spring+Struts2+Hibernate整合
    Spring+MyBatis+SpringMVC整合
    声明式事务管理
    Scala sbt 添加国内镜像
    持续天数算法
    idea run shell set user name
    java insert mysql 中文乱码
    Samba服务器 安装
  • 原文地址:https://www.cnblogs.com/fah936861121/p/7122685.html
Copyright © 2020-2023  润新知