嵌入式开发板LCD的使用

 一、了解

使用之前首先要了解一下,所使用的开发板LCD设备文件的位置。(我的开发板位置: /dev/fb0

文件 IO ——对 LCD设备文件的操作

控制LCD输出设备,就是往里面写像数数据;因此要知道所用的LCD屏的分辨率是多少。

我用的是7寸LCD屏,分辨率为: 800*480

一张图片是以光的三原色(RGB): red(0 ~ 255)green(0 ~ 255) blue(0 ~ 255)

而我们屏幕显示不止RGB三种,还有一个透明度,因此构成分辨率的是 ARGB ,而A透明度:是一种算法  不是颜色分量  范围依然是 0~255; 虽然不是颜色分量   但显存fb0 依然会将该分量计算在内

0x00 00 00 00 (以 A R G B 表示)A不用去管,填FF和00 没什么区别。

unsigned int color = 0x00FF0000;//红色

unsigned int color = 0x0000FF00;//绿色

unsigned int color = 0x000000FF;//蓝色

以上可知,写入fb0 显存的数据ARGB 是占4个字节为一个像数点,总的有800*480个像数点,因此写入显存的真正大小是:800*480*4

下面以一个简单的例子,熟悉一下

要求在 屏幕 显示单颜色绿色:

#include 
#include 
#include 
#include 
#include //read

int main()
{
	int i;//
	int fb0_fd;//lcd文件描述符
	unsigned int color = 0x0000FF00;//绿色
	
	fb0_fd = open("/dev/fb0",O_WRONLY);//只写
	if(-1 == fb0_fd)
	{
		perror("open fb0 fail");
	}
	
	//int i;
	for(i=0;i<800*480;i++)
	{
		write(fb0_fd,&color,4);
	}
	
	close(fb0_fd);
	
	return 0;
}

 

 

 

图片每一个像素点RGB分量都不一致,导致无法以上述那种简单的方式去显示一张五颜六色的图片,因此我们需要拿别人的RGB信息(搬运)。

bmp 格式的图片: 800*480*3 == 1152000字节 = 1.098M

而一张图片的实际大小是 1,152,054 字节

多出的54 字节是,bmp的文件头(位图文件头:14字节,位图信息头:40字节)

#include 
#include 
#include 
#include 
#include //read
#include 

int main()
{
	int i;//
	int j;//循环计数值
	int fb0_fd;//lcd文件描述符
	int bmp_fd;//打开图片的描述符
	char bmp_buf[800*480*3]={0};
	char bmp4_buf[800*480*4]={0};//转换处理后4自己包含A

/*****************打开lcd设备文件******************************/
	fb0_fd = open("/dev/fb0",O_RDWR);//
	if(-1 == fb0_fd)
	{
		perror("open fb0 fail");
		return 0;
	}

/*************************打开图像文件*************************/
	bmp_fd = open("./1.bmp", O_RDONLY);
	if(-1 == bmp_fd)
	{
		perror(" open bmp fail");
		return 0;
	}

/*******************先跳过54字节bmp文件信息头*******************/

	lseek(bmp_fd,54,SEEK_SET);

/***********************处理图像信息************************/	
	read(bmp_fd, bmp_buf, 800*480*3);
	for(i=0,j=0;i<800*480*4;i+=4,j+=3)
	{	//B G R A      B G R
		bmp4_buf[i+2] = bmp_buf[j+2];
		bmp4_buf[i+1] = bmp_buf[j+1];
		bmp4_buf[i+0] = bmp_buf[j+0];
	}
/***********************写到LCD************************/	
	write(fb0_fd,bmp4_buf,800*480*4);
	
	close(fb0_fd);
	close(bmp_fd);

	return 0;
}

问题:会出现翻转问题(上下,左右,镜像翻转)

如果使用单循环(800*480)---循环式连续性 不分行列 需要判断if才能行列翻转很麻烦
                使用循环嵌套解决行列处理:
                    for(y=0,j=0;y<480;y++)//行循环
                    {
                        for(x=0;x<800;x++,j+=3)//列循环
                        {
                            //                                                 B                          G                             R
                            *(pfb0+(479-y)*800+ x) = (bmp_buf[j]<<0) | (bmp_buf[j+1]<<8) | (bmp_buf[j+2]<<16);
                            //通过行列xy的组合公式访问对应的显存映射空间  再赋值
                        }
                    }
                    
翻转现在只要处理 y  或 x 即可     (479-y)是上下翻转  (799-x)是左右翻转

 

利用显存映射 来显示图片:

内存映射技术(内核)

mmap:
    函数功能:映射一个文件(设备文件或其它文件--要用write)的空间到内存(可以直接赋值)

需要用到的头文件:#include #include

        void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
            参数1:addr  你指定的映射后内存中空间的首地址  我们一般不指定---NULL  空间由系统自动分配
            参数2:length  分配空间的大小  800*480*4
            参数3:prot  映射后空间的 权限 PROT_READ 、  PROT_WRITE 、 PROT_NONE(不能存取)
                        PROT_READ | PROT_WRITE  (读写权限)
            参数4:flags    空间属性 MAP_SHARED(空间共享属性)   MAP_PRIVATE(私有属性)    
            参数5:fd    你需要映射的文件  fb0_fd
            参数6: offset  偏移(必须分页大小的整数倍)     0 (不偏移) 
                
            返回值:如果addr是NULL  那返回值就是映射后空间的首地址
                        失败:返回MAP_FAILED(-1)
            

解除映内存射

int munmap(void *addr, size_t length);

参数1:用来取消addr所指的映射内存起始地址。

参数2:是想取消的内存大小。

ARGB(这个是显存映射到内存后的RGB顺序 和之前内存定义数组的顺序BGRA不一致)

所以  赋值操作应该是  BGR ---> BGRA     BGRA = (B<<0) | (G<<8) | (R<<16)

程序如下:

#include 
#include 
#include 
#include 
#include //read
#include //mmap

#define MMAP_LENTH 800*480*4

int main()
{
	int x,y;//循环嵌套赋值显存数据的行列计数值
	int j;//循环计数值
		
	int fb0_fd;//lcd文件描述符
	int bmp_fd;
	char bmp_buf[800*480*3]={0};
	char bmp4_buf[800*480*4]={0};//转换处理后4自己包含A
	
	unsigned int *pfb0;
	
	//打开lcd设备文件
	fb0_fd = open("/dev/fb0",O_RDWR);//只写
	if(-1 == fb0_fd)
	{
		perror("open fb0 fail");
	}
	
	//映射
	pfb0 = mmap(NULL,MMAP_LENTH,PROT_READ | PROT_WRITE,MAP_SHARED,fb0_fd,0);
	if ( pfb0 == MAP_FAILED)
	{
		perror("mmap fail");
		return 0;
	}
	
	//打开图像文件
	bmp_fd = open("/workspace/1.bmp",O_RDONLY);
	if( -1 == bmp_fd )
	{
		perror("open bmp fail");
	}
	
	//先跳过54字节bmp文件信息头
	lseek(bmp_fd,54,SEEK_SET);
	//再读出所有像素点数据
	read(bmp_fd,bmp_buf,800*480*3);

	
	for(y=0,j=0;y<480;y++)
	{
		for(x=0;x<800;x++,j+=3)
		{
		    // 		              B                G                    R
		*(pfb0+(479-y)*800+ x) = (bmp_buf[j]<<0) | (bmp_buf[j+1]<<8) | (bmp_buf[j+2]<<16);
		}
	}
	
	close(fb0_fd);
	close(bmp_fd);
	munmap(pfb0,MMAP_LENTH);
	return 0;
}

 

你可能感兴趣的:(linux)