2. 自检程序基础:自检程序的概念、自检与诊断的区别、自检程序的分类

各位同学,咱们今天聊聊自检程序。说实话,这玩意儿在仪器仪表里,就像人的体检一样重要。我做了这么多年仪器开发,见过太多因为自检没做好,导致现场出大问题的案例。嗯,咱们一步步来。

2.1 自检程序到底是什么?

自检程序,说白了就是仪器自己给自己做检查。它不需要外部设备介入,完全靠自身硬件和软件配合,验证各个模块是否工作正常。

我个人习惯把自检比作「起床三部曲」:睁眼(上电)、活动关节(初始化)、深呼吸(功能验证)。仪器也是一样,它得先确认自己「活着」,再确认自己「能干活的」。

核心定义:自检程序(Self-Test Program)是嵌入式系统中用于验证硬件功能完整性和软件运行环境正确性的一段专用代码。它通常在系统启动时、运行过程中或特定条件下执行。

我在项目中遇到过一件事:一台气相色谱仪,每次开机都报错,但重启后又好了。折腾了三天,最后发现是自检程序里漏掉了对加热模块的电流检测。你想想看,如果自检程序本身就不完整,那仪器就像个「睁眼瞎」。

2.2 自检与诊断,别搞混了

很多新手容易把自检和诊断混为一谈。我刚开始做这行时也犯过这个错。它们俩到底有啥区别?咱们用个表格说清楚。

对比项 自检(Self-Test) 诊断(Diagnosis)
执行时机 固定时间点(上电、周期、触发) 故障发生后或维护时
目的 确认「是否正常」 定位「哪里坏了」
深度 浅层、快速、全覆盖 深层、详细、针对性
耗时 毫秒到秒级 秒到分钟级
用户参与 自动执行,无需干预 可能需要手动操作

举个例子你就明白了。自检就像你每天早上照镜子——看看头发乱不乱、脸上有没有脏东西。诊断呢,就像你感觉牙疼了,去医院拍个片子——医生要找到到底是哪颗牙出了问题。

为什么会这样设计?因为自检要快,不能影响仪器正常启动。诊断可以慢,但必须准。我在一个项目中就吃过亏:把诊断逻辑写进了上电自检里,结果仪器启动要两分钟,客户直接投诉了。

2.3 自检程序的三种分类

根据执行时机和触发方式,自检程序主要分三类。我建议你把这个分类记牢,因为后面写代码时,每个类型的设计思路都不一样。

2.3.1 上电自检(Power-On Self-Test, POST)

这是最基础、最重要的一类。仪器一上电,首先跑的就是它。它的任务只有一个:确认系统能不能安全启动。

上电自检通常包括:

  • CPU 核心检查:跑个简单的指令测试,确认CPU没死锁
  • 内存检查:写读校验,确认RAM能正常存取
  • 关键外设检查:比如ADC、DAC、传感器接口
  • 电源电压检查:各供电轨是否在正常范围内
  • 固件完整性检查:CRC校验,防止固件损坏

我的经验:上电自检一定要「快」。我一般控制在200ms以内。如果超过500ms,操作员就会觉得仪器「卡住了」。曾经有个项目,上电自检做了1.2秒,结果被客户要求返工——因为竞争对手只要300ms。

上电自检的典型流程,用伪代码表示大概是这样:

void PowerOnSelfTest(void)
{
    // 第一步:检查CPU
    if (CPU_Test() != PASS) {
        HaltSystem("CPU故障");
    }
    
    // 第二步:检查内存
    if (RAM_Test() != PASS) {
        HaltSystem("内存故障");
    }
    
    // 第三步:检查电源
    if (Power_Test() != PASS) {
        HaltSystem("电源异常");
    }
    
    // 第四步:检查关键外设
    if (ADC_Test() != PASS) {
        HaltSystem("ADC故障");
    }
    
    // 全部通过,进入正常启动流程
    StartNormalOperation();
}

2.3.2 周期自检(Periodic Self-Test)

仪器运行过程中,不能一直「埋头干活」。它需要时不时地检查一下自己,确保状态没变差。这就是周期自检。

周期自检的特点:

  • 不影响主任务:利用空闲时间或中断间隙执行
  • 分时执行:每次只检查一部分,避免长时间占用CPU
  • 可配置周期:不同模块的检查频率可以不同

举个例子,我在做在线水质分析仪时,pH电极的零点漂移检查每10分钟做一次,而温度补偿电路每1分钟检查一次。为什么?因为温度变化快,pH漂移慢。你想想看,如果反过来,那数据就不准了。

注意:周期自检不能影响正常测量。我见过一个案例,周期自检里做了个耗时的EEPROM擦写操作,结果导致采样周期抖动,数据出现周期性毛刺。排查了整整两天才找到原因。

2.3.3 触发自检(Triggered Self-Test)

这种自检不是自动执行的,而是由外部事件触发。触发条件可以是:

  • 用户指令:操作员按下「自检」按钮
  • 外部信号:比如更换传感器后自动触发
  • 故障标志:某个模块报错后,触发相关模块的自检
  • 定时维护:到了预设的维护周期,提示用户执行自检

触发自检通常比上电自检更深入。因为它有明确的目的——要么是用户想确认仪器状态,要么是系统怀疑某个模块有问题。

我曾经做过一个项目,仪器在野外工作,每三个月需要做一次全面自检。操作员只要按一下面板上的「CAL」键,仪器就会自动执行一套完整的自检流程,包括:

  1. 内部基准源校准
  2. 所有通道的零点和满量程检查
  3. 通信接口环回测试
  4. 电池电量深度检测
  5. 生成自检报告并存储

嗯,这里要注意:触发自检的结果一定要有明确的输出。要么显示在屏幕上,要么通过串口打印,要么存到日志里。不然用户按了半天,啥反馈都没有,那体验就很差了。

2.4 三种自检的对比总结

最后,我用一个表格把三种自检放在一起对比,方便你记忆:

类型 执行时机 检查深度 耗时要求 典型应用
上电自检 系统启动时 浅层、全覆盖 极短(<500ms) 确认系统可安全启动
周期自检 运行过程中 中等、分模块 不影响主任务 监控运行状态变化
触发自检 外部事件触发 深层、针对性 可较长 故障排查、维护验证

好了,这一章的内容就这些。记住一句话:自检程序不是可有可无的装饰品,它是仪器可靠性的最后一道防线。下一章咱们会深入讲自检程序的具体设计方法和代码实现,到时候我会拿实际项目中的代码来拆解。