一、LCD的映射
将一段内核空间的地址映射到进程的虚拟地址空间;使用这种方法之后,我们操作LCD
就可以不需要使用read\write这种;因为使用read\write来写LCD的效率比较低(很明显)
你可以看到LCD上面显示图像的花纹边。
使用mmap这种方法之后,我们直接操作LCD那段内核空间的地址,大大提高了LCD的刷新
效率,使图像刷新的更快。
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函数来读取它里面的原始数据。
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个字节不是它的画面数据,而是它图片的格式信息。
包含分辨率大小、格式等等
练习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);
运行结果: