嵌入式Linux_Framebuffer_01描点画线

Framebuffer顾名思义,Frame是帧的意思,buffer是缓冲区的。Framebuffer中保存着每一帧图像的每一个像素的颜色值。

LCD操作原理

  • 驱动程序设置好LCD控制器
    • 根据LCD参数设置LCD控制器的时序,信号极性
    • 根据LCD分辨率,BPP分配Framebuffer
  • APP通过ioctl获取LCD的分辨率,BPP等参数
  • APP通过mmap映射Framebuffer,在Framebuffer中写入数据。
    在这里插入图片描述

从上图可以看到Framebuffer和LCD的可显示区域是一一对应的。使用Framebuffer显示实际就是向Framebuffer写入每个像素点的颜色数据。LCD的像素点的坐标与Framebuffer中的位置关系如下图
在这里插入图片描述
给出任意屏幕坐标(x,y),以及Framebuffer的基地址fb_base.另外LCD的分辨率是Xres x Yres,表示单个像素颜色的二进制位数bpp。则其颜色数据在framebuffer中的地址是:

(x,y)像素起始地址=fb_base + (y*Xres+x)*bpp/8

像素颜色表示

示例代码

#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 <sys/ioctl.h>
#include <math.h>
static int fd_fb;
static struct fb_var_screeninfo var;	/* Current var */
static int screen_size;					/* 一帧数据所占用的字节数*/
static unsigned char *fb_base;			/* Framebuffer首地址*/
static unsigned int line_width;			/* 一行数据所占用的字节数*/
static unsigned int pixel_width;		/* 单个像素所占用的字节数*/

/**********************************************************************
 * 函数名称: lcd_put_pixel
 * 功能描述: 在LCD指定位置上输出指定颜色(描点)
 * 输入参数: x坐标,y坐标,颜色
 * 输出参数: 无
 * 返 回 值: 会
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2020/05/12	     V1.0	  zh(angenao)	      创建
 ***********************************************************************/ 
void lcd_put_pixel(int x, int y, unsigned int color){
	unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;
	unsigned short *pen_16;	
	unsigned int *pen_32;	

	unsigned int red, green, blue;	

	pen_16 = (unsigned short *)pen_8;
	pen_32 = (unsigned int *)pen_8;

	switch (var.bits_per_pixel){
		case 8:{
			*pen_8 = color;
			break;
		}
		case 16:{
			/* 565 */
			red   = (color >> 16) & 0xff;
			green = (color >> 8) & 0xff;
			blue  = (color >> 0) & 0xff;
			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*pen_16 = color;
			break;
		}
		case 32:{
			*pen_32 = color;
			break;
		}
		default:{
			printf("can't surport %dbpp\n", var.bits_per_pixel);
			break;
		}
	}
}
int main(int argc, char **argv){
	int i;
	fd_fb = open("/dev/fb0", O_RDWR);/** 打开fb设备*/
	if (fd_fb < 0){
		printf("can't open /dev/fb0\n");
		return -1;
	}
	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){/** 获取屏幕可变信息*/
		printf("can't get var\n");
		return -1;
	}
	printf("RES:%d x %d\n",var.xres,var.yres);
	printf("one pixel bits:%d\n",var.bits_per_pixel);
	line_width  = var.xres * var.bits_per_pixel / 8;// 一行数据 占据字节数
	printf("line_width:%d byte\n",line_width);
	pixel_width = var.bits_per_pixel / 8;///单个像素占用的字节数
	printf("pixel_width:%d byte\n",pixel_width);
	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;//一帧画面占用的字节数
	printf("screen_size:%d byte\n",screen_size);
	fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);/** 映射framebuffer的首地址*/
	if (fb_base == (unsigned char *)-1){
		printf("can't mmap\n");
		return -1;
	}
	memset(fb_base, 0x00, screen_size);/* 清屏: 全部设为黑色 */
	/* 随便设置出100个为红点 */
	const double T=2*3.14;//周期
	const int A=100;//振幅
	double x,sin_y,cos_y;
	int start_x,start_y;//绘图的起始点像素坐标
	start_x=0;
	start_y = var.yres/2;
	
	while(1){
		for(i=0;i<var.xres;i++){
			x= (i*2*T)/(var.xres);
			sin_y = A*sin(x);
			cos_y = A*cos(x);
			int w=0;
			for(w=0;w<5;w++){
				
				lcd_put_pixel(start_x+i+w,start_y+sin_y, 0x00FF00);	
				lcd_put_pixel(start_x+i+w,start_y+cos_y, 0xFF0000);
			}
			usleep(1000);
		}
		memset(fb_base, 0x00, screen_size);/* 清屏: 全部设为黑色 */
	}
	munmap(fb_base , screen_size);/** 解除内存映射*/
	close(fd_fb);
	return 0;	
}

上述代码示例效果(手机拍出来效果略微偏色)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值