news 2026/9/11 11:35:58

51单片机驱动ST7789 TFT屏:从接线到刷屏的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
51单片机驱动ST7789 TFT屏:从接线到刷屏的完整指南

简介:51单片机ST7789 320×240驱动包面向嵌入式开发者,针对在51单片机上驱动ST7789控制器TFT屏幕的常见难题,系统覆盖硬件SPI接口连接、初始化命令序列、数据读写协议、显示控制与代码优化等关键技能点。压缩包共23个文件,以C源文件、头文件、Hex固件、Keil工程文件为核心,并包含必要的备份、配置文件,整体仅88KB,轻量紧凑,可直接导入51单片机工程使用。该驱动包已有1445人学习下载,是ST7789与51单片机应用开发中值得参考的实例。资源中不仅提供可调用的驱动源码和工程模板,还通过模拟SPI中文显示、时序控制、帧缓冲管理等实现细节,帮助读者理解从底层寄存器配置到上层显示绘制的完整流程。同时涉及缓冲区管理、亮度调节与电源模式处理等实用内容,对学习嵌入式人机交互界面和快速验证屏幕驱动方案有直接帮助。

1. 51 单片机驱动 ST7789 320×240:瓶颈在显存,不在算力

51 单片机加一块 320×240 的 ST7789 彩色屏,很多人第一反应是“带得动吗”。真实情况是,常见的 STC89C52 也能点亮它,但刷新速度、内存占用、坐标方向这几件事,能把第一次上手的人卡住一两天。问题并不是 51 的算力不够,而是整幅画面 320×240×2 字节,约 150KB 的显存需求,51 内部 RAM 却只有 256 字节到 1KB 级别,缓冲区根本放不下。ST7789 自带 20KB 级别 GRAM,能存下一帧,却没法和 51 共享这块数据。所以这篇驱动说明把整个流程拆成接线、命令初始化、窗口寻址、内存策略和排错五段,一步一步落地,适合刚学会 GPIO 输出想尝试 TFT 屏幕的初学者,也能给想快速拿到 51 驱动 ST7789 方案的嵌入式工程师提供一份可以直接抄改的骨架。

2. 51 最小驱动接线:ST7789 屏引脚、软件 SPI 与硬件 SPI 选型

2.1 320×240 屏的引脚定义与一组能直接用的接线表

ST7789 这个芯片在 320×240 模组上最常见的接口是四线 SPI,也就是 SCL、SDA、CS、DC 四条信号线,加上背光、复位和电源,整块屏一共露出八个引脚。买屏时先确认丝印,很多模组把 DIN 写成 SDA、把 CLK 写成 SCL,名称不一样,含义一样。

屏引脚含义接 51 芯片备注
VCC屏供电3.3V模组带 LDO 时可接 5V,没有 LDO 时只接 3.3V
GND系统共地不共地时 SPI 波形看起来正常但屏幕无响应
DINSPI 数据输入P1.5四线 SPI 模式下只接 MOSI,MISO 通常悬空
CLKSPI 时钟P1.7时钟空闲电平和采样沿决定 CPOL/CPHA
CS片选P1.4 或任意 IO 口只有一块屏时可以直接接地,但仍建议留 GPIO
DC数据/命令选择P1.3低电平写命令,高电平写数据
RESET复位P1.2上电拉低 20ms 以上再拉高
BLK背光控制P1.1 或串电阻接 VCC高电平点亮,低电平关背光

硬件设计时注意几个细节:VCC 和 GND 之间放一个 10μF 电解电容再加一个 0.1μF 陶瓷电容,位置尽量靠近屏的电源排针;背光电流通常在 20mA 到 40mA 之间,如果把它和 51 的 IO 共用同一个稳压器,刷新屏幕时电流波动可能会让单片机复位。最稳妥的做法是背光单独接一个 3.3V 电源轨,IO 只负责切换高低电平。

2.2 软件模拟 SPI:一根普通 GPIO 就能点亮屏幕

标准 8051 架构,比如 STC89C52、AT89S52,没有 SPI 外设,只能用普通 GPIO 逐位翻转。软件模拟 SPI 的时钟频率取决于主频和循环语句条数,在 12MHz 晶振下,一个字节大约需要 7μs 到 10μs。这个速度对初始化命令完全够用,但对全屏刷新来说偏慢,640×480 的图片就别指望了,320×240 一帧 153600 字节,算下来要一秒多。

// 软件模拟 SPI,工作模式 0:空闲低电平,上升沿采样 void spi_write_byte_sw(uint8_t dat) { uint8_t i; for (i = 0; i < 8; i++) { SCLK = 0; // 把时钟拉低,准备移出数据 if (dat & 0x80) { // MSB 先行,先发 bit7 MOSI = 1; } else { MOSI = 0; } dat <<= 1; SCLK = 1; // 上升沿,ST7789 在此时锁存数据 } }

这段代码里的关键点是时钟先拉低再拉高,采样发生在上升沿,对应 SPI 模式 0。如果换成模式 3,空闲电平变成高电平,采样仍在上沿,绝大多数 320×240 的 ST7789 模组也能工作,但为了统一,后续所有寄存器配置都以模式 0 为准。软件模拟 SPI 的好处是任何引脚都能用,不需要查复用寄存器,缺点是主循环被占满,程序没法同时做别的事。

2.3 硬件 SPI:STC12/STC15 上更省心的寄存器写法

STC12C5A60S2、STC15 系列和 STC8 系列都带硬件 SPI 模块。以 STC12C5A60S2 为例,SPI 引脚默认复用在一组 P1 口上:P1.4 是 SS,P1.5 是 MOSI,P1.6 是 MISO,P1.7 是 SCLK。配置成主机模式后,写一个字节只是往 SPDAT 寄存器填数据,然后等 SPIF 标志位即可。

// STC12C5A60S2 硬件 SPI 初始化 void spi_init_hw(void) { // SPCTL 各位含义: // SSIG=1 忽略 SS 引脚,SPEN=1 使能 SPI, // DORD=0 高位先发,MSTR=1 主机模式, // CPOL=0 CPHA=0 对应模式 0, // SPR1=0 SPR0=0 分频系数 4 SPCTL = 0xD0; } // 写一个字节并等待完成 uint8_t spi_rw_hw(uint8_t dat) { SPDAT = dat; while (!(SPSTAT & 0x80)); // 等待 SPIF 置位 SPSTAT = 0x80; // 软件清标志,写 1 才有效 return SPDAT; }

分频系数 SPR1/SPR0 有四种组合:00 对应 4 分频,01 对应 16 分频,10 对应 64 分频,11 对应 128 分频。主频 12MHz 时,4 分频得到 3MHz SPI 时钟,ST7789 完全支持这个速度。如果主频是 24MHz,建议先用 16 分频保守起见,跑通后再把分频降到 4 分频。硬件 SPI 相比软件模拟大约快三到五倍,全屏刷新能压到 0.3 秒左右,这是 51 上做动态界面的基础。

2.4 上电复位时序:背光亮了不等于控制器就绪

ST7789 的上电要求比普通 LCD 模块严格,电源电压稳定后,RESET 引脚至少要维持 10ms 低电平,然后释放,释放后还要再等 120ms 以上再发第一条命令。这里的延时不是敷衍用的,芯片内部有模拟电路负责产生偏压,电压没有稳定时收到命令会被直接丢弃,表现就是屏幕有背光但永远黑屏。

