吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 659|回复: 4
上一主题 下一主题
收起左侧

[其他原创] 树莓3B适配bv050fwm mipi屏幕

[复制链接]
跳转到指定楼层
楼主
wshuo 发表于 2026-3-2 18:24 回帖奖励
本帖最后由 wshuo 于 2026-3-3 03:48 编辑

1. 前言

之前在网上淘了一个mipi屏幕型号是bv050fwm。正好研究一下linux对 mipi dsi屏幕驱动方式。  

2. 硬件驱动板

立创开源广场有大佬已经做了 驱动板:https://oshwhub.com/5473675a/28-yuan-make-5inch-touch-display

这里详细说明一些电路硬件部分,方便后续设备树的编写,15pin引脚为标准的树莓派mipi dsi接口。其内部定义:  

引脚号 功能
1 3V3
2 3V3
3 GND
4 I2C_SDA
5 I2C_SCL
6 GND
7 MIPI_DSI_D0P
8 MIPI_DSI_D0N
9 GND
10 MIPI_DSI_CLKP
11 MIPI_DSI_CLKN
12 GND
13 MIPI_DSI_D1P
14 MIPI_DSI_D1N
15 GND

可以看到除了 mipi 2line 线以外,还有个I2C接口,然后他们中间用GND分割用于屏蔽串扰。

驱动板还可以驱动触控,不过这里我只关注屏幕显示部分,所以不介绍此部分。
屏幕驱动 需要RST引脚,但15pin mipi中没有这一部分,所以电路借助了一个 PCA9536 芯片,用于拓展IO口(I2C->4 GPIO), 其中 俩路BL_EN (背光引脚), VCI_EN(屏幕使能引脚), LCD_RST_L(屏幕rest引脚)。

关于屏幕背光部分:
引脚定义


其pwm引脚是一个 输出引脚,所以调光的原理,是主机通过mipi协议想屏幕驱动板发送数据然后此引脚会输出一个pwm波,用于调控屏幕背光,  AP3019AKTR芯片接收pwm波,然后对VCC_LED_A, VCC_LED_K输出高电压。  

驱动板预留了,BL_EN 与BL_PWM短接的的位置,只需要用跳线冒短接,在driver中将其设置为高电平,相当于PWM占空比100%即屏幕最亮。

3. 树莓派上驱动此屏幕

3.1 编译设备树

对于树莓派要知道此硬件设备,需要在设备树中配置。
树莓派的 dtoverlay(设备树覆盖)机制,是一种在不修改内核主设备树文件(DTB)的前提下,动态地向系统添加或修改硬件描述的“热插拔”方案 。

所以这里使用dtoverlay的配置方式,进行配置屏幕的设备树:
vi boe-bv050fwm.dts

// SPDX-License-Identifier: GPL-2.0-only
/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2837";

    fragment@0 {
    target-path = "/soc/i2c0mux/i2c@1";
        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;
            pca9536: gpio@41 {
                compatible = "nxp,pca9536";
                reg = <0x41>;
                gpio-controller;
                #gpio-cells = <2>;
                status = "okay";
                gpio-line-names = "BL_EN", "VCI_EN", "LCD_RST", "TP_RST";
            };
        };
    };

    fragment@1 {
        target = <&dsi1>;
        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;
            panel: panel@0 {
                status = "okay";
                compatible = "boe,bv050fwm";
                reg = <0>;

                vci-gpios = <&pca9536 1 0>;
                reset-gpios = <&pca9536 2 1>;
                backlight-gpios = <&pca9536 0 0>;

                port {
                    panel_in: endpoint {
                        remote-endpoint = <&dsi1_out>;
                    };
                };
            };

            port {
                dsi1_out: endpoint {
                    remote-endpoint = <&panel_in>;
                    data-lanes = <0 1>;
                };
            };
        };
    };

    fragment@2 {
        target = <&spidev0>;
        __overlay__ {
            status = "disabled";
        };
    };
};

然后将其进行编译,并放到/boot/overlays/ 目录下:

dtc -@ -I dts -O dtb -o /boot/overlays/panel_boe_bv050fwm.dtbo boe-bv050fwm.dts

