STM32F103 CAN通信实战:从位定时计算到滤波器配置的避坑指南
简介这份资源面向嵌入式开发初学者与STM32工程师聚焦STM32F103系列微控制器的CAN总线通信实现适用于汽车电子、工业自动化及物联网等需要多节点可靠通信的场景。压缩包共206个文件约4.73MB以C源码、头文件、编译中间文件及Keil工程配置为主涵盖CAN外设初始化、滤波器设置、收发函数与错误管理等核心模块并附带LCD、定时器、Flash、RCC等外设驱动便于在完整工程中理解CAN通信的集成方式。资源围绕CAN控制器与收发器的硬件连接、标准ID与扩展ID帧格式、波特率配置、中断收发及错误状态处理展开读者可据此掌握HAL_CAN_Transmit与HAL_CAN_GetRxMessage等关键接口的使用并参考工程目录结构快速搭建可运行的CAN通信实验。目前已有1909人学习下载适合需要从零实现STM32F103 CAN通信、排查总线异常或完善嵌入式通信方案的开发者参考。1. stm32f103can通信从点灯到总线一个让新手翻车的分水岭很多人第一次接触 stm32f103can通信都是被“CAN 比串口高级”这句话带进来的。我当年也是串口收发跑通了觉得总线不过如此结果接上收发器、写了两行发送代码示波器上连个毛刺都没有。问题不在代码在于 CAN 不是“你发我就收”的透明管道它是一套带仲裁、带位定时、带错误帧的差分总线协议。STM32F103 的 bxCAN 外设把协议层几乎全包了但前提是你得把 GPIO 重映射、波特率分频、滤波器、终端电阻这几件事同时做对。这篇笔记面向已经能跑通 GPIO 和串口、准备把两块 F103 板子用 CAN 连起来的工程师我会把标准库和 HAL 两条路都拆开讲参数怎么算、坑在哪、怎么用回环模式先自检全部落到可复现的命令和代码上。2. 先把物理层和位定时算清楚CAN 不通八成卡在这2.1 差分线、120 欧终端电阻和共地一个都不能少CAN 的物理层是差分信号CAN_H 和 CAN_L 之间的电压差决定显性位和隐性位。显性位逻辑 0压差约 2V隐性位逻辑 1压差约 0V。这意味着两件事第一总线上任意一个节点发显性位就能覆盖隐性位这是仲裁的物理基础第二如果 CAN_H 和 CAN_L 接反或者终端电阻缺失差分电压根本建立不起来收发器不会输出有效电平。我一般会先拿万用表量三样东西CAN_H 对 CAN_L 的静态电阻两个 120 欧并联后应该是 60 欧左右CAN_H 对地、CAN_L 对地的静态电压收发器正常工作时都在 2.5V 附近两块板子的 GND 必须连在一起否则共模电压漂到收发器承受范围之外通信时好时坏这种玄学问题最耗时间。终端电阻只在总线两端各放一个中间节点不要放。很多开发板已经把 120 欧焊在板上了如果你再外接一个总线负载变成 40 欧波形幅度被拉低短距离可能还能跑长距离直接丢帧。常见做法是两块板点对点通信两端各一个 120 欧三块以上只有物理最远的两端放。2.2 位定时参数怎么算以 500kbps 为例手算一遍STM32F103 的 bxCAN 挂在 APB1 上默认 36MHz。位定时由三段组成同步段SYNC_SEG固定 1Tq、时间段 1BS1、时间段 2BS2。采样点落在 BS1 结束处。波特率 1 / (Tq × (1 BS1 BS2))其中 Tq (BRP) / 36MHz。目标 500kbps周期 2us。取 BRP4则 Tq 4/36MHz ≈ 111.1ns。需要总 Tq 数 2us / 111.1ns ≈ 18。于是 1 BS1 BS2 18取 BS115BS22采样点 (115)/18 ≈ 88.9%这是 CAN 推荐的采样点位置75%~87.5% 之间偏上。对应到代码里标准库的配置如下// 标准库CAN 位定时配置APB136MHz目标 500kbps CAN_InitTypeDef CAN_InitStructure; CAN_InitStructure.CAN_TTCM DISABLE; // 关闭时间触发 CAN_InitStructure.CAN_ABOM ENABLE; // 自动离线恢复调试期建议开 CAN_InitStructure.CAN_AWUM DISABLE; // 自动唤醒关闭 CAN_InitStructure.CAN_NART DISABLE; // 禁止自动重传关闭失败会重发 CAN_InitStructure.CAN_RFLM DISABLE; // FIFO 不锁定溢出覆盖 CAN_InitStructure.CAN_TXFP DISABLE; // 发送优先级由标识符决定 CAN_InitStructure.CAN_Mode CAN_Mode_Normal; CAN_InitStructure.CAN_SJW CAN_SJW_1tq; // 同步跳转宽度 1Tq CAN_InitStructure.CAN_BS1 CAN_BS1_15tq; // 时间段1 15Tq CAN_InitStructure.CAN_BS2 CAN_BS2_2tq; // 时间段2 2Tq CAN_InitStructure.CAN_Prescaler 4; // 分频系数 4 CAN_Init(CAN1, CAN_InitStructure);逻辑说明SJW 取 1Tq 是为了在时钟偏差不大时保持稳定如果两个节点晶振精度差可以加到 2Tq 或 3Tq。BS1 和 BS2 的比例决定了采样点BS1 越大采样点越靠后对长线缆的延迟容忍更好但太小会压缩相位缓冲。Prescaler 就是 BRP改这个值直接改波特率但改完必须重新算 BS1/BS2不能只动一个。HAL 库的写法更直观用CAN_Init里的Prescaler、TimeSeg1、TimeSeg2、SyncJumpWidth四个字段含义完全一样。注意 HAL 里TimeSeg1对应的是 BS1不包含同步段别多算一个 Tq。2.3 回环模式先自检别一上来就接总线新画的板子或者新写的驱动我强烈建议先跑回环模式Loopback。bxCAN 支持静默回环和正常回环回环模式下发送的帧不经过收发器直接在内部被接收用来验证滤波器、FIFO、中断配置是否正确。如果回环都收不到问题一定在软件回环能收接上总线收不到再去查物理层。// 回环模式初始化用于软件自检 CAN_InitStructure.CAN_Mode CAN_Mode_LoopBack; CAN_Init(CAN1, CAN_InitStructure); // 发送一帧标准数据帧标识符 0x123数据长度 8 CanTxMsg TxMessage; TxMessage.StdId 0x123; TxMessage.ExtId 0; TxMessage.IDE CAN_Id_Standard; TxMessage.RTR CAN_RTR_Data; TxMessage.DLC 8; for (uint8_t i 0; i 8; i) { TxMessage.Data[i] i; // 填充 0~7 便于比对 } uint8_t mailbox CAN_Transmit(CAN1, TxMessage); // 等待发送完成超时退出避免死等 uint32_t timeout 0xFFFFF; while (CAN_TransmitStatus(CAN1, mailbox) ! CAN_TxStatus_Ok timeout--);这段代码里CAN_Transmit返回的是邮箱编号0~2不是成功失败。必须用CAN_TransmitStatus查状态或者等CAN_IT_TME中断。timeout递减是防止硬件异常时卡死实际项目里我会用定时器做超时。回环模式下如果接收中断能进且数据对得上说明 bxCAN 的收发路径是通的。3. 滤波器、FIFO 和中断让接收端只拿你想要的那几帧3.1 滤波器组怎么配掩码模式和列表模式的选择STM32F103 有 14 个滤波器组互联型是 28 个每个组可以配成 32 位或 16 位。32 位掩码模式最常用一个寄存器放标识符一个放掩码掩码位为 1 表示该位必须匹配为 0 表示不关心。比如我只想收标准帧 ID 0x123掩码全 1就是精确匹配如果想收 0x120~0x12F掩码低 4 位设 0其余设 1。// 滤波器 032 位掩码模式只接收标准帧 ID 0x123 CAN_FilterInitTypeDef CAN_FilterInitStructure; CAN_FilterInitStructure.CAN_FilterNumber 0; CAN_FilterInitStructure.CAN_FilterMode CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh 0x123 5; // 标准帧 ID 左移 5 位 CAN_FilterInitStructure.CAN_FilterIdLow 0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh 0xFFFF; // 高 16 位全匹配 CAN_FilterInitStructure.CAN_FilterMaskIdLow 0x0000; // 低 16 位不关心 CAN_FilterInitStructure.CAN_FilterFIFOAssignment CAN_Filter_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation ENABLE; CAN_FilterInit(CAN_FilterInitStructure);关键点标准帧的 11 位 ID 在过滤器里是左对齐的CAN_FilterIdHigh的高 11 位才是 ID所以必须左移 5 位。这一点手册里写得清楚但很多人第一次配完发现收不到就是忘了移位。掩码的对应关系是FilterIdHigh和FilterMaskIdHigh逐位对应掩码为 1 的位参与比较。列表模式适合需要精确接收多个不连续 ID 的场景但会消耗更多滤波器组。如果 ID 数量少且固定列表模式更省 CPU如果是一段连续 ID掩码模式更划算。3.2 FIFO0 和 FIFO1 的分流策略bxCAN 有两个接收 FIFO每个 3 级深度。滤波器可以指定把匹配的帧丢进 FIFO0 还是 FIFO1。我一般把高优先级、需要快速响应的 ID 放 FIFO0用更高抢占优先级的中断处理低优先级、可以批量处理的放 FIFO1。这样避免低优先级帧把 FIFO 占满导致高优先级帧丢失。FIFO 溢出是个隐蔽的坑如果中断没及时取走第 4 帧进来时 FIFO 溢出CAN_RF0R的FOVR0位会置 1但默认不报错只是新帧被丢弃。调试期我会在中断里读一下溢出标志确认没有静默丢帧。// FIFO0 接收中断处理读取一帧并打印 void USB_LP_CAN1_RX0_IRQHandler(void) { CanRxMsg RxMessage; if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) ! RESET) { CAN_Receive(CAN1, CAN_FIFO0, RxMessage); // 检查是否溢出溢出说明中断响应太慢 if (CAN_GetFlagStatus(CAN1, CAN_FLAG_FOV0) ! RESET) { CAN_ClearFlag(CAN1, CAN_FLAG_FOV0); } // RxMessage.StdId / Data[0..DLC-1] 可用 } CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0); }中断向量名取决于芯片型号和启动文件F103 通常是USB_LP_CAN1_RX0_IRQHandler。如果编译报未定义去启动文件里搜CAN1_RX0确认。CAN_Receive会同时清掉 FMP0 标志但保险起见再清一次中断挂起位。3.3 发送优先级和邮箱占用三个发送邮箱优先级由标识符数值决定数值越小优先级越高。如果三个邮箱都满CAN_Transmit会返回CAN_TxStatus_NoMailBox。我一般会在发送前检查返回值如果没邮箱就等一个发送完成中断再重试而不是死循环。// 带邮箱检查的发送函数 uint8_t CAN_SendStd(uint16_t std_id, uint8_t *data, uint8_t len) { CanTxMsg tx; tx.StdId std_id; tx.IDE CAN_Id_Standard; tx.RTR CAN_RTR_Data; tx.DLC len; for (uint8_t i 0; i len; i) tx.Data[i] data[i]; uint8_t mb CAN_Transmit(CAN1, tx); if (mb CAN_TxStatus_NoMailBox) { return 1; // 无空闲邮箱调用者稍后重试 } return 0; }参数说明len最大 8超过 8 会被截断或触发错误。标准帧 ID 范围 0x000~0x7FF扩展帧 0x00000000~0x1FFFFFFF。如果传了超出范围的值bxCAN 不会自动截断可能发出意外 ID所以调用前自己 clamp 一下。4. 避坑与排查CAN 不通时我按这个顺序查4.1 现象发送成功但接收端毫无反应原因最常见的是终端电阻缺失或 CAN_H/CAN_L 接反。其次是波特率不匹配两个节点一个 500k 一个 250k仲裁阶段就出错。还有一种情况是滤波器把所有帧都过滤掉了接收端 FIFO 始终为空。解决先用示波器看 CAN_H 和 CAN_L 的差分波形正常发送时应该有明显的显性位脉冲。如果没有波形查收发器供电和使能引脚有些收发器有 STB 或 EN 脚低电平才工作。如果有波形但接收不到把滤波器临时改成全通过掩码全 0确认是不是滤波问题。波特率用回环模式自测回环能通说明位定时算对了。4.2 现象通信一段时间后突然全部报错总线瘫痪原因某个节点进入错误被动或总线关闭状态持续发错误帧。常见诱因是某个节点晶振偏差太大或者总线某段接线松动导致反射严重。CAN_ABOM没开的话节点进入离线后不会自动恢复。解决初始化时把CAN_ABOM置 ENABLE让硬件在检测到 128 次连续 11 个隐性位后自动恢复。同时检查各节点晶振CAN 对时钟精度要求比串口高陶瓷谐振器往往不够要用晶振。总线分支尽量短星形拓扑在 CAN 里是大忌。4.3 现象回环模式正常一接总线就进不了接收中断原因GPIO 重映射没做或者重映射后没使能 AFIO 时钟。F103 的 CAN 默认引脚是 PA11/PA12重映射到 PB8/PB9 需要开 AFIO 时钟并配置GPIO_PinRemapConfig。另一个可能是收发器的 TX/RX 和 MCU 的 CAN_TX/CAN_RX 交叉接错TX 必须接 TXRX 接 RX不能像串口那样交叉。解决确认RCC_APB2Periph_AFIO时钟已开重映射配置在 GPIO 初始化之前。用万用表通断档查 MCU 的 CAN_TX 到收发器 TXD 是否直连。如果用的是带隔离的收发器模块还要确认隔离侧供电是否正常。4.4 现象中断里读到的数据长度对但内容错位原因CAN_Receive之后没有及时取走数据FIFO 里下一帧覆盖了当前帧的缓冲区。或者发送端 DLC 设了 8但实际只填了 4 个字节接收端按 8 字节读后 4 字节是上一次的残留。解决接收中断里先把数据拷到自己的缓冲区再清中断。发送端严格按实际数据长度设 DLC不要图省事固定 8。如果数据本身有结构体注意字节对齐和大小端CAN 传输的是原始字节流没有类型信息。4.5 现象两个节点单独通信正常三个以上就随机丢帧原因总线负载过高或者某个节点发送过于频繁仲裁失败后不断重试把总线占满。CAN 没有重传次数上限NART关闭时失败就无限重发低优先级帧可能永远发不出去。解决算一下总线负载率500kbps 下每帧约 108 位标准帧含填充如果每秒发 1000 帧负载约 21.6%还算安全超过 50% 就要考虑降频或分批。调试期可以临时开NART禁止自动重传让发送失败快速返回暴露问题而不是掩盖问题。5. 进阶用 CAN 做固件升级和双机冗余的实操要点CAN 除了传传感器数据还能做固件升级IAP和双机冗余。IAP 的思路是Bootloader 常驻通过 CAN 接收固件包写入 Flash 的应用区校验通过后跳转。关键点是 Flash 分页要和 F103 的页大小对齐中容量 1KB/页大容量 2KB/页擦除前先解锁写入时按半字16 位编程。// CAN IAP 写入一帧固件数据到 Flash // 假设应用区起始 0x08004000数据已按 2 字节对齐 uint8_t flash_write(uint32_t addr, uint8_t *data, uint16_t len) { FLASH_Unlock(); for (uint16_t i 0; i len; i 2) { uint16_t half data[i] | (data[i1] 8); if (FLASH_ProgramHalfWord(addr i, half) ! FLASH_COMPLETE) { FLASH_Lock(); return 1; // 写入失败 } } FLASH_Lock(); return 0; }参数说明addr必须是 2 的倍数且落在应用区范围内。写入前该页必须已擦除F103 的 Flash 只能把 1 写成 0不能把 0 写回 1。固件包建议加 CRC32 校验收完整个包再跳转避免半包变砖。跳转前关掉所有中断和外设设置 MSP 和复位向量。双机冗余则是两个节点互发心跳帧标识符固定周期比如 100ms。如果连续 3 个周期收不到对方心跳判定对方离线接管关键输出。这里要注意心跳帧的优先级要设高避免被大数据帧阻塞。我一般把心跳 ID 设成 0x000数值最小仲裁必赢。最后说一个我踩过的坑调试 CAN 时不要开着NART又开着回环模式跑压力测试发送失败不重传回环 FIFO 又满最后现象是“发送成功但接收不到”查了半天才发现是邮箱和 FIFO 同时溢出。现在的习惯是任何 CAN 工程先跑通回环再跑通点对点最后上多节点每一步都用示波器和溢出标志确认不跳步。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Activiti流程删除的三种场景与安全实践