void lcd_reset(void) { LCD_RST = 0; delay_ms(50); // 拉低 50ms,确保完成硬件复位 LCD_RST = 1; delay_ms(150); // 释放后等待内部电源稳定 }

实际操作里,很多人都栽在复位后的第一个延时上。初始化序列里看到 0x11 退出睡眠后再等 120ms 也不要省略,这条延时和硬件复位延时负责的是同一个环节,只是发生在软件层面。如果外接的 RC 复位电路和 51 的复位电路连在一起,屏幕复位时序会受到单片机复位信号影响,建议 RESET 引脚直接用 GPIO 控制,不依赖外部电路。

提示:屏幕没有反应时,先用万用表量 VCC、GND 和背光引脚电压,再查逻辑分析仪上 SCLK 是否有下降沿。绝大多数“驱动代码死活不对”的情况,根源是接线而不是寄存器配置。

3. ST7789 初始化序列与窗口寻址:从写命令到亮起第一个色块

3.1 DC 引脚怎么区分命令和数据

ST7789 通过 DC 引脚的电平区分当前 SPI 总线上传输的是命令还是数据。DC 为低,下一个字节被解析为命令;DC 为高,下一个字节被解析为命令的参数或显存数据。写驱动的第一步就是封装两个最底层的函数。

// 写命令:DC 拉低,发送命令字节 static void lcd_cmd(uint8_t cmd) { LCD_DC = 0; LCD_CS = 0; spi_write_byte(cmd); LCD_CS = 1; } // 写数据:DC 拉高,发送参数或像素数据 static void lcd_dat(uint8_t dat) { LCD_DC = 1; LCD_CS = 0; spi_write_byte(dat); LCD_CS = 1; }

注意这里每次传输都把 CS 拉低再拉高。命令和数据分开传输时可以这么写,连续写大量像素时为了性能要把 CS 一直拉低,只发一次片选信号。每个命令的参数个数不同,比如设置像素格式的命令 0x3A 带一个参数,而设置扫描方向的命令 0x36 同样带一个参数,具体格式以 ST7789 参考手册里的寄存器和时序说明为准。

3.2 完整初始化序列:带注释、带延时的可直接使用版本

初始化序列在不同厂家模组之间有差异,但核心步骤是固定的:硬件复位、退出睡眠、设置像素格式、配置电源与伽马值、打开显示。下面这份序列是我在通用 320×240 模组上经常使用的版本,参数偏向兼容性,不是针对单一屏厂的官方代码。

void st7789_init(void) { lcd_reset(); // 硬件复位:拉低 50ms,释放后延时 150ms lcd_cmd(0x01); // 软件复位 delay_ms(150); lcd_cmd(0x11); // Sleep Out,退出睡眠模式 delay_ms(150); // 这 150ms 不能省,等待内部 DC-DC 启动 lcd_cmd(0x36); lcd_dat(0x00); // MADCTL 扫描方向,先写 0,方向问题稍后调 lcd_cmd(0x3A); lcd_dat(0x05); // 像素格式:RGB565,16 位/像素 // 电源与时序设置 lcd_cmd(0xB2); lcd_dat(0x0C); lcd_dat(0x0C); lcd_dat(0x00); lcd_dat(0x33); lcd_dat(0x33); // Porch 设定 lcd_cmd(0xB7); lcd_dat(0x35); // Gate 控制 lcd_cmd(0xBB); lcd_dat(0x19); // VCOM 电压,3.3V 供电常见值 lcd_cmd(0xC0); lcd_dat(0x2C); // LCM 电压控制 lcd_cmd(0xC2); lcd_dat(0x01); // VDV 使能 lcd_cmd(0xC3); lcd_dat(0x12); // VDV 值 lcd_cmd(0xC4); lcd_dat(0x20); // VDV 响应设置 lcd_cmd(0xC6); lcd_dat(0x0F); // 显示时钟频率 lcd_cmd(0xD0); lcd_dat(0xA4); lcd_dat(0xA1); // 调压设置 // 伽马校正,影响灰阶通透度,不影响能否点亮 lcd_cmd(0xE0); lcd_dat(0xD0); lcd_dat(0x04); lcd_dat(0x0D); lcd_dat(0x11); lcd_dat(0x13); lcd_dat(0x2B); lcd_dat(0x3F); lcd_dat(0x54); lcd_dat(0x4C); lcd_dat(0x18); lcd_dat(0x0D); lcd_dat(0x0B); lcd_dat(0x1F); lcd_dat(0x23); lcd_cmd(0xE1); lcd_dat(0xD0); lcd_dat(0x04); lcd_dat(0x0C); lcd_dat(0x11); lcd_dat(0x13); lcd_dat(0x2C); lcd_dat(0x3F); lcd_dat(0x44); lcd_dat(0x51); lcd_dat(0x2F); lcd_dat(0x1F); lcd_dat(0x1F); lcd_dat(0x20); lcd_dat(0x23); lcd_cmd(0x29); // Display On,显示打开 delay_ms(50); }

这段代码里有两个容易误解的参数。0x3A 命令收到 0x05,内部会解析为 16 位的 RGB565 格式;很多库写成 0x55,是因为高字节位保留不校验,写 0x55 和写 0x05 效果相同,但按参考手册原始定义,低三位 101 才是有效配置。0xB2 到 0xD0 这组参数决定显示面板的模拟电路工作点,不同模组可能出现亮度差异,调试时如果发现屏发暗或者底色偏灰,优先检查 0xBB 的 VCOM 值而不是怀疑 SPI 接线。

3.3 窗口寻址三件套:CASET、RASET、RAMWR 与大端字节序

ST7789 的显存操作不是从头到尾顺序写,而是先指定一个矩形窗口,然后向窗口内连续灌入像素数据。三个命令分别是 0x2A 列地址、0x2B 行地址、0x2C 开始写入显存。坐标参数为两个字节,先发高字节再发低字节,顺序颠倒会显示错乱。

void lcd_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { lcd_cmd(0x2A); // 列地址,对应 X 方向 lcd_dat(x0 >> 8); lcd_dat(x0 & 0xFF); lcd_dat(x1 >> 8); lcd_dat(x1 & 0xFF); lcd_cmd(0x2B); // 行地址,对应 Y 方向 lcd_dat(y0 >> 8); lcd_dat(y0 & 0xFF); lcd_dat(y1 >> 8); lcd_dat(y1 & 0xFF); lcd_cmd(0x2C); // 开始写显存数据 }

设置完窗口之后,每写两个字节代表一个像素的 RGB565 颜色:第一个字节是高 5 位红色和高 6 位绿色的组合,第二个字节是低 5 位蓝色和绿色低位。窗口的 start 和 end 都是闭区间,全屏写满时 x1、y1 分别取 319 和 239,而不是 320 和 240。ST7789 的 GRAM 会自动跨行连续填充,不需要手动改窗口边界,这给后面做图片流式刷新埋下了基础。

3.4 用小色块验证驱动是否成立再往下走

初始化代码写完不要急着做全屏清屏或者画字库,先用一个只有 16×16 像素的小色块验证。全屏清屏一次要写 153600 字节,如果 SPI 或者窗口方向有问题,满屏全是花点,很难定位原因;而 16×16 色块只有 512 字节,颜色、位置、边界三件事一次就能验证清楚。

uint16_t i; // 画一个 16x16 的红色块,屏幕左上角 lcd_set_window(0, 0, 15, 15); for (i = 0; i < 16 * 16; i++) { lcd_dat(0xF8); // RGB565 红色高字节 lcd_dat(0x00); // 低字节 }

如果左上角出现一个红色方块,说明 SPI、复位、DC、初始化序列全部正确。如果出现的是蓝色或者绿色,代表 RGB565 字节序反了,把两个 lcd_dat 参数交换即可。如果方块出现在其他角落,说明 0x36 的扫描方向不对,接下来进入第四章方向调试的逻辑。

4. 51 显存不够怎么办:条带缓冲、分块刷新与屏内 GRAM 复用

4.1 150KB 全屏图像在 51 上注定不能做整幅缓冲

一帧 320×240 的 RGB565 图像需要 320×240×2,算下来 153600 字节。STC89C52 内部只有 128 字节或 256 字节的 RAM,STC12C5A60S2 内部多一块约 1KB 的扩展 RAM,仍然装不下十分之一幅画面。ST7789 内部有 240×320×18 位的 GRAM,约 20KB,能完整存下 320×240 一帧,但它的 GRAM 只能被屏幕控制器读取,51 没法把它当临时画布来使用。

所以 51 驱动 ST7789 的通用做法是放弃全屏重绘,改成局部刷新。每个 UI 控件,比如进度条、波形区、数字显示区,只重绘自己负责的小窗口。这样每次传输量只有几百到几千字节,16MHz 主频下毛刺完全可接受。

4.2 裸点直写与条带缓冲两种模式的选择

最直接的驱动是裸点直写:任何绘图操作都立刻换算成窗口,通过 SPI 写进屏幕显存。

void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color) { lcd_set_window(x, y, x, y); lcd_dat(color >> 8); lcd_dat(color & 0xFF); }

这段代码用来画简单图形是够用的,画一条直线就调用一百次,每次调用都要发五条命令带六个参数,效率很低。要显示字符、波形或滚动列表时,更好的方案是维护一块条带缓冲,把屏幕横向按 320 像素宽、纵向按 32 像素高切成条带,先在内存里画好,再整体提交给屏幕。

#define STRIP_H 32 #define STRIP_SIZE (320 * STRIP_H * 2) // 320*32*2 = 20480 字节 // 将缓冲区内容一次性刷到屏幕指定区域 void flush_strip(uint16_t y0) { uint16_t i; lcd_set_window(0, y0, 319, y0 + STRIP_H - 1); LCD_CS = 0; // 片选只拉低一次,提高连续传输效率 for (i = 0; i < STRIP_SIZE; i++) spi_write_byte(strip_buf[i]); LCD_CS = 1; }

裸点直写适合界面元素少、每次重绘范围小的场景,比如温度显示每隔一秒变一次。条带缓冲适合做波形滚动、中文字库混排、多行菜单这类频繁覆盖大区域的场景。20KB 的条带缓冲区如果片内放不下,可以放到外部扩展 RAM,或者在 STC15/STC8 上放宽到 64KB 片内存储的型号。

4.3 从 SPI Flash 或串口流式刷全屏图片的代码骨架

要显示整幅图片,常见做法是外挂一片 SPI Flash 存放图片数据,再按行分块读出来写入屏幕。这个过程不需要把整张图装进内存,每读一块刷一块,内存占用只有临时缓冲。

#define CHUNK_ROWS 32 uint8_t chunk_buf[320 * CHUNK_ROWS * 2]; // 20480 字节 void show_image_from_flash(uint32_t img_offset) { uint16_t y; for (y = 0; y < 240; y += CHUNK_ROWS) { // 从外部 Flash 读取 32 行图片数据到缓冲区 spi_flash_read(img_offset + y * 320 * 2, chunk_buf, sizeof(chunk_buf)); // 设置窗口并写入屏幕 lcd_set_window(0, y, 319, y + CHUNK_ROWS - 1); LCD_CS = 0; for (uint16_t i = 0; i < sizeof(chunk_buf); i++) spi_write_byte(chunk_buf[i]); LCD_CS = 1; } }

这个流程里每刷 32 行要用 20KB 缓冲区,STM32 这类平台可以改大,51 上 32 行是一个性价比很好的分块尺寸:缓冲区能放进扩展 RAM,刷新次数也只有八次,每次窗口切换的开销可以忽略。需要显示动态波形或者动画时,把整个显示刷新逻辑放在主循环里,每帧只调一次 show_image_from_flash,就能得到一个低速但可靠的幻灯效果。

4.4 想刷动态界面:STC8 的 SPI+DMA 升级路线

如果项目需要流畅刷动画,STC12 系的软查标志位方式还是不够。STC8H 系列仍然属于 51 架构,指令兼容,但片内带有 SPI 和 DMA 控制器,可以把一整块内存数据自动搬运到 SPI 外设,发送完成后触发中断。这种模式下 51 主循环只需要修改条带缓冲区的数据,然后启动一次 DMA 传输,屏幕就会自动刷新。

用这种方式时,条带缓冲可以再一次扩大,直接把 64KB 以内的图片缓存放在 STC8 的扩展 RAM 中,DMA 每搬完一段就更新窗口地址。实际效果是分辨率 320×240 的静态刷新能降到 100ms 以内,动画界面不再是奢求。这套方案仍然延续 51 的开发方式,不需要切换到 ARM 平台,是 51 系驱动 ST7789 最接近“流畅”的落点。

5. 方向、花屏与刷新速度:ST7789 参数调试的三个必查项

5.1 画面镜像和旋转都由 0x36 控制,不是改坐标

ST7789 的扫描方向由 MADCTL 寄存器,也就是命令 0x36 决定,三个关键位是 MY、MX、MV。MY 控制从上到下还是从下到上扫,MX 控制从左到右还是从右到左扫,MV 控制行和列是否交换。注意,旋转 90° 也许搭配设置 MV 位为 1,同时交换宽度和高度,而不是在代码里把所有 x、y 坐标对调。

建议在驱动里固定一个函数集中管理方向,后续所有绘图接口都基于逻辑坐标。

void lcd_set_rotation(uint8_t rot) { switch (rot) { case 0: lcd_cmd(0x36); lcd_dat(0x00); break; // 纵屏,左上角起点 case 1: lcd_cmd(0x36); lcd_dat(0x60); break; // 横屏,左方旋转 case 2: lcd_cmd(0x36); lcd_dat(0xC0); break; // 纵屏,倒置 case 3: lcd_cmd(0x36); lcd_dat(0xA0); break; // 横屏,右方旋转 } }

不同模组的排线方向不一样,这四组值不保证每次装上就是正向。调试方法是:先画一个带文字内容的色块,观察镜像方向,再调整对应位的值,直到文字正向且不镜像。

5.2 花屏的三个区间定位:时序、电源、字节序

花屏出问题时要分段定位,不要上来就怀疑初始化序列。先从最原始的环节排查。

现象优先检查项对应位置
黑屏无任何反应RESET 延时、VCC 电压上电复位流程
满屏噪点雪花SCLK 与 DIN 接反、模式 0/模式 3 设置错SPI 接线与 CPOL/CPHA
显示颜色错乱RGB565 高字节低字节颠倒写入显存的数据格式
底色偏灰、亮度忽闪0xBB 的 VCOM 值,匹配屏厂推荐初始化序列电源参数
画面残影、局部不刷新窗口边界算错,x1/y1 写成尺寸值CASET/RASET 参数

字节序的问题最隐蔽。RGB565 红色像素高字节是 0xF8,低字节是 0x00,如果把低字节先发,红色会变成暗蓝色甚至紫黑色。确认方法是定义红色、绿色、蓝色三个纯色宏,分别画三个色块,比对输出。

#define COLOR_RED 0xF800 #define COLOR_GREEN 0x07E0 #define COLOR_BLUE 0x001F

5.3 刷新速度的最后一个减法:省掉不必要的重建

51 上最有效的优化不是改 SPI 分频,而是减少写入量。全屏清一次颜色大约写 150KB,即便硬件 SPI 也要几十毫秒;许多界面刷新时并不需要全清,只重绘变化区域是最高性价比的优化。其次是连续传输时保持 CS 低电平,避免每个字节都做一次 CS 下降和上升,这个动作对软件模拟 SPI 影响尤其明显。最后才是修改分频系数,STC12 系把分频从 16 改成 4,刷屏时间大约缩短四倍,但要确认 SPI 时钟不超过 ST7789 手册给出的上限,51 平台上一般跑 4MHz 以内足够稳定。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 11:33:52

Python数据处理实战:从pandas基础到高效数据分析的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 11:33:36

WiFi温湿度传感器与485温湿度传感器深度对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 11:30:52

Flink CDC实现MySQL实时数据同步与变更捕获

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 11:30:29

FPGA实现图像直方图统计与均衡化的技术解析

1. FPGA直方图统计与均衡化Demo工程解析 作为一名FPGA开发工程师&#xff0c;我最近完成了一个关于图像直方图统计与均衡化的Demo工程。这个项目不仅让我深入理解了图像处理的基础算法&#xff0c;还让我掌握了如何在FPGA上高效实现这些算法。下面我将详细分享这个项目的实现过…

作者头像 李华
网站建设 2026/9/11 11:30:24

macOS 菜单栏管理工具 Ice 完整指南:5 分钟整理混乱的图标

macOS 菜单栏管理工具 Ice 完整指南&#xff1a;5 分钟整理混乱的图标 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice Ice 是一款免费开源的 macOS 菜单栏管理工具&#xff0c;能把屏幕右上角挤在一…

作者头像 李华
网站建设 2026/9/11 11:28:31

高性能服务器必知:TCP/IP协议栈底层逻辑与内核调优实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华