最近在学习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屏幕界面一般使用什么工具去开发,小白不太了解,望解答