模板网站官网,广东城市建设档案馆官方网站,云南省文山建设厅网站,免费申请注册网站1 LCD操作原理
linux中通过framebuffer驱动程序来控制LCD。framebuffer中包含LCD的参数#xff0c;大小为LCD分辨率xbpp。framebuffer 是一块内存 内存中保存了一帧图像。 关于图像的帧指的是在图像处理中#xff0c;一帧#xff08;Frame#xff09;是指图像序列中的单个…1 LCD操作原理
linux中通过framebuffer驱动程序来控制LCD。framebuffer中包含LCD的参数大小为LCD分辨率xbpp。framebuffer 是一块内存 内存中保存了一帧图像。 关于图像的帧指的是在图像处理中一帧Frame是指图像序列中的单个静止图像。当连续的图像以每秒多帧的速度播放时就可以产生动画、视频或电影。每一帧都是由像素组成的二维网格每个像素都包含颜色和亮度信息。通过在连续的帧之间进行快速切换人眼会感知到连续的动态效果。因此一帧是构成动画和视频的基本单元。 LCD的操作过程 1、驱动程序设置好LCD控制器 根据 LCD 的参数设置 LCD 控制器的时序、信号极性 根据 LCD 分辨率、BPP 分配 Framebuffer。 2、APP 使用 ioctl 获得 LCD 分辨率、BPP 3、APP 通过 mmap 映射 Framebuffer在 Framebuffer 中写入数据 假设需要设置 LCD 中坐标(x,y)处像素的颜色首要要找到这个像素对应的内存然后根据它的 BPP 值设置颜色。也就是找到内存所对应的地址然后给他赋值。假设 fb_base 是 APP 执行 mmap 后得到的 Framebuffer 地址首地址 计算公式 (xy)像素起始地址fb_base(xres*bpp/8)y xbpp/8 xresx方向分辨率bpp每个像素的位数 /8:将位数换算成字节 y y坐标这里从第0行开始所以不用减1 x x坐标 bpp 每个像素的位数bits per pixel 有RGB888 565 555格式 对于 32BPP一般只设置其中的低 24 位高 8 位表示透明度一般的 LCD都不支持。 对于 24BPP硬件上为了方便处理在 Framebuffer 中也是用 32 位来表示效果跟 32BPP 是一样的。 对于 16BPP常用的是 RGB565很少的场合会用到 RGB555这可以通过ioctl 读取驱动程序中的 RGB 位偏移来确定使用哪一种格式 这里补充一下寻址方式一般为字节寻址也就是说一个地址对应的一个储存单元能储存8位数据。
实验一 并画一条直线
#include fcntl.h
#include stdint.h
#include stdio.h
#include sys/ioctl.h
#include linux/fb.h
#include sys/mman.h
#include sys/types.h
#include string.h
#include unistd.h
static struct fb_var_screeninfo var;
static int fd_fb;
static unsigned int screen_size;
static unsigned int line_width;
static unsigned int pixel_width;
static unsigned char *fb_base;
static void lcd_put_pixel(int x, int y,int color)
{unsigned char *pen_8 fb_basey*line_widthx*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_8color;//printf(*pen_8 %d\n,*pen_8);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;// printf(*pen_16 %d\n,*pen_16);break;}case 32:{*pen_32 color;// printf(*pen_32 %d\n,*pen_32);break;}default:{printf(cant surport %dbpp\n, var.bits_per_pixel);break;}}
}
int main(char argc, char **argv)
{int i;//这里我先提个问题如何确定设备驱动文件的/* 以只读方式打开驱动设备文件 */fd_fb open(/dev/fb0, O_RDWR);if(fd_fb0){printf(cannot open /dev/fb0 \n);return -1;}/* fd_fb是一个打开的 Framebuffer 设备文件的文件描述符。
FBIOGET_VSCREENINFO是一个常量宏表示获取可见屏幕信息的操作。
var是一个指向 vscreeninfo 结构体的指针用于接收获取到的可见屏幕信息。 */// ioctl成功返回 失败-1if (ioctl(fd_fb, FBIOGET_VSCREENINFO,var)){printf(can not get var \n);return -1;}/* 一行的字节数 */line_width var.xres *var.bits_per_pixel/8;/* bpp转换成字节 */pixel_width var.bits_per_pixel/8;screen_size var.xres*var.yres*var.bits_per_pixel/8;printf(var.bits_per_pixel %d\n,var.bits_per_pixel);/* MAP_SHARED 表示映射区域与其他进程共享。0表示映射区域在文件中的偏移量此处为从文件开头开始映射。*/fb_base(unsigned char *)mmap(NULL ,screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);/* mmap 调用失败它会返回 MAP_FAILED通常定义为 (void *)-1 */if(fb_base (unsigned char *) -1){printf(can not mmap \n);return -1;}memset(fb_base, 0xff, screen_size);for ( i 0; i 100; i){lcd_put_pixel(var.xres/2i,var.yres/2,0xFF0000);}munmap(fb_base, screen_size);close(fd_fb);return 0;
}实验效果 在屏幕中间从左至右画了一条横线 终端打印出var.bits_per_pixel 32 这里我有几个问题 1、mmap返回值转换成uchar*类型 这时注意地址并没有变地址这个指针操作系统是多少位他就永远是多少位他指向的内容也不会变只是寻址方式发生变化 就比如我们看datasheet stm32 的一个寄存器偏移地址为0x00而下一个为0x04 他就是以四个字节递增的。 再比如我们从flash中读取一段数据 要区分半字读还是字读。
2、这引入了第二个问题 x后地址偏移的字节数是根据pixel_width决定的 pixel_width var.bits_per_pixel/8; var.bits_per_pixel 为32位那么一次偏移4个字节刚好32位存储32位数据 也就是说2进制编码中一个地址存放1位数据0/1 0x1000 到0x1004 则跨了四个字节32位能存储32位数据。