STM32 互补PWM波形死区不对?用 TaoToken 接 Codex 对着 TIM1 死区参数排查
一、STM32 互补 PWM 死区排查为什么逻辑分析仪里 CH1N 没波形在 Keil 软件仿真里用逻辑分析仪看 TIM1 互补 PWM是 STM32 高级定时器调试里很典型的一类场景。CubeMX 里预分频 71、自动重载 99算下来周期 0.1ms死区先设 0 再改成 10 重新生成工程按键外部中断里把TIM1-CCR1从 50 切到 80 看占空比变化——流程本身不复杂但实际跑起来经常遇到三类卡点死区时间设得比占空比还大互补通道直接出不来波形芯片外部晶振没按 8MHz 填仿真周期和设定值对不上只调了HAL_TIM_PWM_Start忘了HAL_TIMEx_PWMN_StartCH1N 一直没输出。这类问题单靠翻参考手册效率不高因为寄存器位定义、CubeMX 生成代码、HAL 库调用三层信息要交叉核对。本文用 TaoToken官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 接入 Codex把MyInit.c里的启动代码、CallBack.c里HAL_GPIO_EXTI_Callback的占空比判断逻辑以及逻辑分析仪截图一起交给它逐项核对重点对照 TIM1 的 Prescaler/ARR/DeadTime 与 CCR1 的比较逻辑并检查是否漏调互补输出启动函数。下面按排查顺序展开。二、TaoToken 前置注册、创建 Key、在 Codex 里填 Base URLTaoToken 在这里的角色是给 Codex 提供一个可用的模型通道让排查过程能直接对着代码和配置问。前置动作只有两步第一步打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号进入控制台创建一把 API Key。Key 只在创建时完整显示一次复制后先存到本地临时文件里。第二步在 Codex 的配置里把 Base URL 填成https://taotoken.net/apiKey 填刚拿到的那把。注意 Base URL 后面不要带 UTM 参数API 地址就是https://taotoken.net/api这个形式。如果你用的是 Claude Code 而不是 Codex配置位置在settings.json对应字段是ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY值分别填https://taotoken.net/api和你的 Key。Codex 这边则是config.toml把 base_url 和 api_key 两项写对即可。两种工具只是配置文件不同通道是同一个。Key 创建入口在控制台的 API Keys 页面接入文档在 doc 页面模型对话入口在模型对话页面。这三个地址在排障过程中会反复用到建议先各开一个标签页。三、可复制配置TIM1 参数、启动代码与中断回调这一节把需要交给 Codex 核对的三块内容整理成可直接复制的形式。CubeMX 侧 TIM1 参数预分频系数 Prescaler 71自动重载值 ARR 99由此得到计数频率 1MHz、PWM 周期 100us0.1ms。死区时间 DeadTime 先设 0验证互补波形正常后再改成 10 重新生成工程。CH Polarity 和 CHN Polarity 都设为低电平计数值小于 CCR1 时输出高电平还是低电平由极性决定实际应用里高低都可以但要和后续 MOS 管驱动逻辑对上。触摸按键引脚设为外部中断、下降沿触发LED 设为推挽输出NVIC 里记得开启外部中断。MyInit.c 里的启动代码static void Peripheral_Set() { // 启动定时器1互补PWM输出 HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_1); }这里的关键点是两行都要有。HAL_TIM_PWM_Start只开主通道 CH1HAL_TIMEx_PWMN_Start才开互补通道 CH1N。只写第一行逻辑分析仪上 CH1N 就是一条直线。CallBack.c 里的占空比切换void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin KEY1_Pin) { LED.LED_Fun(LED1, LED_Flip); if(TIM1-CCR1 50) { TIM1-CCR1 80; } else { TIM1-CCR1 50; } } }这段逻辑本身没问题但要注意 CCR1 的比较值和死区时间的关系。如果 DeadTime 折算后的计数值接近或超过 CCR1互补通道的有效电平区间会被吃掉。Keil 软件仿真设置Debug 选项里选左边的软件仿真DLL 文件按芯片型号选对应的把找到的 DLL 路径填进选项框。外部晶振填 8MHzf103ZET6 就是 8M。这一步填错后面逻辑分析仪测出来的周期就对不上 0.1ms。四、验证请求发一次请求确认 Key 与通道可用配置写完后先在 Codex 里发一次最简单的请求比如让它复述一段 TIM1 初始化代码的结构。能正常返回内容说明 Key 和 Base URL 都通了通道可用。这一步不要跳过因为后面要把代码片段和截图描述一起发过去如果通道本身有问题排查会被误导到模型侧。通道确认后把下面这段核对指令发给 Codex这是 STM32F103 用 TIM1 输出互补 PWM 的配置Prescaler71ARR99DeadTime 先 0 后改 10CH Polarity 和 CHN Polarity 均为低电平。启动代码里同时调用了 HAL_TIM_PWM_Start 和 HAL_TIMEx_PWMN_Start。中断回调里根据 TIM1-CCR1 是否等于 50 在 50 和 80 之间切换。请逐项核对1Prescaler 和 ARR 算出的周期是否为 0.1ms2DeadTime10 时折算的计数值是否小于 CCR150 对应的比较值3互补通道启动函数是否遗漏4外部晶振 8MHz 与仿真周期的关系。Codex 返回后重点看它对 DeadTime 折算值的解释。死区时间寄存器 DTG 的编码不是直接写计数值而是按位段映射到不同的时间范围10 这个值对应的实际延时需要按参考手册的 DTG 表换算。如果换算结果接近 50 个计数周期那 CCR150 时互补通道就几乎没有有效输出区间。回到 Keil 重新全速运行在逻辑分析仪里看上下桥臂之间的延时是否与设定的死区时间一致。周期应为 0.1ms频率约 10kHz占空比在按键触发后从 50% 变为 80%。带死区时上管导通前会有一段延时等下面通道完全关闭后再开启这段延时就是死区时间。五、本篇常见错排查错误一死区时间大于占空比导致互补通道无波形这是最典型的卡点。死区时间设成 10 后如果折算的计数值接近 CCR150 的比较点互补通道的有效电平区间被死区吃掉逻辑分析仪上 CH1N 看起来就像没输出。排查方法先把 DeadTime 改回 0确认互补波形正常再逐步增大 DeadTime观察波形从哪个值开始异常。Codex 在这步能帮你把 DTG 编码换算成实际计数值比手动查表快。错误二外部晶振没按 8MHz 填导致仿真周期对不上Keil 软件仿真里晶振频率填错逻辑分析仪测出来的周期就不是 0.1ms。f103ZET6 的外部晶振是 8MHz如果填成其他值Prescaler71、ARR99 算出来的周期会整体偏移。这个错误的表现是波形形状对、周期数值不对容易被误判成定时器配置问题。核对时把晶振设置和 Prescaler/ARR 一起发给 Codex让它反推周期。错误三只调 HAL_TIM_PWM_Start 忘了 HAL_TIMEx_PWMN_StartHAL_TIM_PWM_Start在stm32f1xx_hal_tim.h里只开主通道。互补通道的启动函数HAL_TIMEx_PWMN_Start是拓展功能在同一个头文件的扩展区。只写前者CH1N 不输出。这个错误在代码 review 时很容易漏因为两行函数名只差一个 Ex。把MyInit.c的Peripheral_Set函数完整贴给 Codex让它检查是否两个启动函数都在。错误四CCR1 直接赋值没有考虑预装载中断回调里直接写TIM1-CCR1 80如果 CCR1 的预装载使能没开新值可能在当前周期就生效波形上会看到占空比切换点不在周期边界。CubeMX 里 CCR1 的 preload 选项要确认。这个点不影响功能验证但会影响波形质量。错误五按键中断里没有消抖导致占空比反复切换软件仿真里点击 PE0 模拟按键点一次按下、再点一次松开。实际硬件上触摸按键如果没有消抖一次按下可能触发多次中断CCR1 在 50 和 80 之间反复跳。仿真阶段可以先不管但代码交付前要在回调里加简单的状态判断或延时消抖。六、语义一致 CTA排障和接入相关的配置问题比如 Base URL 填写、API Key 创建、Codex 的config.toml或 Claude Code 的settings.json设置走 API Keys 页面和接入文档这两个入口。API Keys 在控制台里创建和管理 Key接入文档里有各工具的完整配置示例。验证模型通道是否正常用模型对话页面发一次请求即可这也是本文第四节验证步骤对应的入口。如果你后续要长期做 STM32 这类嵌入式编码和 Agent 辅助排查Coding Plan 更适合它面向持续性的编码场景不用每次单独配 Key。把MyInit.c、CallBack.c和逻辑分析仪截图整理好按第四节的核对指令发一次先确认通道可用再逐项对照 TIM1 的 Prescaler、ARR、DeadTime 和 CCR1 比较逻辑。死区排查的核心就是让死区折算值小于占空比对应的比较值同时确保互补启动函数没漏。