设了电流测不到输出?状态机IDLE态在偷偷清零
2026/8/5 10:12:46 网站建设 项目流程

一句话: 发光序列状态机在IDLE态每100ms把所有DAC清零(安全设计)。手动设的电流100ms内就被抹掉——串口回显"设置成功"不代表硬件真有输出。加个"手动模式"标记就解决。

适合谁读:遇到"设置了没效果""回显成功但输出端测不到"的嵌入式工程师。

现象:100mA有输出,40/80mA没有

上位机设电流:回显成功,CRC校验通过,一切正常。但拿万用表测输出端:

  • 设 100mA →有输出
  • 设 40mA →没有
  • 设 80mA →没有

同样的命令、同样的换算、同样的写码逻辑,为什么 100mA 能测到?

排查:先排除换算和写码

40mA 对应 DAC 码 546,80mA 对应 1092,100mA 对应 1365——换算没问题。写码逻辑三条路径完全相同,也排除了。

问题不在命令本身,在命令之后发生了什么。

真相:IDLE态每100ms清一次DAC

设备有个发光序列状态机:空闲 → 预热 → 运行 → 待机……设计上,空闲态必须把所有 DAC 清零(安全要求:不点亮的时候输出必须为零,防止漏电烧器件)。代码长这样:

else { /* IDLE: 全关 */ ... Dac_Write_Code(ch, 0x0000); // 每100ms清一次! }

时序是这样的:

t=0ms 上位机设 40mA,DAC 输出 40mA ✓ t=100ms 序列 IDLE 定时任务跑一次:全部清零 ✗ t=200ms 再清一次……

你设完电流,100ms 内就被序列的 IDLE 任务抹掉。万用表当然测不到。

那为什么 100mA 能测到?因为测试时发光序列恰好处于别的状态(那个状态会设激光电流,不清零),100mA 是它设的,不是你设的。40/80mA 测试时序列早已超时回到空闲态,一直清零。

设计冲突:安全逻辑 vs 手动测试

回头看,这是个真实的设计矛盾:

  • IDLE 全关是必须的——防漏电、防误点亮,这是安全底线,不能删
  • 手动设电流是调试刚需——但它的语义被 IDLE 覆盖了,设了等于没设

安全逻辑本身没错,错的是没有区分"业务输出"和"手动测试输出"

修复:加一个手动模式标记

合理的做法是让状态机知道"谁在控制输出":

if (manual_mode) { /* 手动模式:保留上位机设的值,IDLE 不清零 */ } else { /* 序列模式:按状态机输出 */ }
  • 上位机手动设电流 → 置手动模式标记,IDLE 跳过清零
  • 退出手动模式(比如启动序列)→ 清除标记,恢复安全逻辑

这样安全底线还在,调试也不再被静默覆盖。

经验

  1. 串口回显"设置成功" ≠ 硬件实际输出——协议层和硬件之间隔着一层业务逻辑,回显只证明"命令收到了"
  2. 周期任务会静默覆盖手动操作——状态机、轮询这类后台逻辑,调试时先搞清楚"现在它在干什么"
  3. 安全逻辑是调试时的隐形敌人——"禁用时全关"这类兜底设计,最容易让人误判"设备坏了"

排查这类问题最快的办法:禁用后台任务测一次。禁掉序列,再设电流,如果立刻有输出——问题就实锤了。


实测对比:直接设电流:100ms内被IDLE清掉,测不到输出 | 加手动模式标记:设值保留,调试一次过

有用的话点个收藏,下次调试直接用。有问题欢迎评论区交流,看到了都会回。

下一篇:脚本明明写对了,为什么就是匹配不到?\r\n 和 \n 的坑——跨平台脚本的行尾陷阱

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询