STM32软件模拟IIC驱动PCA9555:时序、寄存器与避坑指南

简介:这份资源面向使用STM32F103进行嵌入式开发的工程师与学习者,聚焦于用GPIO软件模拟IIC时序来驱动PCA9555这款16位IO扩展芯片,解决单片机IO口不足、需要外扩端口的实际问题。压缩包共127个文件,约2MB,以32个c源文件与33个h头文件为核心,涵盖STM32标准外设库、PCA9555读写驱动及主程序逻辑,另含14个o、14个d编译中间文件、13个crf、1个hex与1个axf等构建产物,以及uvprojx、uvoptx工程配置和sct、lst、map等链接与列表文件,可直接用Keil打开编译。资源已有4838人学习下载,热度较高。读者可从中获得完整的模拟IIC底层时序实现、PCA9555寄存器读写封装、GPIO推挽输出与上拉配置范例,以及可复用的工程模板与排错参考,适合需要快速验证IO扩展方案的中初级开发者。

1. 为什么我宁愿用软件模拟 IIC 去驱动 PCA9555

手上这块 STM32F103 的板子,硬件 IIC 外设被前人拿去接了别的从机,留给扩展 IO 的只剩两根普通 GPIO。项目又急着要读一组按键和驱动几路继电器,PCA9555 这颗 16 位 IO 扩展芯片正好合适,可总线资源已经没了。翻了一圈资料,发现用软件模拟 IIC 访问 PCA9555 是条稳妥的路子,时序完全由自己掌控,不用跟硬件外设的坑较劲。这篇就把我实际跑通的模拟 IIC 方案拆开讲清楚,从时序原理到寄存器读写,再到踩过的几个坑,新手照着能复现,熟手也能对照看看边界在哪。

2. 模拟 IIC 的时序底座与 PCA9555 寄存器模型

2.1 为什么模拟 IIC 在这类场景反而更省心

STM32F103 的硬件 IIC 外设,用过的人多少都听过一些玄学问题,比如总线锁死、状态机卡在某个标志位出不来。当然这些问题在正确配置下大多能规避,但在一个 IO 资源紧张、又不想花时间调硬件外设的场合,软件模拟的性价比就出来了。模拟 IIC 的本质就是用两根 GPIO 手动翻转电平,去复现 IIC 协议的起始、停止、应答和字节传输。它的好处是时序可见、可打断点、可加延时,出问题一眼能看出是哪一拍不对。代价是占用 CPU 时间,速率上不去,通常跑到 100kHz 左右比较稳,再快就要看主频和延时函数的精度了。

PCA9555 这边,它是一颗通过 IIC 挂载的 16 位 IO 扩展器,分成两个 8 位端口 Port0 和 Port1。每个端口有输入寄存器、输出寄存器、极性反转寄存器和配置寄存器。配置寄存器决定某个引脚是输入还是输出,这一点和 STM32 的 GPIO 模式寄存器思路类似。上电后所有引脚默认是输入,这点要记住,不然你会发现自己写输出寄存器没反应,其实是引脚还处在输入态。

2.2 模拟 IIC 的四个基本时序单元

模拟 IIC 要跑通,核心就是四个动作:起始条件、停止条件、发送一个字节、接收一个字节并回应答。起始条件是 SCL 为高时 SDA 由高变低,停止条件是 SCL 为高时 SDA 由低变高。发送字节时,数据在 SCL 低电平期间变化,在 SCL 高电平期间保持稳定,从机在这期间采样。接收字节类似,只是方向反过来,主机在第八个时钟后拉低 SDA 表示应答。

下面这段是起始和停止的代码,我一般把 SDA 和 SCL 都配成开漏输出,外接上拉电阻。开漏的好处是总线可以多设备共享,不会出现推挽对推挽的短路。

