友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕
屏幕介绍
本文以中景园
1.69
寸LCD
,驱动芯片ST7789V2
该款屏幕示例,屏幕的分辨率为240*280
屏幕引脚说明
NanoPi NEO IO介绍
屏幕与板子的IO连接关系
屏幕 | NanoPi NEO |
---|---|
GND | GND |
VCC | 3.3V |
SCL | PC2 |
SDA | PC0 |
RES | PG11 |
DC | PA1 |
CS | PC3 |
BLK | PA0 |
下载交叉编译器和linux内核源码并按教程配置好开发环境
参考友善官方链接:Building U-boot and Linux for H5/H3/H2+/zh
修改设备树
需要修改的设备树文件路径:
linux/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
找到其中spi0节点,修改为如下:
&spi0 {/* needed to avoid dtc warning */#address-cells = <1>;#size-cells = <0>;status = "okay";pinctrl-names = "default";pinctrl-0 = <&spi0_pins &spi0_cs_pins>;cs-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>, <&pio 0 6 GPIO_ACTIVE_HIGH>;spidev0: spi@0 {compatible = "nanopi,spidev";reg = <0>;status = "disabled";spi-max-frequency = <10000000>;};spiflash: spiflash@0 {#address-cells = <1>;#size-cells = <1>;compatible = "mxicy,mx25l12805d";reg = <0>;status = "disabled";spi-max-frequency = <50000000>;mode = <0>;partition@0 {reg = <0x0 0x1000000>;label = "spi-flash";};};pitft: pitft@0{compatible = "sitronix,st7789v";reg = <0>;status = "okay"; /* 使能 */spi-max-frequency = <96000000>; /* 修改了默认速度 */rotate = <90>;/* 初始默认旋转了90度 横屏 */fps = <33>;buswidth = <8>;dc-gpios = <&pio 0 1 GPIO_ACTIVE_HIGH>; /* PA1 */reset-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */led-gpios = <&pio 0 0 GPIO_ACTIVE_LOW>; /* PA0 */debug = <0x0>;};pitft_ts: pitft-ts@1 {compatible = "ti,ads7846";reg = <1>;status = "disabled";spi-max-frequency = <2000000>;interrupt-parent = <&pio>;interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* PG9 / EINT9 */pendown-gpio = <&pio 6 9 GPIO_ACTIVE_LOW>;ti,swap-xy;ti,vref-delay-usecs = <1000>;ti,x-min = /bits/ 16 <100>;ti,x-max = /bits/ 16 <0xfff>;ti,y-min = /bits/ 16 <100>;ti,y-max = /bits/ 16 <0xfff>;ti,vref-mv = <3300>;ti,x-plate-ohms = /bits/ 16 <256>;ti,penirq-recheck-delay-usecs = <10>;ti,settle-delay-usec = /bits/ 16 <100>;ti,keep-vref-on = <1>;ti,pressure-max = /bits/ 16 <0xfff>;ti,debounce-max = <10>;ti,debounce-tol = <30>;ti,debounce-rep = <1>;};
};
找到pio节点,添加屏幕其它控制引脚的io
&pio {leds_npi: led_pins {pins = "PA10";function = "gpio_out";};lcd_reset_pins: lcd_reset_pins {pins = "PG11";function = "gpio_out";};lcd_dc_pins: lcd_dc_pins {pins = "PA1";function = "gpio_out";};lcd_led_pins: lcd_led_pins {pins = "PA0";function = "gpio_out";};spi0_cs_pins: spi0_cs_pins {pins = "PC3", "PA6";function = "gpio_out";};
};
禁用hdmi音频视频输出,否则屏幕不显示
&hdmi {#status = "okay";status = "disabled";
};&hdmi_out {hdmi_out_con: endpoint {remote-endpoint = <&hdmi_con_in>;};
};&sound_hdmi {#status = "okay";status = "disabled";
};
修改驱动文件
linux/drivers/staging/fbtft/
路径下,找到fb_st7789v.c
,根据自己屏幕情况修改相关参数本人移植时,出现屏幕颜色不对,坐标偏移等情况,根据中景园提供的驱动程序对该文件进行了一定修改,本人用途屏幕旋转90度横屏使用,只做了横屏坐标校准,其它旋转角度下坐标不准只需要修改set_addr_win
函数内的坐标偏移即可,至此代码修改内容全部完成
/** FB driver for the ST7789V LCD Controller** Copyright (C) 2015 Dennis Menschel** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.*/#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <video/mipi_display.h>
#include <linux/gpio.h>#include "fbtft.h"#define DRVNAME "fb_st7789v"#define DEFAULT_GAMMA \"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25\n" \"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25"/*** enum st7789v_command - ST7789V display controller commands** @PORCTRL: porch setting* @GCTRL: gate control* @VCOMS: VCOM setting* @VDVVRHEN: VDV and VRH command enable* @VRHS: VRH set* @VDVS: VDV set* @VCMOFSET: VCOM offset set* @PWCTRL1: power control 1* @PVGAMCTRL: positive voltage gamma control* @NVGAMCTRL: negative voltage gamma control** The command names are the same as those found in the datasheet to ease* looking up their semantics and usage.** Note that the ST7789V display controller offers quite a few more commands* which have been omitted from this list as they are not used at the moment.* Furthermore, commands that are compliant with the MIPI DCS have been left* out as well to avoid duplicate entries.*/
enum st7789v_command {PORCTRL = 0xB2,GCTRL = 0xB7,VCOMS = 0xBB,VDVVRHEN = 0xC2,VRHS = 0xC3,VDVS = 0xC4,VCMOFSET = 0xC5,PWCTRL1 = 0xD0,PVGAMCTRL = 0xE0,NVGAMCTRL = 0xE1,
};#define MADCTL_BGR BIT(3) /* bitmask for RGB/BGR order */
#define MADCTL_MV BIT(5) /* bitmask for page/column order */
#define MADCTL_MX BIT(6) /* bitmask for column address order */
#define MADCTL_MY BIT(7) /* bitmask for page address order *//*** init_display() - initialize the display controller** @par: FBTFT parameter object** Most of the commands in this init function set their parameters to the* same default values which are already in place after the display has been* powered up. (The main exception to this rule is the pixel format which* would default to 18 instead of 16 bit per pixel.)* Nonetheless, this sequence can be used as a template for concrete* displays which usually need some adjustments.** Return: 0 on success, < 0 if error occurred.*/
static int init_display(struct fbtft_par *par)
{/* turn off sleep mode */write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);mdelay(120);
#if 0/* set pixel format to RGB-565 */write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);/** VGH = 13.26V* VGL = -10.43V*/write_reg(par, GCTRL, 0x35);/** VDV and VRH register values come from command write* (instead of NVM)*/write_reg(par, VDVVRHEN, 0x01, 0xFF);/** VAP = 4.1V + (VCOM + VCOM offset + 0.5 * VDV)* VAN = -4.1V + (VCOM + VCOM offset + 0.5 * VDV)*/write_reg(par, VRHS, 0x0B);/* VDV = 0V */write_reg(par, VDVS, 0x20);/* VCOM = 0.9V */write_reg(par, VCOMS, 0x20);/* VCOM offset = 0V */write_reg(par, VCMOFSET, 0x20);/** AVDD = 6.8V* AVCL = -4.8V* VDS = 2.3V*/write_reg(par, PWCTRL1, 0xA4, 0xA1);write_reg(par, MIPI_DCS_SET_DISPLAY_ON);#endifwrite_reg(par, 0x3A,0x05);write_reg(par, 0xB2,0x0C,0x0C,0x00,0x33,0x33);write_reg(par, 0xB7,0x35);write_reg(par, 0xBB,0x32); write_reg(par, 0xC2,0x01); write_reg(par, 0xC3,0x15); write_reg(par, 0xC4,0x20);write_reg(par, 0xC6,0x0F);write_reg(par, 0xD0,0xA4,0xA1);write_reg(par,PVGAMCTRL,0xD0,0x08,0x0E,0x09,0x09,0x05,0x31,0x33,0x48,0x17,0x14,0x15,0x31,0x34);write_reg(par,NVGAMCTRL, 0xD0,0x08,0x0E,0x09,0x09,0x15,0x31,0x33,0x48,0x17,0x14,0x15,0x31,0x34);write_reg(par,0x21); write_reg(par,0x29);return 0;
}/*** set_var() - apply LCD properties like rotation and BGR mode** @par: FBTFT parameter object** Return: 0 on success, < 0 if error occurred.*/
static int set_var(struct fbtft_par *par)
{u8 madctl_par = 0;if (par->bgr)madctl_par |= MADCTL_BGR;switch (par->info->var.rotate) {case 0:break;case 90: madctl_par |= (MADCTL_MV | MADCTL_MY);break;case 180:madctl_par |= (MADCTL_MX | MADCTL_MY);break;case 270:madctl_par |= (MADCTL_MV | MADCTL_MX);break;default:return -EINVAL;}write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, madctl_par);return 0;
}/*** set_gamma() - set gamma curves** @par: FBTFT parameter object* @curves: gamma curves** Before the gamma curves are applied, they are preprocessed with a bitmask* to ensure syntactically correct input for the display controller.* This implies that the curves input parameter might be changed by this* function and that illegal gamma values are auto-corrected and not* reported as errors.** Return: 0 on success, < 0 if error occurred.*/
static int set_gamma(struct fbtft_par *par, u32 *curves)
{int i;int j;int c; /* curve index offset *//** Bitmasks for gamma curve command parameters.* The masks are the same for both positive and negative voltage* gamma curves.*/static const u8 gamma_par_mask[] = {0xFF, /* V63[3:0], V0[3:0]*/0x3F, /* V1[5:0] */0x3F, /* V2[5:0] */0x1F, /* V4[4:0] */0x1F, /* V6[4:0] */0x3F, /* J0[1:0], V13[3:0] */0x7F, /* V20[6:0] */0x77, /* V36[2:0], V27[2:0] */0x7F, /* V43[6:0] */0x3F, /* J1[1:0], V50[3:0] */0x1F, /* V57[4:0] */0x1F, /* V59[4:0] */0x3F, /* V61[5:0] */0x3F, /* V62[5:0] */};for (i = 0; i < par->gamma.num_curves; i++) {c = i * par->gamma.num_values;for (j = 0; j < par->gamma.num_values; j++)curves[c + j] &= gamma_par_mask[j];write_reg(par, PVGAMCTRL + i,curves[c + 0], curves[c + 1], curves[c + 2],curves[c + 3], curves[c + 4], curves[c + 5],curves[c + 6], curves[c + 7], curves[c + 8],curves[c + 9], curves[c + 10], curves[c + 11],curves[c + 12], curves[c + 13]);}return 0;
}
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{switch(par->info->var.rotate){case 0: xs+=0;xe+=0;ys+=0;ye+=0;break;case 90: xs+=20;xe+=20;ys+=0;ye+=0;break;case 180: xs+=0;xe+=0;ys+=80;ye+=80;break;case 270: xs+=0;xe+=0;ys+=53;ye+=53;break;default :break;}write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}/*** blank() - blank the display** @par: FBTFT parameter object* @on: whether to enable or disable blanking the display** Return: 0 on success, < 0 if error occurred.*/
static int blank(struct fbtft_par *par, bool on)
{if (on)write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);elsewrite_reg(par, MIPI_DCS_SET_DISPLAY_ON);return 0;
}static struct fbtft_display display = {.regwidth = 8,.width = 240,.height = 280,.gamma_num = 2,.gamma_len = 14,.gamma = DEFAULT_GAMMA,.fbtftops = {.init_display = init_display,.set_var = set_var,.set_addr_win = set_addr_win,.set_gamma = set_gamma,.blank = blank,},
};FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7789v", &display);MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:st7789v");
MODULE_ALIAS("platform:st7789v");MODULE_DESCRIPTION("FB driver for the ST7789V LCD Controller");
MODULE_AUTHOR("Dennis Menschel");
MODULE_LICENSE("GPL");
使用menuconfig使能该驱动
在
linux
源码根目录下执行
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-
Device Drivers ---> [*] Staging drivers ---> <*> Support for small TFT LCD display modules ---><*> FB driver for the ST7789V LCD Controller
编译内核设备树
# 编译内核、设备树、模块
make zImage dtbs modules ARCH=arm CROSS_COMPILE=arm-linux-
更新板子内核和设备树文件
将
arch/arm/boot/zImage
内核镜像文件和arch/arm/boot/dts/sun8i-h3-nanopi-neo.dtb
设备树文件拷贝到板子的/boot
目录下,使用内存卡拷贝或者网络传输都可以,这里以网络更新为例
scp arch/arm/boot/zImage root@192.168.31.88:/boot
scp arch/arm/boot/dts/sun8i-h3-nanopi-neo.dtb root@192.168.31.88:/boot
重启板子后屏幕可以出现内核启动和linux终端画面
这里开机logo已经修改,原系统是三只linux企鹅图标
后期玩法
画一张带屏幕的接口板与板子组合成一体,可以移植
lvgl
或者QT
,真正变成一个小电脑
参考链接:NanoPi NEO Air使用十二:使用自带的fbtft驱动点亮SPI接口TFT屏幕,ST7789V
相关文章:

友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕
屏幕介绍 本文以中景园1.69寸LCD,驱动芯片ST7789V2该款屏幕示例,屏幕的分辨率为240*280 屏幕引脚说明 NanoPi NEO IO介绍 屏幕与板子的IO连接关系 屏幕NanoPi NEOGNDGNDVCC3.3VSCLPC2SDAPC0RESPG11DCPA1CSPC3BLKPA0 下载交叉编译器和linux内核源码并按教…...

MFC第三十天 通过CToolBar类开发文字工具栏和工具箱、GDI+边框填充以及基本图形的绘制方法、图形绘制过程的反色线模型和实色模型
文章目录 CControlBar通过CToolBar类开发文字工具栏和工具箱CMainFrame.hCAppCMainFrm.cppCMainView.hCMainView.cppCEllipse.hCEllipse.cppCLine.hCLine.cppCRRect .hCRRect .cpp CControlBar class AFX_NOVTABLE CControlBar : public CWnd{DECLARE_DYNAMIC(CControlBar)pro…...

Android Https
本质:在客户端和服务端使用非对称加密协商出一套对称密钥,每次发送数据前加密,收到后解密,达到加密传输 http ssl 在http之下增加了安全层,用于保障http的加密传输 HTTPS连接 TLS连接步骤 1.客户端发送 client h…...

Games101学习笔记2
参考博客:GAMES101 梳理 / 个人向图形学笔记_games101笔记_river_of_sebajun的博客-CSDN博客 lecture 05 Rasterization 1(Triangles) 光栅化 把东西画在屏幕上的过程就是光栅化的过程 视口变换 为什么模型用三角形? 最基本的几何平面;保…...
java字符串String类的常用方法
java字符串String类的常用方法 字符串的创建: (1)定义字符串直接赋值,在字符串池中开辟空间() String str1“Hello”;//在字符串池中写入字符串"hello" String str2“Hello”;//直接引用字符串池中的"Hello" System.out.println(s…...
自动化测试如何解决chrome自动更新问题
问题 调试好的自动化测试脚本,有时候总是在第一天或过几天就不好使了。产品并未进行功能逻辑,ui修改,一切还和调试自动化脚本的时候保持一致。运行自动化测试脚本时,控制台总是会在driver webdriver.Chrome()这一行报错。 问题…...

闲鱼卖货:新手容易踩坑的7个地方。赶紧看看有没有中招?
科思创业汇 大家好,这里是科思创业汇,一个轻资产创业孵化平台。赚钱的方式有很多种,我希望在科思创业汇能够给你带来最快乐的那一种! 这是我以前的一个学生收到的第一个非法通知。他告诉我,他当时很害怕,…...
PowerShell 获取某目录下所有的文件、文件夹,同时对获取到的文件路径字符串进行替换处理
PowerShell 获取某目录下所有的文件、文件夹,同时对获取到的文件路径字符串进行替换处理 前言: 为了将Windows系统下的Java编译文件与linux服务器上的文件进行比较,故进行此文件路径的获取及路径处理。 在只有文件路径 而没有实际文件的情况下…...

JUC并发编程之线程锁(一)
目录 1.ReentrantLock(互斥锁) 2.ReentRantReaderWriterLock(互斥读写锁) 3.StampedLock(无障碍锁) 4.Condition(自定义锁) 5.LockSupport 问题引出: 由于传统的线程控制需要用到同步机制Sy…...
Android AlertDialog标题居中
网上很多做法都是使用setCustomTitle方法实现的,我偏不,因为我已经找到了标题的textView了: 在show了之后可以拿到标题(注意一定是show之后才能拿得到,create之后拿也是空的): TextView title…...
k8s界面化平台dashboard、kubesphere、Rancher对比
k8s集群管理dashboard有很多,比如kuboard、官方发dashboard、kubesphere、Rancher等等。 Dashboard、KubeSphere 和 Rancher 都是流行的 Kubernetes 管理和操作界面。它们都提供了图形化的用户界面,以简化对 Kubernetes 集群的管理和监控。每个工具都有其…...
【字符串左旋】
字符串左旋 1.题目要求 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 2.解法: 设计循环使其可以旋1次,然后让他执行n次是一个最简单的思路: 函数实现…...
Docker Dirtypipe(CVE-2022-0847)漏洞复现与分析容器逃逸
安装环境 ./metarget cnv install cve-2022-0847 --verbose 原理 同脏牛,通过写只读内存,对映射的内存做篡改 EXP docker run --rm -it -v $(pwd):/exp --cap-addCAP_DAC_READ_SEARCH ubuntu如果提示 Unknown capability to add: "CAP_CAP_DAC_RE…...

python接口自动化测试框架2.0,让你像Postman一样编写测试用例,支持多环境切换、多业务依赖、数据库断言等
项目介绍 接口自动化测试项目2.0 软件架构 本框架主要是基于 Python unittest ddt HTMLTestRunner log excel mysql 企业微信通知 Jenkins 实现的接口自动化框架。 前言 公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化…...

Vue.js2+Cesium1.103.0 九、淹没分析效果
Vue.js2Cesium1.103.0 九、淹没分析效果 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"><spanid"button"style"position: absolute; right: 50px; top: 50px; z-index: 999; font-size: 24px…...

SpringBoot案例-部门管理-新增
根据页面原型,明确需求 页面原型 需求 阅读接口文档 接口文档链接如下: 【腾讯文档】SpringBoot案例所需文档 https://docs.qq.com/doc/DUkRiTWVaUmFVck9N 思路分析 前端在输入要新增的部门名称后,会以JSON格式将数据传入至后端…...
微信小程序中背景图片如何占满整个屏幕,拉伸
不变形 1. 在页面的wxss文件中,设置背景图片的样式: page{background-image: url(图片路径);background-size: 100% 100%;background-repeat: no-repeat; }2. 在页面的json文件中,设置背景图片的样式: {"backgroundTextStyl…...

Java并发编程(四)线程同步 中 [AQS/Lock]
概述 Java中可以通过加锁,来保证多个线程访问某一个公共资源时,资源的访问安全性。Java提出了两种方式来加锁 第一种是我们上文提到的通过关键字synchronized加锁,synchronized底层托管给JVM执行的,并且在java 1.6 以后做了很多…...

PyTorch深度学习环境安装(Anaconda、CUDA、cuDNN)及关联PyCharm
1. 关系讲解 Tytorch:Python机器学习库,基于Torch,用于自然语言处理等应用程序 Anaconda:是默认的python包和环境管理工具,安装了anaconda,就默认安装了conda CUDA:CUDA是一种由显卡厂商NVIDI…...

Active Directory安全和风险状况管理
风险评估和管理 风险评估和管理是主动安全性和合规性管理不可或缺的一部分。 发现关键基础设施组件中的风险行为和配置对于阻止网络入侵和预防网络攻击至关重要。帐户泄露和配置错误漏洞是用于破坏网络的常见技术。当评估、监控和降低 Active Directory 基础架构的风险时&…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...