PIC16F676 软件 SPI 驱动 nRF24L01 无线收发实战
简介这份资源面向嵌入式初学者与PIC单片机开发者提供16F676通过SPI接口驱动nRF24L01无线模块完成收发通信的完整程序可用于智能家居、无线遥控、物联网设备等短距离2.4GHz通信场景的学习与二次开发。压缩包共22个文件约56KB以C源码、头文件、HEX烧录文件、MPLAB工程文件及编译中间文件为主另含少量说明文本覆盖从源码到可烧录固件的完整链路。目前已有324人学习下载。读者可从中获取SPI初始化、nRF24L01工作模式与通道频率配置、数据收发缓冲区操作、中断标志处理及CRC错误与重传监控等关键实现思路并借助工程文件在MPLAB X IDE中直接编译调试快速理解PIC单片机与无线模块协同工作的软硬件配合方式。1. 用 PIC16F676 驱动 nRF24L018 位小单片机也能跑无线收发手头只有一颗 8 引脚、Flash 才 1K 字的 PIC16F676却想让它通过 nRF24L01 收发数据这事听起来有点勉强但确实能跑通。我最早做这个组合是因为一个电池供电的遥控采集节点主控只能用最便宜的小片子无线部分又不想用红外或者 433 超再生那种玄学方案最后选了 nRF24L01。PIC16F676 没有硬件 SPI所有时序都得靠软件模拟这是整个方案里最需要耐心的地方。这篇文章面向的是手里有 PIC16F676 和 nRF24L01 模块、想自己写收发程序但被时序和寄存器卡住的嵌入式开发者。我会把 SPI 模拟、寄存器配置、收发流程、常见翻车点都拆开讲代码可以直接抄去改。2. 先搞清楚 PIC16F676 和 nRF24L01 的硬件边界2.1 为什么这两颗芯片搭配起来需要特别处理PIC16F676 是 Microchip 的一款 8 位闪存单片机14 引脚封装实际可用 I/O 是 12 个1K 字程序存储器64 字节 RAM没有硬件 SPI、没有硬件 UART只有一个 8 位定时器和比较器。nRF24L01 是 Nordic 的 2.4GHz 收发芯片通过 SPI 接口访问内部寄存器支持 125 个频道、6 个管道、自动应答和自动重传。两者放在一起最大的矛盾在于nRF24L01 的 SPI 时钟最高可以到 10MHz但 PIC16F676 在 4MHz 晶振下指令周期是 1μs软件模拟 SPI 时一个时钟周期至少需要几个指令周期实际能跑到的 SPI 速率大概在 100kHz 到 250kHz 之间。这个速率对 nRF24L01 来说完全够用因为它的寄存器操作本身就不需要高速真正影响的是收发切换时的响应延迟。另一个边界是 RAM。PIC16F676 只有 64 字节 RAMnRF24L01 的一包数据最多 32 字节加上状态变量、指针、临时缓冲很容易就把 RAM 吃满。我一般会留出至少 8 字节给栈和临时变量实际可用于收发缓冲的也就 40 字节左右。这意味着你不能在中断里做大数组操作也不能嵌套太多函数调用。2.2 引脚分配与最小系统接线PIC16F676 的引脚不多必须精打细算。下面是我常用的接线方案用 PORTA 和 PORTC 的部分引脚PIC16F676 引脚功能接 nRF24L01 引脚说明RA0模拟输入/数字 I/O不接留作电池电压检测RA1数字 I/OCE使能收发模式RA2数字 I/OCSN片选低有效RA3数字 I/OSCKSPI 时钟RA4数字 I/OMOSI主机输出RA5数字 I/OMISO主机输入RC0数字 I/OIRQ中断输出可选VDD电源VCC3.3VVSS地GND共地注意 nRF24L01 的供电是 3.3V不能直接接 5V。PIC16F676 如果跑在 5VSPI 信号线上需要做电平转换最简单的方法是在 MOSI、SCK、CSN、CE 上串 1kΩ 电阻再并 3.3V 稳压管或者直接用 3.3V 给 PIC 供电。我一般让整个系统跑 3.3V省掉电平转换的麻烦。2.3 软件模拟 SPI 的时序要求nRF24L01 的 SPI 模式是 Mode 0CPOL0CPHA0也就是时钟空闲为低数据在上升沿采样。PIC16F676 模拟 SPI 时需要手动控制 SCK 的高低和数据的输出/采样。下面是最基础的三个函数// SPI 写一个字节返回同时读到的字节 unsigned char spi_transfer(unsigned char data) { unsigned char i; unsigned char recv 0; for (i 0; i 8; i) { // 准备 MOSI先放数据再拉高 SCK if (data 0x80) MOSI 1; else MOSI 0; data 1; SCK 1; // 上升沿nRF24L01 采样 MOSI __delay_us(1); // 保持高电平至少 1us recv 1; if (MISO) recv | 0x01; // 下降沿前读取 MISO SCK 0; // 下降沿 __delay_us(1); } return recv; }这段代码里__delay_us(1)是为了保证 SCK 高低电平各维持至少 1μs对应大约 250kHz 的 SPI 时钟。如果你把 PIC 超频到 8MHz可以把延时缩短但没必要因为 nRF24L01 的寄存器操作对速度不敏感。关键点是数据必须在 SCK 上升沿之前稳定MISO 在 SCK 下降沿之前读取。很多新手翻车是因为先拉高 SCK 再改 MOSI导致 nRF24L01 采样到错误的数据。3. nRF24L01 的寄存器配置与收发流程3.1 必须配置的五个核心寄存器nRF24L01 有 20 多个寄存器但实际做点对点收发只需要重点配置下面五个寄存器地址名称配置值示例作用0x00CONFIG0x0E 或 0x0F使能 CRC、16 位 CRC、上电、收发模式0x01EN_AA0x01使能管道 0 自动应答0x02EN_RXADDR0x01使能管道 0 接收0x03SETUP_AW0x03地址宽度 5 字节0x05RF_CH0x4C射频频道 762.476GHz0x06RF_SETUP0x070dBm 发射功率、2Mbps 速率CONFIG 寄存器的 0x0E 表示EN_CRC1CRCO116 位 CRCPWR_UP1PRIM_RX0发射模式。如果要切到接收模式把最低位改成 1即 0x0F。RF_SETUP 的 0x07 表示 2Mbps 速率、0dBm 功率如果通信距离不够可以改成 0x061Mbps或 0x05250kbps速率越低灵敏度越高。3.2 写寄存器与读寄存器的命令格式nRF24L01 的 SPI 命令分两类写寄存器是 0x20 | 寄存器地址读寄存器是 0x00 | 寄存器地址。写数据到发送缓冲区是 0xA0读接收缓冲区是 0x61。下面是对应的封装函数// 写一个寄存器 void nrf_write_reg(unsigned char reg, unsigned char value) { CSN 0; // 片选拉低 spi_transfer(0x20 | reg); // 写命令 寄存器地址 spi_transfer(value); // 写入的值 CSN 1; // 片选拉高锁存 } // 读一个寄存器 unsigned char nrf_read_reg(unsigned char reg) { unsigned char value; CSN 0; spi_transfer(0x00 | reg); // 读命令 寄存器地址 value spi_transfer(0xFF); // 发送哑数据同时读回 CSN 1; return value; } // 写发送缓冲区payload 是数据指针len 是长度 void nrf_write_payload(unsigned char *payload, unsigned char len) { unsigned char i; CSN 0; spi_transfer(0xA0); // 写 TX FIFO 命令 for (i 0; i len; i) spi_transfer(payload[i]); CSN 1; }注意spi_transfer(0xFF)里的 0xFF 是哑数据因为 SPI 是全双工主机必须发送一个字节才能产生时钟从而读回从机的数据。CSN 必须在整个命令序列期间保持低电平命令字节和数据字节之间不能拉高否则 nRF24L01 会认为命令结束。3.3 发射流程与接收流程的代码实现发射一包数据的完整流程是拉低 CE 进入待机、写 TX 地址、写 payload、拉高 CE 触发发射、等待 IRQ 或查询 STATUS 寄存器。接收流程是配置为接收模式、拉高 CE、等待 IRQ、读 payload、清中断标志。下面是简化后的收发函数// 发射一包数据返回 1 表示成功0 表示失败 unsigned char nrf_tx_packet(unsigned char *data, unsigned char len) { unsigned char status; CE 0; nrf_write_reg(0x00, 0x0E); // 发射模式 nrf_write_reg(0x04, 0x00); // 清 STATUS 中断标志 nrf_write_payload(data, len); // 写数据到 TX FIFO CE 1; // 触发发射 __delay_us(20); // 保持 CE 高至少 10us CE 0; // 等待发射完成最多等 10ms for (unsigned int timeout 0; timeout 1000; timeout) { status nrf_read_reg(0x07); // 读 STATUS if (status 0x20) // TX_DS 置位发射成功 return 1; if (status 0x10) // MAX_RT 置位重传失败 return 0; __delay_us(10); } return 0; } // 接收一包数据返回数据长度0 表示没收到 unsigned char nrf_rx_packet(unsigned char *buf) { unsigned char status, len; status nrf_read_reg(0x07); if (status 0x40) { // RX_DR 置位收到数据 CSN 0; spi_transfer(0x61); // 读 RX FIFO 命令 len spi_transfer(0xFF); // 第一个字节是长度 for (unsigned char i 0; i len; i) buf[i] spi_transfer(0xFF); CSN 1; nrf_write_reg(0x07, 0x40); // 清 RX_DR 标志 return len; } return 0; }发射函数里CE 拉高后必须保持至少 10μsnRF24L01 才会真正启动发射。等待 TX_DS 或 MAX_RT 的超时时间我设了 10ms实际在 2Mbps 速率下一包 32 字节的数据发射时间不到 200μs加上自动重传10ms 足够。接收函数里读 RX FIFO 的第一个字节是数据长度这个长度是发射端写入的 payload 长度不是固定值。4. 避坑与常见问题排查4.1 现象发射端一直返回失败STATUS 的 MAX_RT 置位原因通常是接收端没有上电、地址不匹配、频道不一致或者自动应答配置错误。nRF24L01 的自动重传机制要求接收端开启 EN_AA 并且地址匹配否则发射端会一直重传直到 MAX_RT。解决方法是先用nrf_read_reg读回接收端的 CONFIG、EN_AA、RF_CH、RX_ADDR_P0 四个寄存器确认和发射端一致。特别是 RX_ADDR_P0 必须和发射端的 TX_ADDR 相同很多人只配了 TX_ADDR 忘了配 RX_ADDR_P0。4.2 现象接收端收不到数据但发射端显示成功这种情况多半是接收端的 CE 没有拉高或者 PRIM_RX 位没有置 1。nRF24L01 在接收模式下CE 必须保持高电平才能持续监听。另外接收端的 EN_RXADDR 必须使能对应的管道如果用的是管道 0EN_RXADDR 的最低位必须是 1。我遇到过因为nrf_write_reg(0x02, 0x01)写成了0x00接收端完全不响应查了半天才发现是寄存器值写错。4.3 现象通信距离很短几厘米就断先检查电源。nRF24L01 在发射瞬间电流会冲到 12mA 以上如果电源去耦不好电压会跌落导致芯片复位。我一般会在 nRF24L01 的 VCC 和 GND 之间并一个 10μF 钽电容和一个 100nF 陶瓷电容越靠近模块越好。其次检查 RF_SETUP 的速率和功率设置2Mbps 速率虽然快但灵敏度低改成 1Mbps 或 250kbps 能明显增加距离。最后检查天线PCB 天线周围不能铺地也不能有金属遮挡。4.4 现象SPI 读写寄存器返回值全是 0x00 或 0xFF这是典型的 SPI 时序问题。先用示波器看 SCK、MOSI、CSN 三根线确认 CSN 拉低后 SCK 才有波形MOSI 在 SCK 上升沿之前已经稳定。如果没有示波器可以写一个最简单的测试向 CONFIG 寄存器写 0x0E再读回来如果读回的不是 0x0E说明 SPI 通信本身有问题。常见原因是 MISO 方向配置错误PIC16F676 的 TRIS 寄存器没有把 MISO 对应的引脚设为输入。4.5 现象程序跑一段时间后死机或数据错乱PIC16F676 的 RAM 只有 64 字节如果收发缓冲定义得太大或者中断里用了太多局部变量栈会溢出。我一般把收发缓冲定义为全局数组大小不超过 32 字节中断里只置标志位不做数据处理。另外nRF24L01 的 STATUS 寄存器在每次操作后最好读一次并清除否则中断标志累积会导致误判。5. 进阶技巧用状态机把收发逻辑串起来5.1 为什么裸写收发函数容易翻车上面给的nrf_tx_packet和nrf_rx_packet是阻塞式的发射时要等 10ms接收时要轮询。在实际项目里如果主循环还有其他任务比如读传感器、驱动数码管阻塞式收发会让整个系统响应变慢。更麻烦的是如果发射失败需要重发或者接收和发射需要切换裸写函数很容易把状态搞乱。我早期做的一个遥控器就是因为发射函数里等了太久按键响应延迟到肉眼可见。5.2 用状态机管理收发切换状态机的思路是把收发过程拆成几个状态空闲、配置为发射、写数据、等待发射完成、配置为接收、等待接收。每个状态只做一件事主循环每次进来推进一步。下面是一个简化的状态机框架// 收发状态定义 typedef enum { STATE_IDLE, STATE_TX_SETUP, STATE_TX_SEND, STATE_TX_WAIT, STATE_RX_SETUP, STATE_RX_WAIT } rf_state_t; rf_state_t rf_state STATE_IDLE; unsigned char tx_buf[32]; unsigned char tx_len; unsigned char rx_buf[32]; unsigned char rx_len; // 主循环里调用每次推进一步 void rf_task(void) { unsigned char status; switch (rf_state) { case STATE_IDLE: // 空闲时切到接收模式 rf_state STATE_RX_SETUP; break; case STATE_TX_SETUP: CE 0; nrf_write_reg(0x00, 0x0E); // 发射模式 nrf_write_reg(0x04, 0x00); // 清中断 nrf_write_payload(tx_buf, tx_len); rf_state STATE_TX_SEND; break; case STATE_TX_SEND: CE 1; __delay_us(20); CE 0; rf_state STATE_TX_WAIT; break; case STATE_TX_WAIT: status nrf_read_reg(0x07); if (status 0x20) { // 发射成功 nrf_write_reg(0x07, 0x20); rf_state STATE_RX_SETUP; } else if (status 0x10) { // 重传失败 nrf_write_reg(0x07, 0x10); rf_state STATE_RX_SETUP; } // 否则继续等不改变状态 break; case STATE_RX_SETUP: CE 0; nrf_write_reg(0x00, 0x0F); // 接收模式 nrf_write_reg(0x07, 0x40); // 清 RX_DR CE 1; rf_state STATE_RX_WAIT; break; case STATE_RX_WAIT: status nrf_read_reg(0x07); if (status 0x40) { // 收到数据 rx_len nrf_rx_packet(rx_buf); rf_state STATE_IDLE; } break; } }这个状态机里STATE_TX_WAIT和STATE_RX_WAIT不会阻塞每次调用只查一次 STATUS没完成就下次再查。主循环可以以 1ms 或更快的周期调用rf_task按键和传感器处理放在主循环其他位置互不干扰。注意STATE_TX_WAIT里没有超时计数实际使用时需要加一个计数器超过一定次数强制回到STATE_RX_SETUP否则发射失败会卡死。5.3 用 IRQ 引脚减少轮询开销如果 PIC16F676 的引脚够用可以把 nRF24L01 的 IRQ 接到 RC0 并配置外部中断。IRQ 在发射成功、接收成功、重传失败时都会拉低中断里只置一个标志位主循环根据标志位决定下一步。这样rf_task里就不需要频繁读 STATUS 寄存器SPI 总线占用更少。PIC16F676 的 RB0/INT 引脚也可以用作外部中断但要注意中断触发边沿配置。5.4 地址和频道的动态切换点对点通信时地址和频道固定就行。但如果要做一对多或者避免干扰可以在运行时切换。nRF24L01 的 RX_ADDR_P0 到 RX_ADDR_P5 可以分别设置不同地址发射时通过 TX_ADDR 指定目标。频道切换直接写 RF_CH 寄存器即可但切换后需要重新进入接收模式。我一般把频道和地址做成一个配置表存在 PIC16F676 的 EEPROM 里上电时读出来初始化。5.5 一个我踩过的坑CE 和 CSN 的时序关系最后说一个血泪经验。nRF24L01 的 CE 和 CSN 不能同时拉低否则芯片会进入不确定状态。正确的顺序是先拉低 CSN 做 SPI 操作操作完拉高 CSN再拉高 CE 触发发射或接收。我早期写代码时在nrf_write_payload里忘了拉高 CSN紧接着就拉高 CE结果 nRF24L01 一直不工作查了两天才发现是 CSN 没有释放。后来我养成了一个习惯每个 SPI 操作函数结束时都强制CSN 1不管之前是什么状态。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

STM32驱动24位ADC CS1238:GPIO模拟I2C时序与第25个时钟应答详解

STM32驱动24位ADC CS1238:GPIO模拟I2C时序与第25个时钟应答详解

简介:面向STM32平台的CS1238/CS1237 ADC驱动包,用于解决嵌入式系统中高精度、低功耗模拟信号采集问题。CS1238是CS1237的升级版本,作为十二位逐次逼近型ADC,支持多输入通道以及单次转换、连续转换等工作模式;驱动源码已…

2026/10/16 17:09:13 阅读更多 →
等几何分析Matlab库:NURBS与PDE耦合的可调试实现

等几何分析Matlab库:NURBS与PDE耦合的可调试实现

简介:本资源是一个面向计算力学研究者与工程仿真工程师的等几何分析(IGA)专用MATLAB开源库,聚焦CAD模型与数值分析的无缝衔接,有效解决传统有限元中几何近似误差大、模型重构繁琐等痛点,特别适用于断裂力学…

2026/10/16 17:08:06 阅读更多 →
人脸识别SDK集成实战:从离线部署到阈值标定的完整指南

人脸识别SDK集成实战:从离线部署到阈值标定的完整指南

简介:这是一套免费提供的人脸识别开发包SDK,面向需要在应用中集成人脸检测、关键点定位、特征提取与比对功能的开发者。包体小巧,仅2.82MB,共214个文件,包含93个dat数据文件、34个h头文件、26个cpp源码文件&#xff0c…

