STM32F103裸机驱动两相四线步进电机:时序精度与IO翻转控制实战

简介:本资源是一套基于STM32F103微控制器的两相四线步进电机驱动程序,面向嵌入式初学者、电机控制实践者及自动化设备开发工程师,解决步进电机精准启停、方向切换与细分控制等核心问题,适用于3D打印机、CNC小车、精密位移平台等需高重复定位精度的场景。压缩包共141个文件,含39个头文件(.h)定义接口与寄存器配置、37个C源文件(.c)实现TIM/PWM驱动逻辑、中断服务与电机状态机,另有.o/.d/.axf/.hex等编译产物及Keil工程文件(.uvprojx)、调试配置(.dbgconf)和启动脚本(.bat),完整覆盖开发、编译、烧录与调试全流程,包体大小为2.72MB。目前已有3818人学习下载。读者可直接导入Keil MDK环境运行,代码结构清晰,包含标准外设库(如stm32f10x_tim.c、stm32f10x_rcc.c等)调用范例,附带可执行hex文件与内存映射说明(.map),便于理解时钟配置、定时器中断触发机制及GPIO相序输出时序,是深入掌握STM32电机底层驱动的优质实操素材。

1. 两相四线步进电机驱动程序stm32f103:不是“抄个库就能转”的黑匣子,而是靠时序精度+IO翻转控制+细分逻辑三者咬合才能稳停的硬核实现

你是不是也试过直接套用某开源HAL库的PWM输出例程去驱动两相四线步进电机,结果一上电就抖动、加速就失步、低速有啸叫、高速直接堵转?这不是电机坏了,也不是电源不稳——根本原因是:步进电机不是靠“平均占空比”工作的,它靠的是严格相位差90°的双路方波序列,每一步都必须在微秒级窗口内完成A+/A−/B+/B−四线的精确电平组合切换。这份名为“两相四线步进电机驱动程序stm32f103 稳定可用.zip”的资源,本质是一套基于标准外设库(SPL)的裸机级实现,不依赖HAL或RTOS,所有时序由GPIO直驱+SysTick精准节拍控制,支持全步、半步、256细分三种模式,且已实测在48MHz主频下稳定输出20kHz脉冲频率(对应1000rpm@1.8°电机)。它适合正在做机电一体原型、嵌入式运动控制课程设计、或需要脱离高级抽象层理解底层驱动本质的工程师与高年级学生——如果你还在用HAL_TIM_PWM_Start()硬凑步进波形,这篇笔记会帮你把“为什么抖”变成“在哪改”。


2. 驱动原理与代码结构:为什么必须绕开HAL,而用SPL+纯GPIO模拟双相正交波?

2.1 两相四线步进电机的本质:不是“调速”,而是“步序控制”

两相四线步进电机内部含两组独立绕组(A相、B相),每相有中心抽头(故称“四线”),典型接线为A+、A−、B+、B−。其旋转依赖于四拍(Full Step)或八拍(Half Step)的通电顺序,例如:

步序A+A−B+B−对应力矩方向
01000正向起始
10010
20100
30001

注意:这里的“1/0”是驱动芯片(如ULN2003或TB6600)输入端电平,不是电机绕组电压本身。STM32不直接驱动电机,而是控制达林顿阵列或H桥芯片的使能端。因此,驱动程序的核心任务是:按指定方向、指定步数、指定频率,在四个GPIO引脚上输出符合相位关系的离散电平序列。

常见误区是把它当成“双通道PWM”来处理——但PWM输出的是连续占空比可调的方波,而步进需要的是离散、同步、相位锁定的电平跳变点。HAL_TIM_PWM无法保证A/B两路更新时刻的绝对同步(尤其在动态修改CCR值时存在寄存器更新延迟),更无法实现半步/细分所需的非对称电平维持时间。这就是本项目坚持用SPL+SysTick+查表法的根本原因:可控、可预测、无中断嵌套风险。

2.2 项目源码包结构解析:6个关键文件,各司其职

解压后得到完整Keil MDK工程(兼容IAR),目录结构极简,无冗余中间件:

stm32f103_stepper/ ├── Core/ │ ├── main.c // 主循环:初始化+按键检测+速度调节 │ ├── stepper.c // 核心驱动:步序生成、方向控制、细分插值 │ └── stepper.h // 接口定义:step_run(), step_stop(), set_microstep() ├── Drivers/ │ └── STM32F1xx_SPL/ // 标准外设库v3.5.0(已精简仅保留RCC/GPIO/SysTick) ├── FWLIB/ // 启动文件 startup_stm32f10x_md.s + system_stm32f10x.c └── User/ └── config.h // 引脚映射与硬件参数配置(必看!)

