MIPI_DSI屏
一 软件配置
1.1 屏幕相关配置
以开发板硬件lcd为例 ,lcd配置
(不同 lcd在不同板级设备引脚可能不同, 要根据原理图配置.)
此设备gpio backlight enable不设置, 在背光驱动里面单独配置. lcd及触摸屏供电共用一个gpio,通过设备电源管理"GPIO-POWER0" 控制
1.2 背光配置
默认使用pwm调整背光亮度
需要用到pwm驱动
1.3 framebuffer 配置
进入如下的配置目录, 勾选framebuffer 驱动, 并进入配置.
默认使用直通,若画面显示有异常或lcd underrun等报错,可以选择mixer, 旋转使用rotator
mixer及rotator默认多两帧fb内存消耗, rotator另外需要512 字节对齐, 分辨率800 ×1280的屏幕为例 , 计算如下
mixer 2帧:800×1280×4×2 , 可以修改帧数
rotator: 800×4需要被512整除, 实际消耗512×7×1280×2, 可以修改帧数, 旋转角度
fb帧数配置, 视频流默认可配置0帧,ui图形界面配置1帧
二 验证
开机启动后, 使用lsmod
命令查看驱动是否安装成功. 需要有下面3个驱动, 否则屏幕不能正常使用.
查询设备列表ls /dev/fb*
, 需要有fb设备. 否则fb驱动安装失败.
# ls /dev/fb*
/dev/fb0 /dev/fb1 /dev/fb_layer_mixer
三 使用cmd_fb工具命令实现显示效果
3.1 使能lcd, fb设备
如果/dev目录下
没有fb设备, 表示lcd或者fb驱动未初始化成功. 请重新检查上述配置, 编译. 烧录操作
# 使能 fb 设备,上电并初始化.
cmd_fb enable /dev/fb0;
# 在某一帧绘制一个方形数据, 绿色.
# x, y: 绘制像素点的起始位置.(默认是x=0, y=0)
# width, height: 绘制方块的宽度, 高度.(默认是lcd设备宽度, 高度)
# frame_index: 根据自己设置的帧缓冲选择. 上述我设置fb0帧缓冲数为2, frame_index可以使用的值0, 1.(默认是0)
cmd_fb draw_rect /dev/fb0 color=0xff00ff00 frame_index=0 x=0 y=0 width=200 height=200;
# 将某一帧缓冲的数据刷新到屏幕上
cmd_fb display /dev/fb0 frame_index=0;
# 将fb设备中的某一帧清除成指定颜色 白色
cmd_fb clear /dev/fb0 color=0xffffffff frame_index=0;
# 将某一帧缓冲的数据刷新到屏幕上
cmd_fb display /dev/fb0 frame_index=0;
实现叠层操作, 需要配置2个fb设备. 分别操作两个fb设备 fb0 和 fb1, 刷入不同的数据. 操作的方式如上. 这样就可以看到叠层的显示效果.
四 使用fb API编写程序实现显示效果
4.1 编写测试程序
将如下代码编译, 运行, 轮流显示各种颜色.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libhardware2/fb.h>
/* 绘制方形, 数据长度为32位.
** 向一块fb内存写入数据
*/
static void draw_rect32(unsigned int *p, int x, int y, int x1, int y1,
unsigned int color, struct fb_device_info *info)
{
p = (void *)p + y*info->line_length + x*4;
int i, j;
for (i = 0; i < y1 - y; i++){
for (j = 0; j < x1 - x; j++) {
p[j] = color;
}
p = (void *)p + info->line_length;
}
}
/* 绘制一个方形
** int x, int y: 绘制图像的起始点
** int weight, int height: 绘制图像的宽高
*/
static void draw_rect(void *mem, int x, int y, int width, int height,
unsigned int color, struct fb_device_info *info)
{
int xres = info->xres;
int yres = info->yres;
int x1 = (width < 0) ? xres : x + width;
int y1 = (height < 0) ? yres : y + height;
if (x1 > xres)
x1 = xres;
if (y1 > yres)
y1 = yres;
if (x < 0)
x = 0;
if (y < 0)
y = 0;
int bytes = info->line_length / info->xres;
if (bytes < 4) {
fprintf(stderr, "not support pix fmt: %d %d %d\n",
info->bits_per_pixel, info->line_length, info->xres);
exit(-1);
}
draw_rect32(mem, x, y, x1, y1, color, info);
}
int main(int argc, char *argv[])
{
int fd, ret;
struct fb_device_info info;
printf("lcd test...\n");
fd = fb_open("/dev/fb0", &info);
if (fd < 0) {
fprintf(stderr, "can`t open /dev/fb0.\n");
return -1;
}
ret = fb_enable(fd);
if (ret < 0) {
fprintf(stderr, "can`t enable fb.\n");
return -1;
}
/* 6种不同颜色的数据 */
unsigned int color[6] = {
0xffff0000,
0xffffff00,
0xffff00ff,
0xff00ff00,
0xff00ffff,
0xff0000ff,
};
void *fb_base = info.mapped_mem + info.frame_size * 0;
for (int i=0; i<12; i++) {
/* 在指定的内存区域, 填充显示数据 */
draw_rect(fb_base, 0, 0, -1, -1, color[i%6], &info);
ret = fb_pan_display(fd, &info, 0);
if (ret < 0) {
fprintf(stderr, "fb_pan_display error.\n");
return -1;
}
usleep(500 * 1000);
}
fb_close(fd, &info);
return 0;
}
4.2 测试程序编译和使用
编译流程
因为编译需要链接到一些君正提供的库文件, 使用/buildroot/buildroot24/output/host/bin/mips-linux-gnu-gcc
这个编译工具.
举例, 我的应用lcd_test.c文件在工程目录下的/myapp
目录.
进入/myapp目录
cd /myapp # 进入用户app目录
../buildroot/buildroot24/output/host/bin/mips-linux-gnu-gcc lcd_test.c -o lcd_test -lhardware2 # 使用编译器编译 指定库-lhardware2
将编译好的模块传输到文件系统有2种方式.
(1). 编译好的模块可以通过adb传输到板子上, 运行. 例如
adb push lcd_test /tmp
# 在设备终端上使用命令, 可以看到颜色刷屏效果.
cd /tmp
./lcd_test
(2). 打包到文件系统, bin文件会在/usr/bin文件目录下面.
cd myapp # 进入到用户app目录下
cp lcd_test ../buildroot/buildroot24/output/target/usr/bin/ # 拷贝模块到文件系统/usr/bin目录下.
# 进入/build目录
make buildroot # 重新打包文件系统, 重新烧录.
# 在设备终端使用命令, 运行. 可以看到颜色刷屏效果.
lcd_test
五 fb API相关说明
上述使用的API介绍
int fb_open(const char *dev_path, struct fb_device_info *info)
功能:打开fb设备驱动,获取fb操作句柄
参数:const char *dev_path 如:/dev/fb0 //fb设备路径
struct fb_device_info *info //需要初始化的info结构体
返回值:成功:fb操作句柄; 失败:-1
int fb_close(int fd, struct fb_device_info *info)
功能:关闭fb设备句柄,释放内存资源
参数:int fd //fb设备操作句柄
struct fb_device_info *info //需要被释放的info结构体
返回值:成功:0; 失败:负数.
int fb_enable(int fd);
功能:使能fb设备,上电
参数:int fd //fb设备操作句柄
返回值:成功:0; 失败:负数.
int fb_pan_display(int fd, struct fb_device_info *info, unsigned int frame_index);
功能:显示/刷新fb指定的帧
参数:int fd //fb设备操作句柄
struct fb_device_info *info //fb设备的相关信息的结构体
unsigned int frame_index //要显示帧的序号
返回值:成功:0; 失败:负数.