这里简单补充一下几个信息:

  1. 关于I2C通道,在树莓派3b使用mux(多路复用器), 如果直接指定I2C物理总线,会导致在调用pca9536模块进行i2c通信没有响应,直到timeout从而影响 屏幕驱动的reset vci backlight引脚,从而导致驱动屏幕失败,这个也是我在调试设备树遇到的最复杂的问题,所以这里指定的是"/soc/i2c0mux/i2c@1" 虚拟I2C通道,当mux检测到使用虚拟通道1时会自动进行切换通信,这样不需要每次进行唤醒切换。
  2. I2C总线下挂载pca9536 模块,其给屏幕提供 reset vci backlight引脚。
  3. panel面板中没有定义时序,时序有driver中进行定义,其会加载bv050fwm(驱动名字)。

在设备树编译完成后,在 /boot/firmware/config.txt 中使用 panel_boe_bv050fwm.dtbo

dtoverlay=panel_boe_bv050fwm
3.2 编译屏幕驱动

在编译内核驱动前,需要安装内核头文件:

sudo apt install linux-headers-$(uname -r) -y

touch panel-boe-bv050fwm.c

// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2019, Michael Srba

#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/backlight.h>
#include <video/mipi_display.h>

#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>

struct bv050fwm {
    struct drm_panel panel;
    struct mipi_dsi_device *dsi;
    struct regulator_bulk_data supplies[1];
    struct gpio_desc *vci_gpio;
    struct gpio_desc *reset_gpio;
    struct gpio_desc *backlight_gpio;

    bool prepared;
};

static inline struct
bv050fwm *to_bv050fwm(struct drm_panel *panel)
{
    return container_of(panel, struct bv050fwm, panel);
}

static void bv050fwm_reset(struct bv050fwm *ctx)
{
    struct mipi_dsi_device *dsi = ctx->dsi;
    struct device *dev = &dsi->dev;
    gpiod_set_value_cansleep(ctx->backlight_gpio, 1);

    gpiod_set_value_cansleep(ctx->reset_gpio, 0);
    usleep_range(1000, 2000);
    gpiod_set_value_cansleep(ctx->reset_gpio, 1);
    usleep_range(5000, 6000);
    gpiod_set_value_cansleep(ctx->reset_gpio, 0);
    usleep_range(10000, 11000);
}

static int bv050fwm_on(struct bv050fwm *ctx)
{
    struct mipi_dsi_device *dsi = ctx->dsi;
    struct device *dev = &dsi->dev;
    int ret;

    dsi->mode_flags |= MIPI_DSI_MODE_LPM;
    dev_info(dev, "bv050fwm_on\n");

mipi_dsi_dcs_write_seq(dsi, 0x11, 0x00);          // SLPOUT
msleep(120);
mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00);          // DISPON

mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x80, 0x00, 0x00);
msleep(10);

mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x80, 0x19, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x80, 0x19);

mipi_dsi_dcs_write_seq(dsi, 0x00, 0xB0);
mipi_dsi_dcs_write_seq(dsi, 0xCA, 0xF0);

mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xFB, 0x00);
msleep(50);
mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00);
mipi_dsi_dcs_write_seq(dsi, 0xFF, 0xFF, 0xFF, 0xFF);

mipi_dsi_dcs_write_seq(dsi, 0x51, 0x80);
mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
mipi_dsi_dcs_write_seq(dsi, 0x5E, 0x28);

    ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
    if (ret < 0) {
        dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
        return ret;
    }
    msleep(120);

    ret = mipi_dsi_dcs_set_display_on(dsi);
    if (ret < 0) {
        dev_err(dev, "Failed to set display on: %d\n", ret);
        return ret;
    }
    msleep(20);

    dev_info(dev, "bv050fwm_on end\n");
  return 0;
}

static int bv050fwm_off(struct bv050fwm *ctx)
{
    struct mipi_dsi_device *dsi = ctx->dsi;
    struct device *dev = &dsi->dev;
    int ret;

    dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;

    ret = mipi_dsi_dcs_set_display_off(dsi);
    if (ret < 0) {
        dev_err(dev, "Failed to set display off: %d\n", ret);
        return ret;
    }
    msleep(20);

    ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
    if (ret < 0) {
        dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
        return ret;
    }
    msleep(120);

    return 0;
}

static int bv050fwm_prepare(struct drm_panel *panel)
{
    struct bv050fwm *ctx = to_bv050fwm(panel);
    struct device *dev = &ctx->dsi->dev;
    int ret;

    if (ctx->prepared)
        return 0;

    // regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
    //                      ctx->supplies);
    // msleep(1000);

    ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
    if (ret < 0) {
        dev_err(dev, "Failed to enable regulators: %d\n", ret);
        return ret;
    }

    bv050fwm_reset(ctx);

    ret = bv050fwm_on(ctx);
    if (ret < 0) {
        dev_err(dev, "Failed to initialize panel: %d\n", ret);
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
        regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
                       ctx->supplies);
        return ret;
    }

    ctx->prepared = true;
    return 0;
}

static int bv050fwm_unprepare(struct drm_panel *panel)
{
    struct bv050fwm *ctx = to_bv050fwm(panel);
    struct device *dev = &ctx->dsi->dev;
    int ret;

    if (!ctx->prepared)
        return 0;

    ret = bv050fwm_off(ctx);
    if (ret < 0)
        dev_err(dev, "Failed to un-initialize panel: %d\n", ret);

    gpiod_set_value_cansleep(ctx->reset_gpio, 0);
    regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);

    ctx->prepared = false;
    return 0;
}

/* Backlight control code */

static int bv050fwm_bl_update_status(struct backlight_device *bl)
{
    struct mipi_dsi_device *dsi = bl_get_data(bl);
    struct device *dev = &bl->dev;
    u8 brightness = backlight_get_brightness(bl) & 0xff;

    //mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00, 0x02, 0x51, 0xEF);
    //mipi_dsi_dcs_write_seq(dsi, 0x51, brightness);
    //mipi_dsi_dcs_write(dsi, 0x51, &brightness, 1);
    mipi_dsi_dcs_set_display_brightness(dsi, brightness);
    dev_info(dev, "boe_bl_update_status: brightness = %u\n", brightness);

    return 0;
}

static int bv050fwm_bl_get_brightness(struct backlight_device *bl)
{
    struct mipi_dsi_device *dsi = bl_get_data(bl);
        struct device *dev = &bl->dev;
    u16 brightness = 0;
    int ret;
    ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
        if (ret < 0) {
             dev_err(&bl->dev, "Failed to get display brightness: %d\n", ret);
             return ret;
        }
        dev_info(&bl->dev, "Read brightness: %u (0x%x)\n", brightness, brightness);
    return brightness & 0xff;
}

static const struct backlight_ops bv050fwm_bl_ops = {
    .update_status = bv050fwm_bl_update_status,
    .get_brightness = bv050fwm_bl_get_brightness,
};

static struct backlight_device *
bv050fwm_create_backlight(struct mipi_dsi_device *dsi)
{
    struct device *dev = &dsi->dev;
    const struct backlight_properties props = {
        .type = BACKLIGHT_RAW,
        .brightness = 255,
        .max_brightness = 255,
    };

    return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
                          &bv050fwm_bl_ops, &props);
}

static const struct drm_display_mode bv050fwm_mode_42hz = {
    .clock = 25200,              // 时钟频率,单位是 kHz
    .hdisplay = 480,              // 水平可视区域
    .hsync_start = 480 + 92,      // 水平同步起始 = hactive + hfront-porch
    .hsync_end = 480 + 92 + 12,   // 水平同步结束 = hsync_start + hsync-len
    .htotal = 480 + 92 + 12 + 88, // 水平总长度 = hactive + hfront + hsync-len + hback-porch
    .vdisplay = 854,              // 垂直可视区域
    .vsync_start = 854 + 18,      // 垂直同步起始 = vactive + vfront-porch
    .vsync_end = 854 + 18 + 4,    // 垂直同步结束 = vsync_start + vsync-len
    .vtotal = 854 + 18 + 4 + 18,  // 垂直总长度 = vactive + vfront-porch + vsync-len + vback-porch
    .width_mm = 62,
    .height_mm = 110,
};

static const struct drm_display_mode bv050fwm_mode_60hz = {
    .clock = 36000,              // 或 36046
    .hdisplay = 480,
    .hsync_start = 480 + 92,
    .hsync_end   = 480 + 92 + 12,
    .htotal      = 480 + 92 + 12 + 88,
    .vdisplay = 854,
    .vsync_start = 854 + 18,
    .vsync_end   = 854 + 18 + 4,
    .vtotal      = 854 + 18 + 4 + 18,
    .width_mm = 62,
    .height_mm = 110,
};

static int bv050fwm_get_modes(struct drm_panel *panel,
                    struct drm_connector *connector)
{
    struct drm_display_mode *mode;

    mode = drm_mode_duplicate(connector->dev, &bv050fwm_mode_42hz);
    if (!mode) {
        dev_err(panel->dev, "failed to add mode\n");
        return -ENOMEM;
    }
    drm_mode_set_name(mode);

    mode->type = DRM_MODE_TYPE_DRIVER;
    connector->display_info.width_mm = mode->width_mm;
    connector->display_info.height_mm = mode->height_mm;
    drm_mode_probed_add(connector, mode);

    mode = drm_mode_duplicate(connector->dev, &bv050fwm_mode_60hz);
    if (!mode) {
        dev_err(panel->dev, "failed to add mode\n");
        return -ENOMEM;
    }
    drm_mode_set_name(mode);

    mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
    connector->display_info.width_mm = mode->width_mm;
    connector->display_info.height_mm = mode->height_mm;
    drm_mode_probed_add(connector, mode);

    return 1;
}

static const struct drm_panel_funcs bv050fwm_panel_funcs = {
    .unprepare = bv050fwm_unprepare,
    .prepare = bv050fwm_prepare,
    .get_modes = bv050fwm_get_modes,
};

static int bv050fwm_probe(struct mipi_dsi_device *dsi)
{
    struct device *dev = &dsi->dev;
    struct bv050fwm *ctx;
    int ret;

// dev_info(dev, "bv050fwm module compiled on: %s %s\n", __DATE__, __TIME__);

    ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
    if (!ctx)
        return -ENOMEM;

    ctx->supplies[0].supply = "power";

    ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
                      ctx->supplies);
    if (ret < 0) {
        dev_err(dev, "Failed to get regulators: %d\n", ret);
        return ret;
    }

    ctx->vci_gpio = devm_gpiod_get(dev, "vci", GPIOD_OUT_HIGH);
    if (IS_ERR(ctx->vci_gpio)) {
        ret = PTR_ERR(ctx->vci_gpio);
        dev_err(dev, "Failed to get vci-gpios: %d\n", ret);
        return ret;
    }
    gpiod_set_value_cansleep(ctx->vci_gpio, 1);

    ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
    if (IS_ERR(ctx->reset_gpio)) {
        ret = PTR_ERR(ctx->reset_gpio);
        dev_err(dev, "Failed to get reset-gpios: %d\n", ret);
        return ret;
    }

    ctx->backlight_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_HIGH);
    if (IS_ERR(ctx->backlight_gpio)) {
        ret = PTR_ERR(ctx->backlight_gpio);
        dev_err(dev, "Failed to get backlight-gpios: %d\n", ret);
        return ret;
    }

    ctx->dsi = dsi;
    mipi_dsi_set_drvdata(dsi, ctx);

    dsi->lanes = 2;
    dsi->format = MIPI_DSI_FMT_RGB888;
    dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM;

    drm_panel_init(&ctx->panel, dev, &bv050fwm_panel_funcs,
               DRM_MODE_CONNECTOR_DSI);

    dev_info(dev, "drm_panel_init ok\n");

    ctx->panel.prepare_prev_first = true;

    ret = drm_panel_of_backlight(&ctx->panel);
    if (ret)
    {
        dev_err(dev, "Failed to set backlight: %d\n", ret);
        return ret;
    }
    // 使用mipi dcs调光
    ctx->panel.backlight = bv050fwm_create_backlight(dsi);
    if (IS_ERR(ctx->panel.backlight))
        return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
                     "Failed to create backlight\n");

    drm_panel_add(&ctx->panel);
    dev_info(dev, "drm_panel_add ok\n");

    ret = mipi_dsi_attach(dsi);
    if (ret < 0) {
        dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
        drm_panel_remove(&ctx->panel);
        return ret;
    }
    dev_info(dev, "mipi_dsi_attach ok\n");

    return 0;
}

static void bv050fwm_remove(struct mipi_dsi_device *dsi)
{
    struct bv050fwm *ctx = mipi_dsi_get_drvdata(dsi);
    int ret;

    ret = mipi_dsi_detach(dsi);
    if (ret < 0)
        dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);

    drm_panel_remove(&ctx->panel);
}