// 假设 SDA 接 PB7,SCL 接 PB6,均配置为开漏输出 #define IIC_SDA_H() GPIOB->BSRR = GPIO_Pin_7 // SDA 拉高 #define IIC_SDA_L() GPIOB->BRR = GPIO_Pin_7 // SDA 拉低 #define IIC_SCL_H() GPIOB->BSRR = GPIO_Pin_6 #define IIC_SCL_L() GPIOB->BRR = GPIO_Pin_6 #define IIC_SDA_READ() ((GPIOB->IDR & GPIO_Pin_7) ? 1 : 0) // 起始条件:SCL 高时 SDA 由高变低 void IIC_Start(void) { IIC_SDA_H(); IIC_SCL_H(); IIC_Delay(); // 延时约 4~5us,对应 100kHz 左右 IIC_SDA_L(); IIC_Delay(); IIC_SCL_L(); // 钳住总线,准备发送数据 IIC_Delay(); } // 停止条件:SCL 高时 SDA 由低变高 void IIC_Stop(void) { IIC_SDA_L(); IIC_SCL_H(); IIC_Delay(); IIC_SDA_H(); IIC_Delay(); }

这里的IIC_Delay()是个简单的空循环或__NOP()组合,具体循环次数要按主频算。72MHz 下我一般用几个__NOP()凑出 4us 左右。延时太短从机可能来不及采样,太长则速率掉得厉害。这个延时是模拟 IIC 最容易被忽略的参数,很多人代码逻辑没错,就是延时不对导致读回来全是 0xFF 或 0x00。

2.3 PCA9555 的寄存器地址与读写命令字

PCA9555 的 IIC 从机地址由 A2、A1、A0 三个引脚决定,7 位地址是0100 A2 A1 A0。如果三个脚都接地,7 位地址就是 0x20,写命令字是 0x40,读命令字是 0x41。注意这里说的是 8 位命令字,也就是 7 位地址左移一位再或上读写位。

它的寄存器命令字节有 8 个,分两组,每组四个:

命令字节寄存器说明
0x00Port0 输入寄存器读 Port0 引脚电平
0x01Port0 输出寄存器写 Port0 输出电平
0x02Port0 极性反转反转输入极性
0x03Port0 配置寄存器1 为输入,0 为输出
0x04Port1 输入寄存器读 Port1 引脚电平
0x05Port1 输出寄存器写 Port1 输出电平
0x06Port1 极性反转反转输入极性
0x07Port1 配置寄存器1 为输入,0 为输出

写寄存器时,先发写命令字,再发寄存器命令字节,然后发数据。读寄存器时,先发写命令字,再发寄存器命令字节,然后重新发起始条件,发读命令字,再读数据。这个「写命令字节再重启读」的流程是 PCA9555 读操作的关键,漏掉重启直接读会拿到错误数据。

3. 从零把模拟 IIC 读写 PCA9555 跑起来

3.1 GPIO 初始化与延时函数

先把两个 IO 配好。我习惯用标准库,寄存器操作也行,这里用标准库写法更直观。SDA 和 SCL 都配成开漏输出,速度选 50MHz 够用。注意开漏模式下必须外接上拉,一般 4.7k 到 10k 都行,板子上如果没有就要自己补。

void IIC_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); IIC_SDA_H(); IIC_SCL_H(); } // 粗略延时,72MHz 下约 4us,按需调整 void IIC_Delay(void) { uint8_t i = 20; while (i--) { __NOP(); } }

延时这里给的是个经验值,实际要用示波器或逻辑分析仪看一眼 SCL 频率。没有仪器的话,可以先用保守的大延时把功能跑通,再逐步减小到通信稳定为止。我一般会留一档余量,不追求极限速率。

3.2 字节收发与应答处理

发送一个字节是高位先发,每发一位拉低 SCL,放好数据,再拉高 SCL 让从机采样。发完八位后释放 SDA,读从机的应答位。接收字节则是主机释放 SDA,从机驱动,主机在 SCL 高电平期间读取。

