树莓派MIPI/DSI接口LCD屏的调试

树莓派MIPI/DSI接口LCD屏的调试

1. 问题:

树莓派CM4模块提供了两个HDMI, 两个DSI接口, 方便用户外接显示屏。 如果将树莓派当做电脑使用,可能使用HDMI接口,会比较方面和省心。但是在嵌入式设备上,我们希望能够使用DSI接口外接LCD屏幕。

如果你Google过raspberry DSI, 你就会知道针对DSI接口的调试,工程师们碰到的问题还是蛮多的。 这里我记录我自己的调试过程。

2. 硬件

本人使用的硬件有:

2.1 树莓派CM4模块

它的链接:

https://www.raspberrypi.com/products/compute-module-4/?variant=raspberry-pi-cm4001000

2.2 树莓派IO底板

它的链接:

https://www.raspberrypi.com/products/compute-module-4-io-board/

2.3 LCD屏 NHD-3.5-640480EF-MSXP-CTP

本人选择了一款3.5 英寸, 640 x 480像素,带触摸屏的LCD, 型号NHD-3.5-640480EF-MSXP-CTP。 它的价格还比较合理。

LCD的链接:

https://newhavendisplay.com/3-5-inch-ips-tft-mipi-interface-capacitive-touchscreen/

2.4 适配板

适配板是自己画的。

电路图非常简单,就不晒了。这里直接上PCB图

因为适配板非常简单, 距离很短,不考虑阻抗匹配应该也能工作。

但是为了性能好些,最好做一下匹配:单端50欧,差分100欧。

(如果对这板子感兴趣的话,可以通过以下链接购买

MIPI/DSI adaptor board for Raspberry Pi from Industrial electronics on Tindie)

2.4 硬件链接图

最后系统的连接如下:

因为LCD的背光需要16.8~20.4V的电压,考虑到我们没有使用PCIe插槽,所以直接给IO板上电18V,然后通过J20接口给LCD背光供电。 上图中的黑白两根线为18v。

3. 软件

Linux内核版本:

Linux raspberrypidylan 6.6.60-v8+

源代码地址: GitHub - raspberrypi/linux: Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/

4. 一些其他资源

LCD驱动芯片:FL7703NI

触摸屏芯片:FT5426

LCDx芯片驱动相关: https://support.newhavendisplay.com/hc/en-us/community/posts/24147208520727-NHD-3-5-640480EF-MSXP-FL7703NI-Linux-driver

LCD屏幕的一些参数:

https://support.newhavendisplay.com/hc/en-us/community/posts/23239667440151-Porch-values-of-NHD-3-5-640480EF-MSXP-CTP

5. 调试过程

5.1 屏幕的驱动

因为当前Linux源码不直接支持FL7703芯片,所以需要自己移植。

通过直接咨询newhavendisplay,他们告知该款芯片和Sitronix ST7703 非常类似。

所以FL7703的驱动可以在Sitronix ST7703 的基础上修改。

ST7703驱动源码的位置:

linux/drivers/gpu/drm/panel/panel-sitronix-st7703.c at master · torvalds/linux · GitHub

5.2 添加compatible和data数据 

static const struct of_device_id st7703_of_match[] = {

      { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc },

      { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },

      { .compatible = "xingbangda,xbd599", .data = &xbd599_desc },

      { .compatible = "forcelead,fl7703", .data = &NHD_35_MSXP_desc },

      { /* sentinel */ }

};

compatible的字符串内容后续要和dts对应上,这里是“forcelead,fl7703”

data数据是一个结构体NHD_35_MSXP_desc,用于描述屏幕的一些设置,下节定义。

5.3 添加屏幕的描述结构体

static const struct st7703_panel_desc NHD_35_MSXP_desc= {
        .mode = &NHD_35_MSXP_mode,
        .lanes = 4,
        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
                     MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,  
        .format = MIPI_DSI_FMT_RGB888,
        .init_sequence = NHD_35_MSXP_init_sequence,
}; 

NHD_35_MSXP_mode 也是一个结构体,用于定义LCD的屏幕同步信息以及时钟等等,后续5.4节添加。   

这里lanes设置为4通道。开始调试的时候, lanes可以设置为1,即单通道, 方便测试和调式。

flag要包含MIPI_DSI_MODE_LPM

NHD_35_MSXP_init_sequence()即是屏幕初始化的函数名。

5.4 添加drm_display_mode

drm_display_mode 用于设置屏幕的一个行同步,场同步的信息,基本上都是来自于产家,见上面第四节的链接。注意时钟的单位是kHz

static const struct drm_display_mode NHD_35_MSXP_mode = {
    .hdisplay       = 640,
    .hsync_start    = 640 + 120,
    .hsync_end      = 640 + 120 + 120,
    .htotal         = 640 + 120 + 120 + 120,
    .vdisplay       = 480,
    .vsync_start    = 480 + 25,
    .vsync_end      = 480 + 25 + 5,
    .vtotal         = 480 + 25 + 5 + 12, 
    .clock      = 31200,
    .flags      = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,  
    .width_mm       = 56,
    .height_mm      = 78,
};

5.5 添加初始化代码NHD_35_MSXP_init_sequence()

NHD_35_MSXP_init_sequence() 主要是做一些寄存器的初始化工作,代码如下:

static int NHD_35_MSXP_init_sequence(struct st7703 *ctx)
{   
	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);  
	msleep(50);
	fl7703ni_read_id(ctx);
	/*
	* Init sequence was supplied by the panel vendor.
	*/
	dev_err(ctx->dev, "NHD_35_MSXP_init_sequence dl!! 5\n");
	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x87);  //0xB9  //last is 0x87 from NH
	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x78, 0x14, 0x70); //0xB2
	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,  //0xB3
			      0x28, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);   //0xB4

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0A, 0x0A);  //0xB5

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x70, 0x70); //0xB6

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x26);//0xB8	      

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,  //0xBA  0x30 1 lane, 31 2 lanes 
		              0xF9, 0x0E, 0x0E, 0x20, 0x00, 0x00, 0x00, 0x00,
		              0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0A,
		              0x00, 0x00, 0x01, 0x4F, 0x01, 0x00, 0x00, 0x37);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);   //0xBC

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);  //0xBF		                     

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, //0xC0
		              0x00, 0x00, 0x12, 0x73, 0x00);		              

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x54, 0x00, 0x32, //0xC1
		              0x32, 0x77, 0xF4, 0x77, 0x77, 0xCC, 0xCC, 0xFF,
		              0xFF, 0x11, 0x11,0x00,0x00,0x31);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0x10, 0x00, 0x0A, 0x00, //0xC7
		              0x00, 0x00,0x00,0x00, 0xED, 0xC7, 0x00, 0xA5);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, //0xC8
		              0x03);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);  //0xCC 

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x05, 0x09, //0xE0
		              0x29, 0x3C, 0x3F, 0x3B, 0x37, 0x05, 0x0A, 0x0C,
		              0x10, 0x13, 0x10, 0x13, 0x12, 0x1A, 0x00, 0x05,
		              0x09, 0x29, 0x3C, 0x3f, 0x3B, 0x37, 0x05, 0x0A,
		              0x0C, 0x10, 0x13, 0x10, 0x13, 0x12, 0x1A);

	mipi_dsi_dcs_write_seq(dsi, 0xE1, 0x11, 0x11, 0x91,0x00, 0x00, 0x00, 0x00 );//0xE1 dylan, ONLY FN7703

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0B, 0x0B, //0xE3
		              0x03, 0x0B, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x04,
		              0xC0, 0x10);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x01, 0x00, 0x0E, 0x00,//0xE9
		              0x00, 0xB0, 0xB1, 0x11, 0x31, 0x23, 0x28, 0x10,
		              0xB0, 0xB1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
		              0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
		              0x88, 0x88, 0xBA, 0x60, 0x24, 0x08, 0x88, 0x88,
		              0x88, 0x88, 0x88, 0x88, 0x88, 0xBA, 0x71, 0x35,
		              0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
		              0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x00, 0x00, 0x00);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0A, 0x82, 0x02,
		              0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x81, 0x88, 0xBA, 0x17, 0x53, 0x88, 0x88, 0x88,
		              0x88, 0x88, 0x88, 0x80, 0x88, 0xBA, 0x06, 0x42,
		              0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
		              0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		              0x00);

	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xFF, 0xFF, 0x01);

	msleep(50);

	dev_err(ctx->dev, "NHD_35_MSXP_init_sequence Done\n");

	return 0;

}

需要注意的是  对寄存器ST7703_CMD_SETMIPI (地址0xBA)设置的lanes必须和5.3节的一致。

至此,驱动代码添加完毕。

https://blog.csdn.net/dylanZheng/article/details/144114763

但是本人为了调试的方便, 添加了一个读ID的函数,以此来判定DSI总线开始时是否是工作的。

5.6 读ID函数fl7703ni_read_id()

static int fl7703ni_read_id(struct st7703 *ctx)
{
	u8 id1, id2, id3;
	int ret;
	 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);

	ret = mipi_dsi_dcs_read(dsi, 0xDA, &id1, 1);
	if (ret < 0) {
		dev_err(ctx->dev, "could not read ID1  11\n");
		return ret;
	}

	ret = mipi_dsi_dcs_read(dsi, 0xDB, &id2, 1);
	if (ret < 0) {
		dev_err(ctx->dev,  "could not read ID2  22\n");
		return ret;
	}

	ret = mipi_dsi_dcs_read(dsi, 0xDC, &id3, 1);
	if (ret < 0) {
		dev_err(ctx->dev, "could not read ID3\n");
		return ret;
	}

	dev_info(ctx->dev,
		     "manufacturer: %02x version: %02x driver: %02x\n",
		     id1, id2, id3);
	return 0;
}

该函数在初始化代码函数NHD_35_MSXP_init_sequence()中被调用。

如果设备工作正常,能够读取到ID是: 38, 21和1f

6. 设备树overlay

仿照类似设备,编写如下overlay dts文件

/*

 * vc4-kms-dsi-fl7703-nhd35-overlay.dts  

 */


/dts-v1/;

/plugin/;


#include <dt-bindings/gpio/gpio.h>

/ {

        compatible = "brcm,bcm2835";

        fragment@0 {

                target = <&dsi1>;

                __overlay__  {

                        #address-cells = <1>;

                        #size-cells = <0>;

                        status = "okay";


                        port {

                                dsi_out: endpoint {

                                        remote-endpoint = <&panel_in>;

                                };
                        };

                        dsi_panel: dsi_panel@0 {                                                        

                                compatible = "forcelead,fl7703";

                                status        = "okay";

                                reg = <0>;                                

                                reset-gpios = <&gpio 21 1>; /* GPIO PIN 21, active Low */

                                //backlight = <&display_mcu>;

                                port {

                                        panel_in: endpoint {

                                                remote-endpoint = <&dsi_out>;

                                        };

                                };

                        };

                };

        };

};

上面的dts文件中compatible需要和5.2节的一致,即都是“forcelead,fl7703”, 否则linux会找不到对应的驱动。

reset-gpios 根据自己的需要修改,本人使用的是GPIO21。

7. config文件的修改

在config.txt文件中添加

dtoverlay=vc4-kms-dsi-fl7703-nhd35

当然同时要使能kms

dtoverlay=vc4-kms-v3d

8. 测试

测试结果直接上图

附上正常工作的一些log信息:

<think>嗯,用户想了解如何在香橙派上点亮MIPI幕。我需要先确认用户使用的具体型号,比如香橙派Zero 2W还是其他型号,因为不同型号的配置可能不同。然后,用户提到的MIPI幕,需要知道是DSI接口LCD,比如常见的5寸或7寸,不同幕的驱动可能不一样。 首先,硬件连接方面,要确保MIPI排线正确连接到香橙派的DSI接口,注意方向不要插反。还要检查供电,有些幕需要额外供电,可能需要通过GPIO或USB供电。 接下来是软件配置。香橙派通常使用Linux系统,比如Armbian或Orange Pi自己的镜像。需要确认内核是否支持对应的MIPI驱动,可能需要更新内核或配置设备树。用户可能需要修改dtb文件,启用DSI和对应的幕参数,比如分辨率、时序等。 然后,安装显示相关的软件,比如xserver-xorg、libdrm等。可能需要配置显示输出,指定使用MIPI幕为主显示器或扩展。如果使用Wayland,配置方式可能不同。 常见问题排查,比如检查连接是否稳固,是否有内核日志报错(dmesg),确认设备树是否正确加载,幕背光是否开启。有些幕需要加载特定的Overlay或模块。 最后,可能需要参考社区资源,比如香橙派论坛或GitHub上的项目,有些用户可能已经分享了配置文件和步骤,直接应用可以节省时间。提醒用户注意型号匹配,避免配置错误导致无法启动。</think>好的,我将分步骤为您介绍如何点亮香橙派(Orange Pi)的MIPI幕。以下是详细操作指南: --- ### **一、硬件准备** 1. **确认型号兼容性** - 香橙派型号:需支持MIPI-DSI接口(如Orange Pi Zero 2W、Orange Pi 3 LTS等) - MIPI幕:需匹配开发板DSI接口协议(常见如5寸/7寸MIPI LCD) 2. **物理连接** - 使用MIPI排线连接开发板的DSI接口(注意防反插设计) - 部分幕需额外供电(通过GPIO或USB接口) --- ### **二、软件配置** #### **步骤1:系统镜像选择** - 推荐使用Armbian或Orange Pi官方Linux镜像(需包含MIPI驱动支持) - 下载地址:Orange Pi官网或Armbian社区 #### **步骤2:设备树配置** 1. 编辑设备树文件(.dts或.dtsi): ```bash sudo nano /boot/dtb/allwinner/overlay/sun50i-h6-mipi-dsi.dts ``` 2. 添加幕参数(示例): ```dts panel: panel { compatible = "panel-dsi"; reg = <0>; reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; // GPIO_PG10 backlight = <&pwm_bl>; width-mm = <68>; height-mm = <121>; // 幕时序参数需根据具体型号填写 }; ``` #### **步骤3:启用设备树覆盖** 1. 在`/boot/armbianEnv.txt`中添加: ```text overlays=mipi-dsi param_mipi_dsi=width=720,height=1280 ``` #### **步骤4:安装显示驱动** ```bash sudo apt update sudo apt install xserver-xorg-core libdrm2 libdrm-test ``` --- ### **三、测试与调试** 1. **检查设备识别** ```bash dmesg | grep -i dsi # 查看MIPI-DSI驱动加载情况 ``` 正常输出应包含类似: ```text [ 2.350000] dsi-phy: DSI PHY initialized ``` 2. **手动点亮测试** ```bash echo 1 > /sys/class/backlight/panel/brightness ``` --- ### **四、常见问题解决** | 问题现象 | 排查方法 | |--------------------------|-----------------------------------| | 幕无显示 | 检查排线接触、供电、设备树配置 | | 花/闪 | 核对时序参数(hbp/hfp/vbp/vfp) | | 系统无法启动 | 检查设备树语法错误 | --- ### **五、参考资源** 1. **官方文档** - Orange Pi Wiki: http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero-2W.html 2. **社区案例** - GitHub开源项目:https://github.com/orangepi-xunlong/orangepi-build --- ### **注意事项** - 不同型号香橙派GPIO引脚定义可能不同,需核对原理图 - MIPI幕的初始化代码(`init_sequence`)需根据幕手册编写 如有具体型号需求,请提供开发板和幕型号,可进一步提供定制化配置!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值