Activiti流程删除的三种场景与安全实践

1. 项目概述:为什么“删除流程”在Activiti中是个高频但高危操作Activiti的删除流程,这个标题看似简单,实则踩中了工作流引擎落地中最常被低估、最易出事故的核心环节。我带过三个不同行业的流程系统重构项目,从某高校教务审批系统…

2026/10/16 19:16:09 阅读更多 →
VCU开发源码+原理图+说明书:嵌入式汽车电子最小可信基线

VCU开发源码+原理图+说明书:嵌入式汽车电子最小可信基线

简介:本资源为电动汽车整车控制器(VCU)全栈开发套件,面向嵌入式工程师、新能源汽车控制系统开发者及高校相关专业高年级学生,解决VCU软硬件协同设计、CAN通信实现、电机与电池协同控制等核心工程问题。压缩包共477个文…

2026/10/16 19:16:09 阅读更多 →
开源AI基础设施全景拆解:从算力调度到MLOps落地

开源AI基础设施全景拆解:从算力调度到MLOps落地

最近开源圈子里最热的话题之一,就是年度开源大会上AI基础设施开源论坛的完整议程正式放了出来。看到这份议程的时候,我第一反应是:AI基建这个领域,终于从“概念热”进入到“工程化落地”的阶段了。整个议程几乎把当前AI基础设施的…

2026/10/16 19:16:09 阅读更多 →

最新新闻

实测 3 套 2026 人才盘点方案,踩坑后锁定轻量化玩法

实测 3 套 2026 人才盘点方案,踩坑后锁定轻量化玩法

一、为什么你的人才盘点总是做完就废据HR科技行业调研数据显示,截至2026年初,国内1000人以上规模企业中,仍有超过73%的人才盘点工作依赖Excel表格、PowerPoint汇报和线下评议会完成,盘点周期平均为6到12个月一次。真正的问题不是盘…

2026/10/16 20:27:56 阅读更多 →
杭州汉服写真不踩雷!4 家实测推荐 + 西湖避坑指南

杭州汉服写真不踩雷!4 家实测推荐 + 西湖避坑指南

杭州汉服写真不踩雷!4 家实测推荐 西湖避坑指南来杭州不拍一组西湖古风汉服写真?那真的白来啦! 柳浪闻莺的烟柳、集贤亭的落日、德寿宫的红墙、胡雪岩故居的古建…… 江南的亭台楼阁配一身汉服,随手一拍都是穿越感大片。但西湖周…

2026/10/16 20:27:56 阅读更多 →
从材质到温控,四个维度帮你选对“冲奶搭档”

从材质到温控,四个维度帮你选对“冲奶搭档”

深夜三点,宝宝哭了。你摸黑爬起来,一手抱娃一手试水温,滴在手背上——太烫,兑点凉水;再试——又凉了。等水温终于“差不多”的时候,宝宝已经哭得嗓子都哑了。这个场景,几乎是每一位新手爸妈的共…

2026/10/16 20:27:56 阅读更多 →
美多集成灶全国售后服务热线电话|24小时人工客服正式上线发布

美多集成灶全国售后服务热线电话|24小时人工客服正式上线发布

为保障消费者合法权益、规范全系列集成灶设备的全国统一服务标准,美多集成灶运营方正式发布公告:品牌全国统一官方售后服务热线 400-9983909,将于 2026 年 10 月起全面上线启用。该官方热线专属服务于美多全系集成灶设备,覆盖经典…

2026/10/16 20:27:56 阅读更多 →
1×1与3×3卷积的“两步走”设计:从瓶颈结构到深度可分离卷积

1×1与3×3卷积的“两步走”设计:从瓶颈结构到深度可分离卷积

做卷积网络的人,十有八九都用过 11 和 33 这两种卷积核,但真正把它们放在一起推敲过设计逻辑的,其实不多。很多人知道 11 能降维、33 能提取空间特征,却说不清楚为什么成熟的网络里总是“11 → 33 → 11”这种结构反复出现。这篇文…

2026/10/16 20:27:56 阅读更多 →
单VLM智能体驱动机械臂操作:设计与落地的完整拆解

单VLM智能体驱动机械臂操作:设计与落地的完整拆解

做机器人操作的人都有一个共同的感受:传统控制链路太长太脆。以前做一个“让机械臂把红色方块放到蓝色盒子里”的任务,你得串联目标检测、位姿估计、运动规划、抓取策略、异常处理,一路下来光是调参就能耗掉一周,换个工件颜色可能…

2026/10/16 20:26:55 阅读更多 →

日新闻

个人 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 阅读更多 →