[ROC-RK3568-PC] [Firefly-Android] 10min带你了解LCD的使用
- 🍇 博主主页: 【Systemcall小酒屋】
- 🍇 博主追寻:热衷于用简单的案例讲述复杂的技术,“假传万卷书,真传一案例”,这是林群院士说过的一句话,另外“成就是最好的老师”,技术既要沉淀,也得分享,成就感的正反馈是支持我持续耕耘的动力!
- 🍇 专栏目录: 【Firefly-RK356x板卡】
- 🍇 专栏说明:基于Firefly旗下的RK356x板卡进行入门篇讲述,欢迎订阅,博主会持续更新!
文章目录
- 一、内核Config配置
- 二、MIPI配置
- 2.1 引脚配置
- 2.2 背光配置
- 2.3 显示时序配置
- 2.3.1 Power on/off sequence
- 2.3.2 Display-Timings
- 三、EDP配置
- 3.1 引脚配置
- 3.2 EDP背光配置
一、内核Config配置
ROC-RK3568-PC的SDK下kernel/arch/arm64/configs/firefly_defconfig
已经把LCD相关的配置好:
CONFIG_DRM_ROCKCHIP=y
CONFIG_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_DRM_PANEL_SIMPLE=y
二、MIPI配置
ROC-RK3568-PC的SDK有MIPI DSI的DTS文件: kernel/arch/arm64/boot/dts/rockchip/rk3568-firefly-roc-pc-mipi101_M101014_BE45_A1.dts
,此DTS文件为MIPI_DSI0+HDMI屏配置,MIPI_DSI1 默认关闭。
2.1 引脚配置
从DTS文件中可以看到以下语句:
#include "rk3568-firefly-roc-pc.dtsi"/ {model = "ROC-RK3568-PC MIPI M101014_BE45_A1 + HDMI(Android)";compatible = "rockchip,rk3568-firefly-roc-pc-mipi", "rockchip,rk3568";...
}&route_dsi0 {status = "okay";logo,rotation = "logo_rotation_270"; //support rotation 90,180,270connect = <&vp1_out_dsi0>;
};&video_phy0 {status = "okay";
};&dsi0_in_vp0 {status = "disabled";
};&dsi0_in_vp1 {status = "okay";
};/** mipi_dphy0 needs to be enabled* when dsi0 is enabled*/
&dsi0 {status = "okay";//rockchip,lane-rate = <1000>;dsi0_panel: panel@0 {status = "okay";compatible = "simple-panel-dsi";reg = <0>;backlight = <&backlight>;enable-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;reset-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>;enable-delay-ms = <35>;prepare-delay-ms = <6>;reset-delay-ms = <25>;init-delay-ms = <55>;unprepare-delay-ms = <0>;disable-delay-ms = <20>;mipi-data-delay-ms = <200>;...panel-init-sequence = [//39 00 04 B9 83 10 2E// 15 00 02 CF FF05 78 01 1105 32 01 29//15 00 02 35 00];panel-exit-sequence = [05 00 01 2805 00 01 10];...};
};
...
&route_hdmi {status = "okay";connect = <&vp0_out_hdmi>;
};&hdmi {status = "okay";
};&hdmi_in_vp0 {status = "okay";
};&hdmi_in_vp1 {status = "disabled";
};
...
这里定义了LCD的控制引脚:
NAME | GPIO | GPIO ACTIVE |
---|---|---|
LCD_EN | GPIO0_C7 | GPIO_ACTIVE_HIGH |
LCD_RST | GPIO3_B5 | GPIO_ACTIVE_LOW |
在硬件信号上 LCD_EN
引脚高电平有效,而 LCD_RST
引脚是低电平有效。
2.2 背光配置
在DTS文件中配置了背光信息,如下:
backlight: backlight {status = "okay";compatible = "pwm-backlight";enable-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;pwms = <&pwm4 0 50000 1>;brightness-levels = <60 60 60 61 61 61 62 6262 63 63 63 64 64 64 6565 65 66 66 66 67 67 6768 68 68 69 69 69 70 7070 71 71 71 72 72 72 7373 73 74 74 74 75 75 7576 76 76 77 77 77 78 7878 79 79 79 80 80 80 8181 81 82 82 82 83 83 8384 84 84 85 85 85 86 8686 87 87 87 88 88 88 8989 89 90 91 92 93 94 9596 97 98 99 100 101 102 103104 105 106 107 108 109 110 111112 113 114 115 116 117 118 119120 121 122 123 124 125 126 127128 129 130 131 132 133 134 135136 137 138 139 140 141 142 143144 145 146 147 148 149 150 151152 153 154 155 156 157 158 159160 161 162 163 164 165 166 167168 169 170 171 172 173 174 175176 177 178 179 180 181 182 183184 185 186 187 188 189 190 191192 193 194 195 196 197 198 199200 201 202 203 204 205 206 207208 209 210 211 212 213 214 215216 217 218 219 220 221 222 223224 225 226 227 228 229 230 231232 233 234 235 236 237 238 239240 241 242 243 244 245 246 247248 249 250 251 252 253 254 255>;default-brightness-level = <200>;};
-
enable-gpios:背光使能脚,高电平有效。
-
pwms属性:配置PWM,范例里面默认使用pwm4,50000ns是周期(20 KHz),pwm为负极性。
-
brightness-levels属性:配置背光亮度数组,一般以值 255 为一个 scale,当 PWM 设置为正极性时,从 0~255 表示背光为正极,占空比从 0%~100% 变化,255~0 为负极性,占空比从 100%~0% 变化;当 PWM 设置为负极性时,反之。
-
default-brightness-level属性:开机时默认背光亮度,范围为0-255。
具体可参考kernel中的说明文档:kernel/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
2.3 显示时序配置
2.3.1 Power on/off sequence
MIPI屏的上下电时序通常都在规格书的Power on/off sequence章节中,可根据规格书的上下电时序修改dts,panel节点中有如下属性:
&dsi0 {status = "okay";//rockchip,lane-rate = <1000>;dsi0_panel: panel@0 {status = "okay";compatible = "simple-panel-dsi";...enable-delay-ms = <35>;prepare-delay-ms = <6>;reset-delay-ms = <25>;init-delay-ms = <55>;unprepare-delay-ms = <0>;disable-delay-ms = <20>;mipi-data-delay-ms = <200>;...};
};
mipi-data-delay-ms
为Firefly 10.1寸 M101014-BE45-A1 MIPI屏所需时序,调试屏幕时可根据本身上下电时序是否需要再配置此属性。MIPI上下电后需要发送初始化或退出指令才能使之正常工作,初始化和退出指令列表可以参考kernel/arch/arm64/boot/dts/rockchip/rk3568-firefly-roc-pc-mipi101_CZNB101862T.dts
,列表如下:
&dsi0 {status = "okay";//rockchip,lane-rate = <1000>;dsi0_panel: panel@0 {...panel-init-sequence = [15 00 02 E0 0015 00 02 E1 9315 00 02 E2 6515 00 02 E3 F815 00 02 E0 0415 00 02 2D 03 15 00 02 E0 0015 00 02 80 03 //15 00 02 4A 35 15 00 02 E0 0115 00 02 00 00 15 00 02 E0 0115 00 02 4B 04//15 00 02 4A 35 15 00 02 00 0015 00 02 01 66//15 00 02 03 00 //15 00 02 04 6D15 00 02 17 00 15 00 02 18 AF15 00 02 19 01...];panel-exit-sequence = [05 05 01 2805 78 01 10];};
};
dts中的init-sequence
和panel-exit-sequence
,只是配置了上电和下电指令, 其他的初始化指令已经烧录在M101014-BE45-A1这款MIPI屏的IC里,dts无需配置。接下来来看看上下电时序在驱动中的实现, 具体实现在kernel/drivers/gpu/drm/panel/panel-simple.c
中:
static int panel_simple_disable(struct drm_panel *panel)
{...if (p->backlight) {p->backlight->props.power = FB_BLANK_POWERDOWN;p->backlight->props.state |= BL_CORE_FBBLANK;backlight_update_status(p->backlight);}if (p->desc->delay.disable)panel_simple_sleep(p->desc->delay.disable);if (p->cmd_type == CMD_TYPE_MCU) {err = panel_simple_xfer_mcu_cmd_seq(p, p->desc->exit_seq);if (err)dev_err(panel->dev, "failed to send exit cmds seq\n");}...
}static int panel_simple_unprepare(struct drm_panel *panel)
{...if (p->desc->exit_seq) {if (p->dsi)panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq);else if (p->cmd_type == CMD_TYPE_SPI)err = panel_simple_xfer_spi_cmd_seq(p, p->desc->exit_seq);if (err)dev_err(panel->dev, "failed to send exit cmds seq\n");}gpiod_direction_output(p->reset_gpio, 1);if(!p->enable_on_always){gpiod_direction_output(p->enable_gpio, 0);}...
}static int panel_simple_prepare(struct drm_panel *panel)
{...gpiod_direction_output(p->enable_gpio, 1);if (p->desc->delay.prepare)panel_simple_sleep(p->desc->delay.prepare);...gpiod_direction_output(p->reset_gpio, 1);if (p->desc->delay.reset)panel_simple_sleep(p->desc->delay.reset);gpiod_direction_output(p->reset_gpio, 0); //由于驱动在控制reset脚时序的时候使用了`gpiod`这类的API//如果在DTS配置了低电平有效,那么这里就会将reset引脚拉高,即取反。if (p->desc->delay.init)panel_simple_sleep(p->desc->delay.init);if (p->desc->init_seq) {if (p->dsi)panel_simple_xfer_dsi_cmd_seq(p, p->desc->init_seq);else if (p->cmd_type == CMD_TYPE_SPI)err = panel_simple_xfer_spi_cmd_seq(p, p->desc->init_seq);if (err)dev_err(panel->dev, "failed to send init cmds seq\n");}if(p->desc->delay.mipi_data){panel_simple_sleep(p->desc->delay.mipi_data);}...
}static int panel_simple_enable(struct drm_panel *panel)
{...if (p->cmd_type == CMD_TYPE_MCU) {err = panel_simple_xfer_mcu_cmd_seq(p, p->desc->init_seq);if (err)dev_err(panel->dev, "failed to send init cmds seq\n");}if (p->desc->delay.enable)panel_simple_sleep(p->desc->delay.enable);if (p->backlight) {p->backlight->props.state &= ~BL_CORE_FBBLANK;p->backlight->props.power = FB_BLANK_UNBLANK;backlight_update_status(p->backlight);}...
}
2.3.2 Display-Timings
display_timings在dts中定义:
disp_timings0: display-timings {native-mode = <&dsi0_timing0>;dsi0_timing0: timing0 {clock-frequency = <72600000>;//<80000000>;hactive = <800>;//<768>;vactive = <1280>;hsync-len = <14>; //20, 50,10hback-porch = <26>; //50, 56,10hfront-porch = <32>;//50, 30,180vsync-len = <8>;//4vback-porch = <20>;//4vfront-porch = <80>;//8hsync-active = <0>;vsync-active = <0>;de-active = <0>;pixelclk-active = <0>;};};
相关的参数一般可以在屏的规格书中找到,然后在kernel/drivers/gpu/drm/panel/panel-simple.c
的panel_simple_probe
中初始化了获取时序的函数。
static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
{...panel->base.funcs = &panel_simple_funcs;...
}
...
static const struct drm_panel_funcs panel_simple_funcs = {.loader_protect = panel_simple_loader_protect,.disable = panel_simple_disable,.unprepare = panel_simple_unprepare,.prepare = panel_simple_prepare,.enable = panel_simple_enable,.get_modes = panel_simple_get_modes,.get_timings = panel_simple_get_timings,
};
...
该函数在kernel/drivers/gpu/drm/panel/panel-simple.c
中定义:
static int panel_simple_get_timings(struct drm_panel *panel, unsigned int num_timings, struct display_timing *timings)
{struct panel_simple *p = to_panel_simple(panel);unsigned int i;if (p->desc->num_timings < num_timings)num_timings = p->desc->num_timings;if (timings)for (i = 0; i < num_timings; i++)timings[i] = p->desc->timings[i];return p->desc->num_timings;
}
三、EDP配置
3.1 引脚配置
ROC-RK3568-PC的SDK有EDP的DTS文件:kernel/arch/arm64/boot/dts/rockchip/rk3568-firefly-roc-pc-edp_M156X40.dts
,从该文件中我们可以看到以下语句:
edp_panel: edp-panel {compatible = "simple-panel";status = "okay";power-supply = <&vcc3v3_lcd_edp>;enable-gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;//bus-format = <MEDIA_BUS_FMT_RBG888_1X24>; backlight = <&backlight>;...ports {panel_in_edp: endpoint {remote-endpoint = <&edp_out_panel>;};};};...
};&edp {status = "okay";hpd-gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;force-hpd;ports {edp_out: port@1 {reg = <1>;#address-cells = <1>;#size-cells = <0>;edp_out_panel: endpoint@0 {reg = <0>;remote-endpoint = <&panel_in_edp>;};};};
};
这里定义了LCD的电源控制引脚:
NAME | GPIO | GPIO_ACTIVE |
---|---|---|
BL_EN | GPIO3_C3 | GPIO_ACTIVE_HIGH |
EDP_HPD | GPIO0_C2 | GPIO_ACTIVE_HIGH |
3.2 EDP背光配置
因为背光接口是公用的,所以可以参考上述MIPI的配置方法。
4.3.3. EDP显示时序配置
不同于MIPI屏,EDP屏对上下电时序没有那么高的要求,当然还是要看调试屏幕的上下电时序图来配置:
edp_panel: edp-panel {compatible = "simple-panel";status = "okay";...display-timings {native-mode = <&timing0>; timing0: timing0 {clock-frequency = <140000000>;hactive = <1920>;vactive = <1080>;hfront-porch = <40>;hsync-len = <40>;hback-porch = <80>;vfront-porch = <16>;vsync-len = <8>;vback-porch = <16>;hsync-active = <0>;vsync-active = <0>;de-active = <0>;pixelclk-active = <0>;};};...};
display-timings同样在kernel/drivers/gpu/drm/panel/panel-simple.c
中使用到:
static int panel_simple_get_timings(struct drm_panel *panel, unsigned int num_timings, struct display_timing *timings)
{struct panel_simple *p = to_panel_simple(panel);unsigned int i;if (p->desc->num_timings < num_timings)num_timings = p->desc->num_timings;if (timings)for (i = 0; i < num_timings; i++)timings[i] = p->desc->timings[i];return p->desc->num_timings;
}
相关文章:

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解LCD的使用
🍇 博主主页: 【Systemcall小酒屋】🍇 博主追寻:热衷于用简单的案例讲述复杂的技术,“假传万卷书,真传一案例”,这是林群院士说过的一句话,另外“成就是最好的老师”,技术…...

【redis】redis分布式锁
目录一、为什么需要分布式锁二、分布式锁的实现方案三、redis分布式锁3.1 简单实现3.2 成熟的实现一、为什么需要分布式锁 1.在java单机服务中,jvm内部有一个全局的锁监视器,只有一个线程能获取到锁,可以实现线程之间的互斥 2.当有多个java服…...

UEditorPlus v3.0.0 接口请求头参数,插入换行优化,若干问题优化
UEditor是由百度开发的所见即所得的开源富文本编辑器,基于MIT开源协议,该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器,主要做了样式的定制,更符…...

LabVIEW 2015介绍
这里写目录标题LabVIEW 2015安装包LabVIEW 2020安装包Labview2015安装过程1、LabVIEW 2015 的介绍2、LabVIEW 2015 的特点3、LabVIEW 2015 的功能4、LabVIEW 2015 快捷键LabVIEW 2015安装包 链接:https://pan.baidu.com/s/1I1cxtbBkmJbHvDTc5JnOyQ 提取码࿱…...

大一被忽悠进了培训班
大家好,我是帅地。 最近我的知识星球开始营业,不少大一大二的小伙伴也是纷纷加入了星球,并且咨询的问题也是五花八门,反正就是,各种迷茫,其中有一个学弟,才大一,就报考培训班&#…...

编写一个存储过程,输入一个日期,判定其距离年底还有多少天
--编写一个存储过程,输入一个日期,判定其距离年底还有多少天 create or replace procedure sp_end(i_date varchar2,o_end out varchar2) is --声明两个变量,v_end存放经过转化的年底日期,v_errm用来存放异常 v_end date; v_errm…...

HTB-Inject
HTB-Inject信息收集开机root信息收集 228080 8080端口如下。 主界面有一个上传图片的功能。 简单测试后发现对上传文件后缀名应该有过滤,只允许jpg后缀名文件上传。将一个内容为”test“的txt文件修改后缀为jpg后上传会出现错误。 验证一下是否存在LFI。 验证一…...

java基础知识——13.类与对象
这篇文章,我们来介绍java中的类与对象 目录 1.面向对象的介绍 2.类的设计与使用 2.1 类和对象 2.1.1 如何定义类 2.2 类的注意事项 3.封装 3.1 private关键字 4.this关键字 5.构造方法 6.标准JavaBean 7.对象内存图 8.成员变量与局部变量 1.面向对象的…...

北邮22信通:(10)第三章 3.2栈的实现
北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章: 北邮22信通:(9)实验1 题目六:模拟内存管理(搬运官方代码)_青…...

Vue3之使用js实现动画
概述 动画的实现其实不仅可以使用CSS的方式实现,而且还可以使用js的方式实现,二者有啥区别呢?CSS更加注重动画的展现,性能更好,而js的方式性能稍微差点,但是可以在动画执行的每一个过程中做些额外的操作。…...

金三银四,你准备好面试了吗? (附30w字软件测试面试题总结)
不知不觉,已是3月下旬。最近有很多小伙伴都在跟我谈论春招面试的问题,其实对于面试,我也没有太多的经验,只能默默地把之前整理的软件测试面试题分享给Ta。今天就来大致的梳理一下软件测试的面试体系(每一部分最后都有相…...

【C语言学习】数组
数组(Array)就是一些列具有相同类型的数据的集合,这些数据在内存中依次挨着存放,彼此之间没有缝隙。 数组不是C语言的专利,Java、C、C#、JavaScript、PHP 等其他编程语言也有数组。 C语言数组属于构造数据类型。一个…...

ElasticSearch序列 - SpringBoot整合ES:根据指定的 ids 查询
文章目录1. ElasticSearch 根据 ids 查询文档2. SpringBoot整合ES实现 ids 查询1. ElasticSearch 根据 ids 查询文档 ① 索引文档,构造数据 PUT /my_index/_doc/1 {"price":10 }PUT /my_index/_doc/2 {"price":20 }PUT /my_index/_doc/3 {&qu…...

Spark SQL实战(08)-整合Hive
1 整合原理及使用 Apache Spark 是一个快速、可扩展的分布式计算引擎,而 Hive 则是一个数据仓库工具,它提供了数据存储和查询功能。在 Spark 中使用 Hive 可以提高数据处理和查询的效率。 场景 历史原因积累下来的,很多数据原先是采用Hive…...

堆(数据结构系列11)
目录 前言: 1.优先级队列概念 2.堆的概念 3.堆的存储方式 4.堆的创建 5.创建堆的时间复杂度 6.堆的插入和删除 6.1堆的插入 6.2堆的删除 结束语: 前言: 上一次博客中小编主要与大家分享了 二叉树一些相关的知识点和一些练习题&…...

算法训练第四十二天|01背包问题 二维 、01背包问题 一维、416. 分割等和子集
动态规划part0401背包问题 二维01 背包二维dp数组01背包完整c测试代码总结01背包问题 一维一维dp数组(滚动数组)一维dp01背包完整C测试代码416. 分割等和子集题目描述思路01背包问题总结01背包问题 二维 视频链接:https://www.bilibili.com/…...

Java-如何使用Java将图片和文字拼接在一起(并非是给图片加水印)
之前有遇到一个问题 问题背景:项目中,有一个功能,管理端可以将客户创建的小程序码下载到本地,方便客户将对应门店的小程序码打印出来并张贴到门店,做门店的引流和会员入会。 具体问题:当小程序码的数量较少…...

Metasploit入门到高级【第三章】
来自公粽号:Kali与编程预计更新第一章:Metasploit 简介 Metasploit 是什么Metasploit 的历史和发展Metasploit 的组成部分 第二章:Kali Linux 入门 Kali Linux 简介Kali Linux 安装和配置常用命令和工具介绍 第三章:Metasploi…...

枚举的使用
Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。1 问题如何在类中使用枚举,例如枚举出一年的四个季度,并且通过迭代枚举…...

Python进阶语法
1.1 Python进阶语法 1.1.1 交换变量 一行代码快速交换两个变量,无需创建临时变量。 from icecream import ica 2 b 4 a, b b, a ic(a, b)ic| a: 4, b: 2 1.1.2 链式比较 from icecream import ica 97 if 90 < a < 100:ic(a)ic| a: 97 1.1.3 初始化列表…...

Pyspark_结构化流4
Pyspark 注:大家觉得博客好的话,别忘了点赞收藏呀,本人每周都会更新关于人工智能和大数据相关的内容,内容多为原创,Python Java Scala SQL 代码,CV NLP 推荐系统等,Spark Flink Kafka Hbase Hi…...

Linux cmp 命令
Linux cmp 命令用于比较两个文件是否有差异。 当相互比较的两个文件完全一样时,则该指令不会显示任何信息。若发现有所差异,预设会标示出第一个不同之处的字符和列数编号。若不指定任何文件名称或是所给予的文件名为"-",则cmp指令…...

Python入门到高级【第五章】
预计更新第一章. Python 简介 Python 简介和历史Python 特点和优势安装 Python 第二章. 变量和数据类型 变量和标识符基本数据类型:数字、字符串、布尔值等字符串操作列表、元组和字典 第三章. 控制语句和函数 分支结构:if/else 语句循环结构&#…...

C语言中(i++)+ (i++)真的每次都等于3吗?
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言结论证明首先,登场的是我们的VC6.0(还有Linux)最后一位,我使用了小熊猫C(还有Clion)请添加…...

Cursor,程序员的 AI 代码编辑助手
相信大家都或多或少地听说过、了解过 chatGPT ,半个月前发布的 GPT-4 ,可谓是 AI 赛道上的一个王炸 那么今天咸鱼给大家分享一个开源的 AI 代码编辑器——Cursor,让各位程序员在编程之路上一骑绝尘 😃 介绍 Cursor 是一个人工智…...

基于XML的自动装配~
基于XML的自动装配之场景模拟: 自动装配:根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或者接口类型赋值 之前我们学过的依赖注入,我们在为不同属性赋值时,例如类类型的属性…...

完全二叉树的4种遍历方式
一张二叉树的图 1,二叉树的特点 每个点p的左儿子是p*2,右儿子是p*21,可以分别表示为p<<1与p<<1|1节点的序号是从左到右,从上到下增加的每个点至多2个儿子(屁话(bushi)) 2ÿ…...

【vue2】使用elementUI进行表单验证实操(附源码)
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:vue使用elementUI进行表单验证实操(附源码) 【前言】我们在构建一…...

JUC之阻塞队列解读(BlockingQueue)
目录 BlockingQueue 简介 BlockingQueue 核心方法 1.放入数据 2.获取数据 入门代码案例 常见的 BlockingQueue ArrayBlockingQueue(常用) LinkedBlockingQueue(常用) PriorityBlockingQueue SynchronousQueue LinkedTransferQueue LinkedBlockingDeque 小结 Bloc…...

LCHub:ChatGPT4和低代码来临,程序员面临下岗?
一个网友吐槽道: “ 建站出来了,你们说程序员会失业。 低代码出来了,你们说程序员会失业。 Copilot出来了,你们说程序员会失业。 Chatgpt出来了,你们说程序员会失业 虽然这只是网友的吐槽,但却引起了小编的好奇。为何程序员那么容易被新技术取代?今天小编打算跟大家…...