LINUX下LCD驱动的基础知识

本文详细介绍了如何使用MP157驱动控制LCD屏幕,包括LCD显示原理、RGB颜色格式、基本显示步骤(如打开设备、获取参数、映射内存、修改像素颜色),以及一个示例代码来画斜线。作者还探讨了直接控制像素点的挑战和可能使用的开发工具。
摘要由CSDN通过智能技术生成

最近在学习MP157驱动LCD屏幕的内容,跟着做一些笔记和自己的理解

1.LCD显示的原理

通过控制LCD多个像素点的颜色也进行图像显示

2.常用的颜色RGB格式

位深度来分:

8bits: 256中颜色-调色板 颜色与常用的256种颜色建立映射关系

16bits:常用格式RGB565 即red green blue各拥有 5 6 5位

32bits:最高字节表示透明度 r g b各一个字节 有256*256*256种颜色

3.LCD显示的基本步骤

1.使用open系统调用打开屏幕设备

	screen_fd = open("/dev/fb0",O_RDWR);
	if(screen_fd < 0)
	{
		perror("open /dev/fb0 failed!\n")
		exit(EXIT_FAILURE);
	}

2.使用ioctl系统调用获取LCD屏幕的参数:主要包括像素长宽和位深度

if(ioctl(screen_fd,FBIOGET_VSCREENINFO,&screen_info) == 0)
	{
		//获得屏幕参数
		//2.1屏幕像素 长宽
		screen_length = screen_info.xres;
		screen_width = screen_info.yres;
		
		//2.2单个像素点的RGB位数
		screen_single_rgb_bits = screen_info.bits_per_pixel;
		
		//2.3用以显示整个屏幕的像素点的字节数
		screen_size = screen.bits_per_pixel / 8 * screen_info.xres * screen_info.yres;

        //2.4打印出屏幕参数用于观察
        printf("screen information: length-%d width-%d rgb_bits-%d\n",screen_length,screen_width,screen_single_rgb_bits);
	}
	else
	{
		perror("ioctl get screen-info failed\n");
		exit(EXIT_FAILURE);
	}

3.使用mmap将用于展示整块屏幕的像素颜色的字节(framebuffer)映射到内存中,并和打开的屏幕描述符绑定起来,修改这些数据的内容即修改位置上像素点的颜色,即修改了显示的图像

mmap_ptr = (unsigned char *)mmap(NULL,screen_size,PROT_READ|PROT_WRITE,MAP_SHARED,screen_fd, 0);
	if(mmap_ptr == (unsigned char*)-1)
	{
		perror("mmap failed!\n")
		close(screen_fd);
		exit(EXIT_FAILURE);
	}

4.建立修改单个像素点的函数,在像素点(x,y)那么它前面有多少个像素点,是不是前面y行(索引0开始)加上最后一行的x个,即x*length+y个像素点,如果每个像素点颜色为n字节,那么前面的字节数量是不是(x*length+y)*n,那么指针应该指向mmap分配内存的首指针先后偏移这么多

    --------------> x
    |
    |
    |
    |
    y
//根据 (不同rgb位格式) 在 (指定像素点) 显示 (指定颜色 格式:0xffff) 
void lcd_show_specified_point(unsigned char bit_length, unsigned int x, unsigned int y,unsigned int color)
{
    unsigned char  *ptr_8 = mmap_ptr+(y*screen_length+x)*(bit_length/8);
	unsigned short *ptr_16;	
	unsigned int   *ptr_32;	

	unsigned int red, green, blue;	

	ptr_16 = (unsigned short *)ptr_8;
	ptr_32 = (unsigned int *)ptr_8;

	switch (bit_length)
	{
		case 8:
		{
			*ptr_8 = color;
			break;
		}
		case 16:
		{
			/* RGB565 */
			red   = (color >> 16) & 0xff;
			green = (color >> 8) & 0xff;
			blue  = (color >> 0) & 0xff;
			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*ptr_16 = color;
			break;
		}
		case 32:
		{
			*pen_32 = color;
			break;
		}
		default: 
		{
			printf("can't surport %dbpp\n", bit_length);
			break;
		}
	}
}

5.关闭mmap映射和打开的屏幕文件,记得展示之前对屏幕清屏

	munmap(mmap_ptr, screen_size);
	close(screen_fd);

4.完整代码--画个斜线

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define RED 0xFFFF0000
#define ORIGIN 0xFFFFA500

unsigned char * mmap_ptr;
struct fb_var_screeninfo screen_info; //存放屏幕信息结构体
unsigned int screen_length;
unsigned int screen_width;
unsigned int screen_size;
unsigned int screen_single_rgb_bits;
int screen_fd;


//根据 (不同rgb位格式) 在 (指定像素点) 显示 (指定颜色 格式:0xffff) 
void lcd_show_specified_point(unsigned char bit_length, unsigned int x, unsigned int y,unsigned int color)
{
    /*颜色位深度:
    8bits: 256中颜色-调色板 颜色与常用的256种颜色建立映射关系
    16bits:常用格式RGB565 即red green blue各拥有 5 6 5位
    32bits:最高字节表示透明度 r g b各一个字节 有256*256*256种颜色
    --------------> x
    |
    |
    |
    |
    y
    */
    unsigned char  *ptr_8 = mmap_ptr+(y*screen_length+x)*(bit_length/8);
	unsigned short *ptr_16;	
	unsigned int   *ptr_32;	

	unsigned int red, green, blue;	

	ptr_16 = (unsigned short *)ptr_8;
	ptr_32 = (unsigned int *)ptr_8;

	switch (bit_length)
	{
		case 8:
		{
			*ptr_8 = color;
			break;
		}
		case 16:
		{
			/* RGB565 */
			red   = (color >> 16) & 0xff;
			green = (color >> 8) & 0xff;
			blue  = (color >> 0) & 0xff;
			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*ptr_16 = color;
			break;
		}
		case 32:
		{
			*ptr_32 = color;
			break;
		}
		default: 
		{
			printf("can't surport %dbpp\n", bit_length);
			break;
		}
	}
}

int main(int argc, char *argv[])
{
	unsigned int i,j;

    //1.打开屏幕设备
	screen_fd = open("/dev/fb0",O_RDWR);
	if(screen_fd < 0)
	{
		perror("open /dev/fb0 failed!\n");
		exit(EXIT_FAILURE);
	}
	
	//2.利用ioctl获取屏幕可变参数
	if(ioctl(screen_fd,FBIOGET_VSCREENINFO,&screen_info) == 0)
	{
		//获得屏幕参数
		//2.1屏幕像素 长宽
		screen_length = screen_info.xres;
		screen_width = screen_info.yres;
		
		//2.2单个像素点的RGB位数
		screen_single_rgb_bits = screen_info.bits_per_pixel;
		
		//2.3用以显示整个屏幕的像素点的字节数
		screen_size = screen_info.bits_per_pixel / 8 * screen_info.xres * screen_info.yres;

        //2.4打印出屏幕参数用于观察
        printf("screen information: length-%d width-%d rgb_bits-%d\n",screen_length,screen_width,screen_single_rgb_bits);
	}
	else
	{
		perror("ioctl get screen-info failed\n");
		exit(EXIT_FAILURE);
	}
	
	/*3.利用mmap函数将这大段字节数据映射到内存中 并和屏幕设备文件描述符绑定 
	    以后改变mmap_ptr指向的screensize字节的值即改变屏幕显示*/
	mmap_ptr = (unsigned char *)mmap(NULL,screen_size,PROT_READ|PROT_WRITE,MAP_SHARED,screen_fd, 0);
	if(mmap_ptr == (unsigned char*)-1)
	{
		perror("mmap failed!\n");
		close(screen_fd);
		exit(EXIT_FAILURE);
	}

	//4.清屏: 全部设为白色 rgb:fffa
    printf("clean screen!\n");
	memset(mmap_ptr,0xff,screen_size);

	//5.画出具体物体:斜线 
	for(i=0;i<screen_width;i++)
	{
        for(j=0;j<screen_length;j++)
        {
            if(i==j)
            {
               lcd_show_specified_point(screen_single_rgb_bits,j,i,ORIGIN);
            }
        }
	}
    printf("show complete!\n");
	
	//6.解除映射 关闭文件描述符
	munmap(mmap_ptr, screen_size);
	close(screen_fd);
    printf("close all!\n");
	
	return 0;	
}

5.疑问

如果这样来控制像素点的颜色来控制lcd屏幕的显示好像很困难,比如想画个小猫 那不是相当的困难,各位大神像 lcd屏幕界面一般使用什么工具去开发,小白不太了解,望解答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值