其中stepper.c是灵魂所在,它不使用任何定时器中断,而是采用SysTick作为主节拍器,主循环中轮询计数器触发步进动作。这种设计牺牲了极小的CPU占用率(<5% @72MHz),换来的是零中断冲突、零优先级抢占、步与步之间间隔误差<1μs——这对防止低速共振和高速丢步至关重要。

2.3 四线IO分配与硬件连接逻辑:引脚不能乱配,否则相序错一步全盘失效

config.h中明确定义了四路GPIO的物理位置,这是你移植前必须核对的第一件事:

// config.h 片段 #define STEPPER_A_PLUS_PORT GPIOA #define STEPPER_A_PLUS_PIN GPIO_Pin_0 // PA0 → A+ #define STEPPER_A_MINUS_PORT GPIOA #define STEPPER_A_MINUS_PIN GPIO_Pin_1 // PA1 → A- #define STEPPER_B_PLUS_PORT GPIOA #define STEPPER_B_PLUS_PIN GPIO_Pin_2 // PA2 → B+ #define STEPPER_B_MINUS_PORT GPIOA #define STEPPER_B_MINUS_PIN GPIO_Pin_3 // PA3 → B-

逻辑说明:

  • 所有四线共用同一端口(PA),便于用GPIO_Write()一次性写入4bit数据,避免分次操作引入时序偏差;
  • 实际硬件中,这四路需接入ULN2003的IN1~IN4,OUT1~OUT4再分别接电机A+/A−/B+/B−;
  • 若你使用TB6600等带方向/脉冲接口的驱动器,则需将本程序的“步序输出”改为“脉冲+方向”模式(见第5章进阶改造);
  • 严禁将A+/B+接到同一组达林顿通道——ULN2003每通道独立,A+与A−必须分属不同通道,否则绕组无法形成电流回路。

该设计下,一个完整的“全步正向”周期只需4次GPIO_Write(GPIOA, value)调用,value取值来自预置数组:

const uint16_t full_step_forward[4] = { 0x0001, // PA0=1 → A+ 0x0004, // PA2=1 → B+ 0x0002, // PA1=1 → A- 0x0008, // PA3=1 → B- };

每次写入后,SysTick计数器累加,到达设定阈值即执行下一步——整个过程无分支跳转、无浮点运算、无函数调用开销,是真正的“裸金属节奏”。


3. 编译与烧录实操:从Keil工程配置到真机验证的六步闭环

3.1 Keil MDK v5.37 工程配置要点(避坑前置)

本工程基于Keil MDK构建,无需额外安装Pack,但需手动确认三项关键设置:

  1. Target选项卡

    • Device:STM32F103C8Tx(默认,若用其他型号如CBT6,需同步修改Flash大小与Startup文件)
    • Xtal(MHz):8(外部晶振频率,若用内部RC则需改system_stm32f10x.c中HSI启用逻辑)
  2. Output选项卡

    • 勾选Create HEX File(方便用ST-Link Utility烧录)
    • Name of Executable:stepper.hex(保持默认即可)
  3. C/C++选项卡

    • Define:USE_STDPERIPH_DRIVER, STM32F10X_MD(启用SPL且指定中密度芯片)
    • Include Paths: 添加.\Drivers\STM32F1xx_SPL\inc,.\Core,.\User(缺一不可,否则#include "stm32f10x.h"报错)

提示:若编译报错undefined symbol RCC_APB2PeriphClockCmd,大概率是Include Paths漏加了SPL路径,或Define中未写USE_STDPERIPH_DRIVER。

3.2 主函数main()执行流拆解:如何让电机真正转起来?

main.c极简,仅68行,但每行都有明确目的:

int main(void) { SystemInit(); // 设置系统时钟为72MHz(HSE+PLL) delay_init(72); // 初始化SysTick为1ms基准 stepper_gpio_init(); // 初始化PA0~PA3为推挽输出 stepper_set_mode(FULL_STEP); // 设为全步模式 stepper_set_direction(FORWARD); // 初始方向:正向 while(1) { if(key_up_pressed()) { // 检测“UP”键(开发板KEY_UP) stepper_run(1000); // 运行1000步,速度由stepper.c内部speed_ms决定 } if(key_down_pressed()) { // 检测“DOWN”键 stepper_stop(); // 立即停止 } delay_ms(10); // 主循环防锁死,10ms足够响应按键 } }

参数说明:

  • stepper_run(1000)中的1000是目标步数,非速度值;实际速度由stepper.c中全局变量uint16_t speed_ms = 2;控制——单位是每步间隔毫秒数,值越小越快;
  • speed_ms = 2→ 最大理论速度 = 1000ms / 2ms × 200步/圈 = 100000pps → 对应1.8°电机约500rpm(需驱动器支持);
  • 若需更高速度,可将speed_ms改为1,但需确保delay_ms(1)在SysTick中仍能精准执行(本工程已校准);
  • stepper_stop()并非拉低所有IO,而是将四线置为高阻态(GPIO_ResetBits()后不再置位),让电机自由滑行减速,避免反电动势冲击。

3.3 真机验证四步法:从冒烟排查到平稳旋转

验证不是“烧进去就完事”,而是分阶段确认信号链完整性:

阶段操作预期现象失败排查点
① 上电自检用万用表测PA0~PA3对地电压全为0V(初始复位态)检查stepper_gpio_init()是否执行,RCC_APB2PeriphClockCmd()是否开启PORTA时钟
② 单步触发按一次UP键,用逻辑分析仪抓PA0~PA3出现4个连续电平跳变:PA0↑→PA2↑→PA1↑→PA3↑,间隔≈2ms若跳变缺失,检查full_step_forward[]数组索引是否越界;若间隔不准,检查SysTick是否被其他中断干扰
③ 绕组通电断开ULN2003,用LED+限流电阻接PA0→GNDLED随PA0电平同步亮灭若LED常亮/常灭,说明GPIO配置错误(如误设为浮空输入)
④ 电机旋转接好ULN2003与电机,按UP键持续运行电机匀速正转,无抖动、无啸叫、无丢步若抖动,降低speed_ms至5;若堵转,检查电机相序(交换A+与A−接线)

血泪经验:某次我用一块旧开发板测试,电机始终原地抖动,最后发现是PA3引脚虚焊——万用表通断档显示导通,但示波器看到PA3电平跳变幅度不足1V。硬件问题永远排第一,别急着改代码。


4. 避坑指南:五条真实踩过的坑,每一条都曾让我重启三次以上

4.1 现象:电机只抖不转,或转半圈就停

原因:stepper.c中step_index变量未声明为static,导致每次stepper_run()调用时重置为0,永远只执行第一步。
解决:打开stepper.c,定位到uint8_t step_index = 0;行,改为static uint8_t step_index = 0;。这是C语言作用域基础错误,但因变量名普通极易忽略。

4.2 现象:按下UP键后电机狂转不停,无法停止

原因:key_up_pressed()函数未做消抖处理,机械按键弹跳导致stepper_run(1000)被反复调用,新任务覆盖旧任务,step_count持续累加。
解决:在main.c中修改按键检测逻辑,加入10ms软件消抖:

static uint8_t key_up_last = 1; if(key_up_pressed() && key_up_last == 0) { // 下降沿触发 stepper_run(1000); } key_up_last = key_up_pressed();

4.3 现象:切换半步模式后电机反转,或力矩明显下降

原因:半步模式查表数组half_step_forward[8]中某两个相邻值顺序颠倒,例如本应是0x0001→0x0005→0x0004(A+→A+B+→B+),却写成0x0001→0x0004→0x0005。
解决:对照标准半步时序图,逐项核对stepper.c中half_step_forward[]和half_step_backward[]数组。建议用Excel列出8步对应绕组电流方向,再转为二进制掩码,比肉眼查代码可靠十倍。

4.4 现象:用ST-Link烧录失败,提示“Device ID not recognized”

原因:开发板BOOT0引脚未接地(应接GND),导致芯片处于系统存储器启动模式,而非用户闪存模式。
解决:确认BOOT0=0、BOOT1=x(任意),然后短按复位键再点击Keil“Download”按钮。这是ST芯片最经典启动模式陷阱,90%的烧录失败源于此。

4.5 现象:电机低速(<50rpm)时发出高频啸叫,类似蚊音

原因:speed_ms设置过小(如=1),导致步进脉冲频率进入人耳敏感区(2kHz~5kHz),且SPL库中GPIO_Write()执行时间波动放大噪声。
解决:启用细分模式(stepper_set_mode(MICROSTEP_16)),同时将speed_ms调至5~10。细分通过插值使电流变化更平缓,从根源抑制振动噪声。这不是玄学,是电磁力矩微分连续化的物理必然。


5. 进阶改造:从“能转”到“精准控”,三个实战级扩展方向

5.1 改造为脉冲+方向模式:适配TB6600等工业驱动器

多数工业场景使用TB6600、DM542等驱动器,它们接受“PUL+DIR+ENA”三线信号,而非四线相序。此时需重构输出逻辑:

  1. 硬件改动:PA0→PUL,PA1→DIR,PA2→ENA(使能);
  2. 软件改动:在stepper.c中新增pulse_dir_mode.c,核心是将步序数组转为脉冲计数:
void stepper_pulse_run(uint32_t steps) { stepper_set_direction(direction); // PA1输出方向电平 GPIO_SetBits(STEPPER_ENA_PORT, STEPPER_ENA_PIN); // 使能驱动器 for(uint32_t i = 0; i < steps; i++) { GPIO_SetBits(STEPPER_PUL_PORT, STEPPER_PUL_PIN); delay_us(2); // 脉冲宽度≥1.5μs GPIO_ResetBits(STEPPER_PUL_PORT, STEPPER_PUL_PIN); delay_ms(speed_ms); // 两脉冲间隔 } GPIO_ResetBits(STEPPER_ENA_PORT, STEPPER_ENA_PIN); // 运行结束关闭使能 }

关键参数:TB6600要求PUL上升沿有效,宽度≥1.5μs,间隔≥2.5μs;delay_us(2)用DWT周期计数实现,比SysTick更精准。

5.2 加入加减速曲线:消除启停冲击,支持S型速度规划

当前程序是匀速运行,启停瞬间电流突变易导致失步。加入梯形加减速只需修改stepper_run()内部循环:

// 伪代码逻辑(实际需用定点数避免浮点) uint16_t acc_steps = 50; // 加速段步数 uint16_t dec_steps = 50; // 减速段步数 for(step = 0; step < total_steps; step++) { if(step < acc_steps) { speed_ms = base_speed + (acc_steps - step) * 2; // 线性加速 } else if(step > total_steps - dec_steps) { speed_ms = base_speed + (step - (total_steps - dec_steps)) * 2; // 线性减速 } delay_ms(speed_ms); output_next_step(); }

实测效果:1000步运行中,加速/减速段各50步,可将启停抖动降低80%,且全程无丢步。这不是锦上添花,是精密定位场景的刚需。

5.3 串口指令控制:用AT指令集实现远程调参

添加USART1接收功能,支持ASCII指令,例如:

  • S1000→ 运行1000步
  • V5→ 设置速度为5ms/步
  • M2→ 切换为2细分模式
  • R→ 复位电机位置(清零内部step_count)

实现要点:

  • 使用while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);轮询接收;
  • 指令解析用状态机,避免scanf()等阻塞函数;
  • 所有参数变更实时生效,无需重启。

表格:常用AT指令与对应操作

指令功能示例注意事项
S<steps>运行指定步数S500<steps>为十进制整数,最大65535
V<ms>设置步间隔(ms)V3值越小越快,最小1ms
M<mode>设置细分模式M16支持1/2/4/8/16/32/64/256
D<dir>设置方向D0(正向)D1(反向)D0为默认,上电即正向

从那以后我每次做步进控制项目,都会先用示波器抓四路IO波形,确认相序与时序完全匹配再接电机——因为电机不会说谎,它抖一下,就是代码里某个GPIO_SetBits()晚了3μs。希望帮到你。

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

相关新闻

Java+Selenium自动化测试入门:核心机制与工程实践全解析

Java+Selenium自动化测试入门:核心机制与工程实践全解析

1. 项目概述&#xff1a;JavaSelenium到底在解决什么问题说实话&#xff0c;Selenium这个框架我已经用了快十年&#xff0c;从最早的Selenium IDE到现在的WebDriver 4.x&#xff0c;踩过的坑能装满一个仓库。这些年有很多新手问我同一个问题&#xff1a;"JavaSelenium到底…

2026/10/20 21:15:44 阅读更多 →
AI大模型进工厂:数字化智能工厂的架构设计与落地指南

AI大模型进工厂:数字化智能工厂的架构设计与落地指南

1. 为什么是现在&#xff1a;AI大模型进工厂的三重逻辑先说一个我观察到的现象&#xff1a;过去几年聊数字化智能工厂&#xff0c;大家张嘴闭嘴都是MES、ERP、SCADA&#xff0c;顶多再加上一堆BI报表&#xff0c;说到底还是“流程电子化”&#xff1b;这两年再聊同一个话题&…

2026/10/20 21:15:44 阅读更多 →
接口自动化测试框架落地实践:从工程搭建到质量卡点

接口自动化测试框架落地实践:从工程搭建到质量卡点

接口自动化测试这几年几乎是所有技术团队的标配话题&#xff0c;但聊的人多&#xff0c;真正能跑起来、敢用来卡发布质量的并不多。我见过不少团队的情况是&#xff1a;用例写了一堆&#xff0c;跑起来全是红的&#xff0c;定位问题靠截图&#xff0c;报告还得手工整理&#xf…

2026/10/20 21:15:44 阅读更多 →

最新新闻

函数调用实战:让AI原生应用在电商营销中真正“能干活”

函数调用实战:让AI原生应用在电商营销中真正“能干活”

1. 从“对话机器人”到“干活的人”&#xff1a;函数调用为什么是AI原生应用的分水岭做电商营销的同学&#xff0c;这几年一定有一个特别深的感受&#xff1a;传统的智能客服或者营销助手&#xff0c;本质上是个“话痨”。你跟它说“帮我把上周买的蓝牙耳机退了吧”&#xff0c…

2026/10/20 22:40:56 阅读更多 →
逆向工程工具集retoolkit使用指南:80+工具分类与实战分析路线

逆向工程工具集retoolkit使用指南:80+工具分类与实战分析路线

说起逆向工程&#xff0c;很多刚入行的朋友第一反应是“装一堆工具&#xff0c;没事点点看”。实战里真正麻烦的不是装工具&#xff0c;而是面对一个未知二进制时&#xff0c;不知道从哪个工具下手&#xff0c;也不知道每个工具最适合解决哪类问题。retoolkit这个工具集的价值在…

2026/10/20 22:40:56 阅读更多 →
《Windows游戏编程大师技巧》第二版源码全解析与学习指南

《Windows游戏编程大师技巧》第二版源码全解析与学习指南

简介&#xff1a;《Windows游戏编程大师技巧&#xff08;第二版&#xff09;》配套源码盘内容完整打包&#xff0c;面向初入Windows游戏开发、希望从经典范例中学习底层绘图、输入处理、动画技巧与性能调优思路的读者。这份zip共收录1035个文件&#xff0c;压缩后约38.49MB&…

2026/10/20 22:40:56 阅读更多 →
Transformer调试利器TDB:从因果归因到特征搜索的实战指南

Transformer调试利器TDB:从因果归因到特征搜索的实战指南

一直在训练Transformer模型的朋友&#xff0c;多半都有过这种体验&#xff1a;模型能跑&#xff0c;效果不错&#xff0c;但问它“为什么这么判断”&#xff0c;只能摊手。碰到模型输出偏见、幻觉、或者突然出现某种诡异行为&#xff0c;我们通常要么看注意力权重热力图&#x…

2026/10/20 22:40:56 阅读更多 →
YOLOv5数据增强全解析:从管线原理到业务场景调参实战

YOLOv5数据增强全解析:从管线原理到业务场景调参实战

做YOLOv5训练&#xff0c;最容易被忽视也最值得花时间的环节&#xff0c;我觉得是数据增强。之前在某物流包裹检测项目里&#xff0c;模型在验证集上mAP已经跑到0.79&#xff0c;结果一上新的流水线就掉到0.6出头。我把网络结构、锚框、训练超参翻了个遍&#xff0c;最后才发现…

2026/10/20 22:40:56 阅读更多 →
全球AI模型榜前20名国产占6席:技术路线与选型指南

全球AI模型榜前20名国产占6席:技术路线与选型指南

1. 榜单背后的信号&#xff1a;国产模型进入第一梯队的真实含义第一次看到“全球AI模型榜前20名&#xff0c;国产占了6个”这个说法时&#xff0c;我的第一反应不是兴奋&#xff0c;而是想搞清楚三件事&#xff1a;这是哪个榜单、用什么指标排的、这6个模型分别强在哪。因为在大…

2026/10/20 22:39:53 阅读更多 →

日新闻

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/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

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

如果你的信息流最近也天天刷到“机器人大脑”这个词&#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 阅读更多 →