2026/10/16 17:08:06 阅读更多 →

最新新闻

Samba 3.0 嵌入式烧录指南:AT91芯片ROM Bootloader实战

Samba 3.0 嵌入式烧录指南:AT91芯片ROM Bootloader实战

简介:本资源为Samba 3.0配套的SAM-BA嵌入式编程工具套件,面向嵌入式开发工程师、Linux系统管理员及跨平台网络服务部署人员,解决ARM微控制器(如SAM V7、SAMA5D2/D4系列)在Windows环境下的固件烧录、底层调试与QML设备交…

2026/10/16 17:48:12 阅读更多 →
Apache Beam WordCount 深度解析:从 PCollection 到分布式 Runner

Apache Beam WordCount 深度解析:从 PCollection 到分布式 Runner

1. 为什么拿WordCount开刀:它几乎覆盖了Beam的全部核心概念 打开Beam官方文档,WordCount几乎总是出现在示例列表第一位。不少教程把它定义成"词频统计的Hello World",照着敲一遍、本地跑通,然后就没有然后了。但我在几个…

2026/10/16 17:48:12 阅读更多 →
Windows防火墙开放8080端口全攻略:入站规则、netsh与PowerShell实战

Windows防火墙开放8080端口全攻略:入站规则、netsh与PowerShell实战