static const struct of_device_id bv050fwm_of_match[] = {
    { .compatible = "boe,bv050fwm" },
    { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, bv050fwm_of_match);

static struct mipi_dsi_driver bv050fwm_driver = {
    .probe = bv050fwm_probe,
    .remove = bv050fwm_remove,
    .driver = {
        .name = "panel-boe-bv050fwm",
        .of_match_table = bv050fwm_of_match,
    },
};
module_mipi_dsi_driver(bv050fwm_driver);

MODULE_DESCRIPTION("MIPI-DSI based Panel Driver for bv050fwm LCD Display Module");
MODULE_LICENSE("GPL");

编写Makefile文件:
touch Makefile

KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build

obj-m := panel-boe-bv050fwm.o

all:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules

clean:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean

开始编译driver:

make

将驱动放到对应目录,并更新驱动模块依赖关系:

cp panel-boe-bv050fwm.ko /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/panel/
depmod -a
update-initramfs -u -c -k $(uname -r)
  1. 关于驱动部分,我修改了60hz时序的问题, 其hback-porch 部分不太正确,导致我屏幕默认图形化显示使用60hz一直黑屏显示。
  2. 关于驱动的初始化部分,寄存器命令也进行了缩减,只保留必要部分。pwm调光部分也进行了解决,我发现其默认的pwm频率为  6.7khz,而  通过 https://github.com/HUAWEI-Y550-Y635/android_kernel_huawei_msm8916/blob/02eea41e4291a3b71c2bc574bae83906ebcf21ca/arch/arm/boot/dts/qcom/huawei_y635_l21_va/hw-panel-boe-otm8019a-5p0-fwvga-video.dtsi#L19
    初始化后会变为 28khz。

其对与 屏幕驱动板的 AP3019AKTR 芯片来说 超过3khz的pwm会有异常: 亮度调节回由特别暗变为特别亮,怀疑是电路中的寄生电容导致的高频pwm有影响(尝试加入上拉电阻无效),中间无过度值。所有我花费很长时间去研究如何修改PWM频率,而数据手册OTM8019A 提供的PWM 5个参数对此无效。
无奈我采用二分法进行查找发现(每次都需要更新内核模块并重启、很费时间,因为rmmod内核模块会导致崩溃这个是更复杂的一个问题了):

mipi_dsi_dcs_write_seq(dsi, 0x00, 0xB0);
mipi_dsi_dcs_write_seq(dsi, 0xCA, 0xF0);

可以调节频率,看数据手册好像是CABC对应的阈值,懒得研究了,调试了整整二天一宿,其对应的频率为:255/ 0xF0 = 1.36 KHz
通过这个寄存器设置降低了PWM的频率可以实现完美调光了。

echo 100 > /sys/class/backlight/3f700000.dsi.0/brightness #亮度值为9-250(dts定义的)

注:此pwm为屏幕芯片内部产生无需连接树莓派GPIO, 跳线帽短接 BL_PWM 和 LCD_BL_PWM

3.3 配置config.txt cmdline.txt

vi /boot/firmware/config.txt
加入

dtparam=i2c_vc=on
dtoverlay=vc4-kms-v3d
#disable_fw_kms_setup=1
enable_uart=1
dtoverlay=panel_boe_bv050fwm
display_default_lcd=1 
display_auto_detect=0
drm.debug=0x1e
dtdebug=1 #开启设备树调试信息
gpu_mem=256

# 下面这几项为了解决冷重启 图片跃出屏幕问题
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=87
hdmi_cvt=480 854 60 3 0 0 0

vi /boot/firmware/cmdline.txt
加入

rd.driver.pre=panel-boe-bv050fwm,gpio-pca953x,i2c-bcm2835 fbcon=map:0

4. 一些调试指令记录

cat /proc/device-tree/chosen/user-warnings # 设备树错误日志与dtdebug配合使用
modetest -M vc4 -s 42:480,572,584,672,854,872,876,894-42 -v #modetest指定时序测试屏幕
sudo dd if=/dev/urandom of=/dev/fb0 bs=1024 count=10 #随机灌入fb0, 测试framebuff
echo 0 > /sys/class/graphics/fbcon/cursor_blink #纯文本终端禁用光标闪烁
modetest -M vc4|grep 480x854 #查看屏幕提供的mode, 以及默认使用的mode
lsinitramfs /boot/initrd.img-$(uname -r)  #查看initramfs 包含的内核模块

免费评分

参与人数 3吾爱币 +1 热心值 +3 收起 理由
lzk1 + 1 我很赞同!
skyward + 1 + 1 我很赞同!
yxzzz666 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
Clarence210 发表于 2026-3-2 20:57
可以开一个嵌入式专栏乐
3#
renpeng009 发表于 2026-3-2 21:47
4#
skyward 发表于 2026-3-3 10:56
佬,有屏幕的链接吗,按型号没搜到,3B 4B通用吗,买的树莓派跑完docker就吃灰了
5#
skyward 发表于 2026-3-3 11:08
找到了,京东方的BV050FWM
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-3-4 17:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表