// 发送一个字节,返回从机应答:0 应答,1 非应答 uint8_t IIC_SendByte(uint8_t byte) { uint8_t i, ack; for (i = 0; i < 8; i++) { IIC_SCL_L(); IIC_Delay(); if (byte & 0x80) IIC_SDA_H(); else IIC_SDA_L(); byte <<= 1; IIC_Delay(); IIC_SCL_H(); IIC_Delay(); } IIC_SCL_L(); IIC_Delay(); IIC_SDA_H(); // 释放 SDA,准备读应答 IIC_Delay(); IIC_SCL_H(); IIC_Delay(); ack = IIC_SDA_READ(); // 0 表示从机应答 IIC_SCL_L(); IIC_Delay(); return ack; } // 接收一个字节,ack=0 发送应答,ack=1 发送非应答 uint8_t IIC_ReadByte(uint8_t ack) { uint8_t i, byte = 0; IIC_SDA_H(); // 主机释放 SDA for (i = 0; i < 8; i++) { IIC_SCL_L(); IIC_Delay(); IIC_SCL_H(); IIC_Delay(); byte <<= 1; if (IIC_SDA_READ()) byte |= 0x01; } IIC_SCL_L(); IIC_Delay(); if (ack) IIC_SDA_H(); // 非应答 else IIC_SDA_L(); // 应答 IIC_Delay(); IIC_SCL_H(); IIC_Delay(); IIC_SCL_L(); IIC_Delay(); IIC_SDA_H(); return byte; }

IIC_SendByte返回的应答位一定要检查。如果返回 1,说明从机没应答,常见原因是地址不对、接线松了或者上拉没接。我早期调试时就是没看应答,结果后面读出来全是 0xFF,查了半天才发现是从机地址算错了。

3.3 写 PCA9555 配置寄存器与输出寄存器

配置寄存器决定引脚方向。假设我要把 Port0 的低四位设成输出驱动继电器,高四位设成输入读按键,那 Port0 配置寄存器的值就是 0xF0。写的时候先发写命令字 0x40,再发寄存器命令字节 0x03,再发 0xF0。

#define PCA9555_ADDR_W 0x40 #define PCA9555_ADDR_R 0x41 // 写一个寄存器 void PCA9555_WriteReg(uint8_t reg, uint8_t data) { IIC_Start(); IIC_SendByte(PCA9555_ADDR_W); IIC_SendByte(reg); IIC_SendByte(data); IIC_Stop(); } // 初始化:Port0 低四位输出,高四位输入 void PCA9555_Init(void) { PCA9555_WriteReg(0x03, 0xF0); // Port0 配置 PCA9555_WriteReg(0x07, 0xFF); // Port1 全输入 PCA9555_WriteReg(0x01, 0x00); // Port0 输出全低 }

写输出寄存器就是往 0x01 写值。比如要点亮接在 P0_0 上的 LED,就写 0x01。这里要注意,输出寄存器的值只有在配置寄存器对应位为 0 时才真正驱动到引脚上,配置为输入的位写输出寄存器不影响引脚。

3.4 读 PCA9555 输入寄存器

读操作要复杂一点,先写命令字和寄存器命令字节,再重启发读命令字,然后读一个字节,最后发非应答再停止。

// 读一个寄存器 uint8_t PCA9555_ReadReg(uint8_t reg) { uint8_t data; IIC_Start(); IIC_SendByte(PCA9555_ADDR_W); IIC_SendByte(reg); IIC_Start(); // 重启 IIC_SendByte(PCA9555_ADDR_R); data = IIC_ReadByte(1); // 读一个字节,发非应答 IIC_Stop(); return data; } // 读 Port0 输入 uint8_t PCA9555_ReadPort0(void) { return PCA9555_ReadReg(0x00); }

读回来的值就是引脚当前电平。如果某个输入引脚悬空,读回来可能是随机跳变的,所以输入引脚最好有确定的上拉或下拉。我一般用内部上拉或者外部上拉,避免悬空带来的误判。

4. 模拟 IIC 访问 PCA9555 的避坑与排查

4.1 从机不应答,读回全是 0xFF

现象是发送命令字后IIC_SendByte返回 1,后续读数据全是 0xFF。原因通常是地址算错、SDA/SCL 接反或者上拉缺失。PCA9555 的 7 位地址是0100 A2 A1 A0,如果 A2A1A0 都接地,写命令字是 0x40。有人会直接把 0x20 当写命令字发,那就错了。解决方法是先用万用表确认 A2A1A0 的电平,再核对命令字,同时确认 SDA 和 SCL 没有接反,上拉电阻是否焊上。

4.2 写输出寄存器没反应

现象是往输出寄存器写了值,但引脚电平不变。原因多半是配置寄存器没设成输出。PCA9555 上电默认所有引脚为输入,配置寄存器对应位是 1。要输出必须先写配置寄存器把对应位清 0。解决方法是先写配置寄存器,再写输出寄存器,顺序不能反。另外确认写的是正确的端口,Port0 和 Port1 的寄存器地址不同。

4.3 读输入寄存器数据跳变

现象是读回来的输入值不稳定,偶尔跳变。原因是输入引脚悬空,没有确定电平。解决方法是给输入引脚加上拉或下拉,或者启用 PCA9555 的内部上拉(如果有的话,具体看型号手册)。软件上也可以在读之前多读几次取稳定值,但根本办法还是硬件上给确定电平。

4.4 通信偶尔失败,重启后恢复

现象是跑一段时间后通信失败,断电重启又好了。原因可能是总线被干扰,或者延时太短导致时序临界。解决方法是适当加大IIC_Delay的延时,降低通信速率,同时在 SDA 和 SCL 上并一个小电容滤波。另外检查电源是否稳定,PCA9555 供电波动也会导致通信异常。

4.5 多字节读写时数据错位

现象是连续读写多个寄存器时,第二个字节开始错位。原因是 PCA9555 支持地址自增,连续读写时寄存器地址会自动加一。如果你不想自增,每次操作都要重新发起始条件并发送寄存器命令字节。解决方法是明确自己的读写意图,要么利用自增连续读写,要么每次单独寻址。

5. 把模拟 IIC 封装成可复用驱动与验证方法

5.1 封装成独立驱动文件

把模拟 IIC 的底层和 PCA9555 的操作分成两个文件,底层只管起始、停止、收发字节,PCA9555 文件只管寄存器和业务逻辑。这样换一个从机,底层不用动。我一般会定义一组函数指针或者宏,方便换 IO 口。

// pca9555.h #ifndef __PCA9555_H #define __PCA9555_H #include "stm32f10x.h" #define PCA9555_ADDR_W 0x40 #define PCA9555_ADDR_R 0x41 void PCA9555_Init(void); void PCA9555_WriteReg(uint8_t reg, uint8_t data); uint8_t PCA9555_ReadReg(uint8_t reg); void PCA9555_WritePort0(uint8_t data); uint8_t PCA9555_ReadPort0(void); #endif

封装好之后,业务层只调PCA9555_WritePort0和PCA9555_ReadPort0,不用关心 IIC 时序。这样代码可读性和可维护性都好很多。

5.2 用回环测试验证时序

没有逻辑分析仪的时候,我会用一个简单的回环测试验证模拟 IIC 时序。把 PCA9555 的某个输出引脚和某个输入引脚短接,写输出再读输入,看是否一致。一致说明时序和寄存器操作都对。这个方法虽然土,但很有效,能快速定位是时序问题还是寄存器配置问题。

// 回环测试:P0_0 输出,P0_4 输入,短接 P0_0 和 P0_4 void PCA9555_LoopbackTest(void) { PCA9555_WriteReg(0x03, 0xEF); // P0_4 输入,其余输出 PCA9555_WritePort0(0x01); // P0_0 输出高 if (PCA9555_ReadPort0() & 0x10) { // P0_4 读到高,回环成功 } PCA9555_WritePort0(0x00); // P0_0 输出低 if (!(PCA9555_ReadPort0() & 0x10)) { // P0_4 读到低,回环成功 } }

这个测试能覆盖起始、停止、发送、接收和应答的完整流程,跑通了基本说明模拟 IIC 没问题。

5.3 速率与稳定性的取舍

模拟 IIC 的速率和稳定性是一对矛盾。延时越小速率越高,但越容易受干扰和主频波动影响。我一般会把延时设到通信稳定的最小值再留 20% 余量。比如稳定跑 100kHz 需要 5us 延时,我就设 6us。这样温度变化或电源波动时不容易翻车。另外,如果系统里有中断会打断 IIC 时序,最好在 IIC 操作期间关中断,或者保证中断服务程序足够短。

从那以后我每次做模拟 IIC,都会先用回环测试把时序跑通,再上真实从机,最后用逻辑分析仪看一眼波形。这个习惯帮我省了很多返工时间。希望帮到你。

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

相关新闻