简介:面向Windows服务器运维与安全配置人员,这份文档以开放8080端口为例,系统讲解通过系统防火墙开启入站端口的标准流程。内容从控制面板进入Windows防火墙,再依次打开高级设置与入站规则,详细展示了新建端口规则的每…

2026/10/16 17:48:12 阅读更多 →
电机设计MATLAB源代码:主尺寸、磁路与绕组校核实战

电机设计MATLAB源代码:主尺寸、磁路与绕组校核实战

简介:电机设计MATLAB源代码合集,由作者基于电机学典型章节整理而成,共17个m文件,压缩包整体仅11KB,主要面向电机方向学生与初步接触电机设计的工程师。代码覆盖直流/交流电机模型、磁路与电路分析、转矩功率计算、控制…

2026/10/16 17:48:12 阅读更多 →
Windows 2008 R2 RAID驱动注入:解决安装卡在找不到硬盘

Windows 2008 R2 RAID驱动注入:解决安装卡在找不到硬盘

简介:本资源是一份面向Windows Server系统管理员与IT运维工程师的实战型技术文档,专门解决Windows Server 2008 R2安装过程中因缺失RAID卡驱动导致无法识别硬盘的典型部署难题。文档详细梳理了使用系统原生dism.exe工具将RAID驱动集成至install.wim与boo…

2026/10/16 17:47:10 阅读更多 →
头部姿态估计:从欧拉角到深度学习回归的完整解析

头部姿态估计:从欧拉角到深度学习回归的完整解析

简介:头部姿态估计文献资源包面向计算机视觉与人工智能方向的研究人员、算法工程师及高年级学生,聚焦从图像或视频中推断头部三维角度与位置这一核心问题,可服务于虚拟现实、自动驾驶疲劳检测、智能监控与人机交互等场景。压缩包共5个文件&am…

2026/10/16 17:47:10 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

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

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →