LCD的映射mmap()、GEC6818开发板刷图

一、LCD的映射
 将一段内核空间的地址映射到进程的虚拟地址空间;使用这种方法之后,我们操作LCD
就可以不需要使用read\write这种;因为使用read\write来写LCD的效率比较低(很明显)
你可以看到LCD上面显示图像的花纹边。
 使用mmap这种方法之后,我们直接操作LCD那段内核空间的地址,大大提高了LCD的刷新
效率,使图像刷新的更快。

LCD的映射mmap()、GEC6818开发板刷图_第1张图片

 

1.mmap--->man 2 mmap 空间映射
       #include

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
参数:
    addr: NULL,直接给NULL内核空间帮你选择
             If  addr  is NULL, then the kernel chooses the address at which to create
               the mapping;
    length:LCD的大小 800*480*4(byte)
    prot:权限 PROT_READ | PROT_WRITE 可读可写
               PROT_EXEC  Pages may be executed. 可执行
              PROT_READ  Pages may be read.
               PROT_WRITE Pages may be written.
               PROT_NONE  Pages may not be accessed.
    flags:标志量 MAP_SHARED  (选褒义词)
        MAP_SHARED 可见
        MAP_PRIVATE 不可见
    fd:文件描述符
    offset:偏移量 如果写整个LCD 不偏移 = 0
返回值:
    成功:返回这段映射空间地址的指针
    失败;NULL

2.munmap 空间映射的释放
       #include

       int munmap(void *addr, size_t length);
参数:
    addr:mmap函数返回的指针
    length:释放空间的大小
返回值:
    成功:0
    失败:-1

练习1:
用mmap来实现刷颜色,对比普通的read write读写,观察两种方法的LCD的显示效果

练习2:
addr使用mmap实现德国国旗

二、刷图
1.图片的格式
jpg、jpeg、png:这种格式的图片都是数据压缩后的图片,这种格式的图片里面的数据都不是它的原始数据
bmp:位图(bit map) 这种格式的图片里面的数据是它的原始数据,我们就可以通过read函数来读取它里面的原始数据。

LCD的映射mmap()、GEC6818开发板刷图_第2张图片 LCD的映射mmap()、GEC6818开发板刷图_第3张图片

 

 

2.如何制作一张位图(bmp图片)
制作一张800*480bmp图片的大小 1.1M
制作一张800*480jpg图片的大小 262KB
总结:
 虽然bmp图片和jpg图片的分辨率一模一样,但是bmp图片的大小要比jpg图片大很多;
如果我们要使用jpg这种格式的图片需要使用第三方软件库;如果使用bmp图片我们就可以直接使用read函数读取数据

3.bmp图片的分辨率大小(以800*480举例)
800*480(像素点)

4.bmp图片里面1个像素点=多少个字节
1个像素点是3个字节 = 由RGB组成没有A透明度
(LCD是4个字节 图片3个字节)

5.一张800*480像素点的bmp图片的大小是多少(字节)
800*480*3+54 = 1152000+54 = 1152054

6.bmp图片的头文件信息
bmp图片的头54个字节不是它的画面数据,而是它图片的格式信息。
包含分辨率大小、格式等等

LCD的映射mmap()、GEC6818开发板刷图_第4张图片

 

练习3:
char a = 0x12;
char b = 0x34;
char c = 0x56;
通过移位和位或运算,得出0x563412
int d = c<<16|b<<8|a<<0
printf("d=%#x\n",d);
验算过程如下:
c<<16 = 0x56<<16 = 1001 1010<<16 = 1001 1010 0000 0000 0000 0000
b<<8 = 0x34<<8    =   0011 0100<<8 =                 0011 0100 0000 0000 
c<<16|b<<8           =                             1001 1010 0011 0100 0000 0000
a = 0x12                 =                            0001 0010      
c<<16|b<<8|a        =                              1001 1010 0011 0100 0001 0010
c<<16|b<<8|a        =                               5      6      3        4         1       2    =(0x563412)

 刷图:

 

	//打开lcd
	int lcd = open("../../dev/fb0",O_RDWR);
	if(lcd < 0)
	{
		perror("open error!\n");
		return -1;
	}
	
	//lcd映射
	//指针指向一个像素点
	int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	if(p == NULL)
	{
		perror("mmap fail!\n");
		return -1;
	}	
	//打开bmp图片
	int lcd_bmp = open("1.bmp",O_RDWR);
	if(lcd_bmp < 0)
	{
		printf("open bmp fail!\n");
		return -1;
	}
	
	//去除掉头54个字节
	lseek(lcd_bmp,54,SEEK_SET);

	//存储bmp图片的buffer:800*480*3
	char buf[800*480*3] = {0};
	
	//读bmp图片
	read(lcd_bmp,buf,800*480*3);
	
	//将buf数据通过指针p填充到LCD中	
	// int i;
	// for(i=0;i<800*480;i++)
	// {
		// *(p+i) = buf[3*i] |buf[3*i+1]<<8 |buf[3*i+2]<<16;
	// }

	//将buf数据通过指针p填充到LCD中
	int x;//x表示横轴
	int y;//y表示纵轴
	for(y=0;y<480;y++)
	{
		for(x=0;x<800;x++)
		{
			/*
				将buf[]里面的数据由BGR换成RGB
				将3个字节封装成4个字节
			*/
			*(p+(y*800+x)) = buf[3*(y*800+x)] |buf[3*(y*800+x)+1]<<8 |buf[3*(y*800+x)+2]<<16;
				/* 
			        0    =  buf[0] | buf[1]<<8 | buf[2]<<16
					1    =  buf[3] | buf[4]<<8 | buf[5]<<16
					2    =  buf[6] | buf[7]<<8 | buf[8]<<16
					800    =  buf[800*3] | buf[800*3+1]<<8 | buf[800*3+2]<<16
				 */	
		}
	}


	
	//lcd映射释放
	munmap(p,800*480*4);
	
	//关闭lcd\bmp
	close(lcd);
	close(lcd_bmp);

运行结果: 

LCD的映射mmap()、GEC6818开发板刷图_第5张图片

 

你可能感兴趣的