智能家居语音控制系统技术拆解与商业化价值评估指南

智能家居语音控制系统技术拆解与商业化价值评估指南

智能家居语音控制系统这几年热度一直没下来&#xff0c;但大部分人讨论它时只停留在两个极端&#xff1a;要么极客视角拆解技术参数&#xff0c;要么投资视角空谈市场规模。真正把这两条线拧在一起、用价值投资的逻辑去审视一套语音控制系统的技术底子和商业前景&#xff0c;反…

2026/10/20 9:34:48 阅读更多 →
Agent Harness:面向生产落地的智能体编排与治理架构

Agent Harness:面向生产落地的智能体编排与治理架构

1. 项目概述&#xff1a;这不是一个“智能体框架”的空泛概念&#xff0c;而是一套可落地的工程化协作系统“Agent Harness架构设计与实现”——光看标题&#xff0c;很多人第一反应是又一个AI Agent技术名词堆砌。但在我过去三年深度参与多个跨团队智能体系统交付的经历中&…

2026/10/20 9:34:48 阅读更多 →
AI日报内容生成的合规边界与专业底线

AI日报内容生成的合规边界与专业底线

我无法根据当前输入生成符合要求的博文。原因如下&#xff1a;项目标题为“AI 日报&#xff08;2026年10月9日&#xff09;”&#xff0c;属于时效性极强的资讯汇总类内容&#xff0c;但项目正文为空、关键词为空、摘要描述为空&#xff0c;且未提供任何实质性的当日AI领域事件…

2026/10/20 9:34:48 阅读更多 →

最新新闻

这6个底层技能,比学一堆工具更不容易过时

这6个底层技能,比学一堆工具更不容易过时

这6个“常用技能”&#xff0c;我一开始全理解错了。当时看项目标题“分享6个最常用的skill”&#xff0c;我第一反应是准备一份技术栈清单&#xff0c;甚至把某段时间特别火的几类工具关键词都列了出来。但和朋友聊完、又翻了几次项目正文之后才发现&#xff0c;真正的核心不是…

2026/10/20 17:34:07 阅读更多 →
工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

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

2026/10/20 17:34:07 阅读更多 →
Ruby重构机票电商平台:事务、缓存与高并发实战解析

Ruby重构机票电商平台:事务、缓存与高并发实战解析

简介&#xff1a;eyoo旅游机票电商平台重构版是一份基于Ruby技术栈的在线机票销售系统学习资源&#xff0c;适合希望掌握Ruby on Rails电商项目完整开发流程的开发者&#xff0c;用于研究业务建模、数据库关联、接口设计与部署方案。压缩包大小约2.62MB&#xff0c;当前标注文件…

2026/10/20 17:34:07 阅读更多 →
AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

如果你现在手机相册里至少存了五张“学霸同款2026 TOP10 AI论文写作软件推荐图”&#xff0c;但论文还卡在“题目改了四遍都没定下来”&#xff0c;那这篇内容就是为你准备的。我不打算继续报一遍软件名字&#xff0c;因为真正决定你论文能不能顺利过关的&#xff0c;从来不是榜…

2026/10/20 17:34:07 阅读更多 →
2024最新Node.js下载安装与环境变量配置完整指南

2024最新Node.js下载安装与环境变量配置完整指南

如果你在前端、后端或者全栈开发这条路上待过一段时间&#xff0c;Node.js这个名字一定绕不开。它本质上是一个基于V8引擎的JavaScript运行时&#xff0c;把原本只能在浏览器里跑的JavaScript带到了操作系统层面。装上它之后&#xff0c;你可以用JavaScript写命令行工具、写后端…

2026/10/20 17:34:07 阅读更多 →
Ubuntu下PostgreSQL安装配置与Navicat连接指南

Ubuntu下PostgreSQL安装配置与Navicat连接指南

做后端开发或者数据相关工作的朋友&#xff0c;应该都经历过这么一幕&#xff1a;好不容易在 Ubuntu 上把 PostgreSQL 装好了&#xff0c;却发现命令行操作没问题&#xff0c;客户端工具却怎么都连不上&#xff1b;或者反过来&#xff0c;Navicat 装好了&#xff0c;连接时报一…

2026/10/20 17:33:06 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →