应广单片机比较器测电压代码详解:不用ADC检测VDD电池低压(PMS150C/PFS154)

整理编辑:逐高电子技术开发部 / 日期:2026-6-19

应广单片机比较器测电压代码详解:低压检测、分压计算与调试优化

用比较器做电压阈值检测,不依赖 ADC 的低成本方案
应广单片机 比较器测电压 低压检测 分压计算 代码详解

一、应广单片机比较器测电压,本质上是在做什么?

在很多低成本电子产品中,经常会遇到电压检测需求,例如电池低压提醒、输入电源检测、充电电压判断、过压保护、掉电检测等。对于这些场景,很多工程师会想到使用 ADC 采样,但在一些应广单片机项目中,使用内部比较器往往也是一种更简单、更经济的方案。

需要先说明一点:比较器并不能像 ADC 一样读取具体电压值。

ADC 可以得到类似这样的结果:

当前电池电压 = 3.72V

而比较器只能判断两个电压谁高谁低:

待测电压 > 参考电压
或
待测电压 < 参考电压

所以,所谓“应广单片机比较器测电压”,更准确地说,应该叫:

应广单片机利用比较器进行电压阈值检测

也就是说,它适合判断电压是否超过某个门槛,而不是用来做高精度电压测量。

如果产品只需要知道“电池是否低压”“电源是否插入”“电压是否超过保护点”,比较器方案非常合适;如果需要显示电压数值、电池百分比或进行精细控制,则应优先考虑 ADC 方案。

二、为什么应广单片机项目常用比较器检测电压?

应广单片机常见于小家电、玩具、LED 控制、充电器、消费电子、电池供电产品等成本敏感场景。这类产品往往有几个特点:

  • 成本要求低;
  • 程序资源有限;
  • IO 和 ADC 资源有限;
  • 功耗要求较高;
  • 电压检测只需要判断高低,不需要精确数值。

在这种情况下,使用比较器检测电压有明显优势。

1. 成本低,外围简单

如果芯片内部已经集成比较器和参考电压模块,外部通常只需要两个分压电阻,就可以完成电池低压检测或输入电压判断。相比外置比较器芯片,BOM 成本更低,PCB 面积也更小。

2. 程序逻辑简单

ADC 检测电压通常需要:

启动 ADC → 等待转换 → 读取采样值 → 换算电压 → 滤波 → 判断阈值

而比较器只需要判断输出状态:

if (CMP_OUT) {
    // 电压高于阈值
} else {
    // 电压低于阈值
}

对低成本 MCU 来说,这种逻辑更轻量。

3. 响应速度快

比较器属于硬件模拟判断,电压跨过阈值后输出状态会快速变化。对于过压保护、掉电检测、短路保护等场景,比较器比纯软件 ADC 轮询更直接。

4. 有利于低功耗设计

部分应广 MCU 型号支持比较器中断或低功耗唤醒。如果产品平时处于休眠状态,可以利用比较器检测外部电压变化,从而唤醒单片机。

5. 节省 ADC 资源

一些应广单片机型号 ADC 通道有限,或者产品中 ADC 已经用于 NTC、电位器、光敏电阻等采样。此时将低压检测交给比较器,可以释放 ADC 资源。

三、比较器和 ADC 检测电压有什么区别?

很多初学者会把比较器和 ADC 混在一起,但二者定位完全不同。

对比项目 比较器检测电压 ADC 检测电压
输出结果 高于/低于阈值 具体数字量
是否能得到电压值 不能 可以
程序复杂度 较高
响应速度 取决于采样周期
成本和资源占用 较高
适合场景 欠压、过压、电源插入检测 电压显示、电量估算、传感器采样
精度 取决于参考源和比较器误差 取决于 ADC 位数和参考源

简单总结:

只判断门槛,用比较器;要读取数值,用 ADC。

例如:

  • 判断电池是否低于 3.0V → 用比较器
  • 显示电池电压为 3.68V → 必须用 ADC
  • 判断 USB 5V 是否插入 → 用比较器
  • 做电池百分比显示 → 建议用 ADC

四、应广单片机比较器检测电压的典型电路思路

比较器通常有两个输入端:

CMP+:正输入端
CMP-:负输入端

当:

CMP+ > CMP- → 比较器输出为高电平
CMP+ < CMP- → 比较器输出为低电平

实际项目中,常见连接方式如下:

待测电压 → 电阻分压 → 比较器一个输入端
参考电压 → 比较器另一个输入端

例如检测电池是否低压:

电池电压 Vin
   |
  R1
   |
   +---- 接入比较器输入端
   |
  R2
   |
  GND

分压点电压为:

Vcmp = Vin × R2 / (R1 + R2)

然后让比较器将 Vcmp 与内部参考电压或外部参考电压进行比较。

五、分压电阻和检测阈值怎么计算?

计算前必须先确认芯片型号是否支持内部固定基准。 应广不同型号(如 PMS150C、PFS154、PMS132B 等)的比较器参考电压档位不同,部分型号只有 VDD 分压,没有 1.2V 固定基准。若芯片没有固定基准,请改用外部参考电压或 ADC 方案。

假设希望检测电池电压是否低于 3.0V,当前芯片型号支持 1.2V 内部参考电压,那么可以让电池电压经过分压后,在 3.0V 时刚好等于 1.2V。

公式如下:

Vcmp = Vin × R2 / (R1 + R2)

设定:

Vin = 3.0V
Vcmp = 1.2V

则:

1.2 = 3.0 × R2 / (R1 + R2)

也就是:

R2 / (R1 + R2) = 0.4

可以选择:

R1 = 150K
R2 = 100K

此时:

Vcmp = Vin × 100K / (150K + 100K)
Vcmp = Vin × 0.4

当电池电压为 3.0V 时:

Vcmp = 3.0V × 0.4 = 1.2V

这样比较器就可以根据分压点与参考电压的大小关系,判断电池是否低于设定阈值。

功耗提示: 150K + 100K 分压在 3V 电池下消耗约 12µA。如需进一步降低功耗,可选用 MΩ 级电阻(如 1.5M + 1M),但需注意高阻分压更容易受干扰,建议增加滤波电容。

六、分压设计时不能忽略输入电压范围

这是比较器测电压方案中非常重要的一点。

无论是普通 IO、ADC 输入,还是比较器输入,引脚电压都不能超过芯片规格书允许范围。特别是检测高于 MCU 供电电压的信号时,不能直接接到单片机引脚。

例如单片机供电为 3V,而外部输入可能是 5V、12V 甚至更高,就必须通过电阻分压、限流、滤波或钳位保护后再接入比较器输入端。

实际设计时需要关注:

  • 分压后最大电压不能超过比较器输入允许范围;
  • 输入电流不能超过 IO 钳位能力;
  • 高阻分压容易受干扰;
  • 必要时增加 RC 滤波;
  • 强干扰环境下可增加限流电阻或保护器件;
  • 具体限制必须以应广对应型号规格书为准

这一点不能只靠代码解决,硬件设计必须先安全。

七、参考电压来源会直接影响检测精度

很多文章在讲应广单片机比较器测电压代码时,会默认芯片内部有 1.2V 参考电压。但实际情况并不一定如此。

不同应广单片机型号的比较器资源差异较大,可能存在以下几种情况:

  • 支持内部固定参考电压;
  • 支持内部 Bandgap 基准;
  • 支持 VDD 分压作为参考;
  • 支持外部参考电压输入;
  • 参考电压档位有限;
  • 某些低成本型号比较器功能较简单。

如果参考电压来自稳定的内部基准,适合做电池低压判断。

如果参考电压来自 VDD 分压,而待测电压本身又是 VDD,那么比较关系可能会随电源一起变化,无法得到稳定的绝对低压点。

因此,做低压检测时要特别注意:

  • 参考源是否稳定?
  • 参考源是否随 VDD 变化?
  • 检测对象是否就是 VDD 本身?
  • 芯片内部参考误差有多大?
  • 量产时是否需要留余量?

如果产品对阈值要求较高,应考虑校准、外部基准,或者使用 ADC 结合软件修正。

八、应广单片机比较器初始化代码思路

由于应广单片机型号较多,不同芯片的寄存器名称、比较器输入通道、参考电压选择方式、开发环境都可能不同。 以下代码更适合作为比较器电压检测代码框架,实际项目中应以具体型号的 数据手册、官方头文件、官方例程、Padauk IDE 或对应开发环境说明、Mini-C 或汇编支持情况为准进行移植。

/*
 * 应广单片机比较器电压检测代码框架
 *
 * 说明:
 * 1. 不同型号寄存器名称不同,以下代码用于说明配置流程;
 * 2. 实际项目请根据具体芯片规格书和官方例程修改;
 * 3. 比较器只能判断电压高低,不能读取具体电压值;
 * 4. 若芯片不支持内部参考电压,需要改用外部参考或其他方案。
 */

void Comparator_Init(void)
{
    /*
     * 1. 配置待测电压输入脚
     * - 设置为输入模式;
     * - 关闭上拉/下拉;
     * - 如芯片要求,切换为模拟功能;
     * - 确认该引脚支持比较器输入复用。
     */
    // Set_CMP_Input_Pin();
    // Disable_Pullup();
    // Select_Analog_Function();

    /*
     * 2. 开启比较器模块
     */
    // Comparator_Enable();

    /*
     * 3. 选择比较器正输入端
     * 例如:CMP+ = 外部分压电压
     */
    // Comparator_Positive_Input_Select(EXTERNAL_PIN);

    /*
     * 4. 选择比较器负输入端
     * 例如:CMP- = 内部参考电压或外部参考电压
     */
    // Comparator_Negative_Input_Select(INTERNAL_VREF);

    /*
     * 5. 开启并选择参考电压
     * 注意:并非所有型号都支持可选内部参考电压。
     */
    // Vref_Enable();
    // Vref_Select(VREF_1_2V);

    /*
     * 6. 设置输出极性
     * 根据实际逻辑选择是否反相。
     */
    // Comparator_Output_Polarity_Normal();

    /*
     * 7. 等待比较器和参考电压稳定
     * 实际延时根据芯片手册和测试结果决定。
     */
    DelayMs(2);

    /*
     * 8. 清除比较器标志位
     * 如需中断,再开启比较器中断。
     */
    // Comparator_Clear_Flag();
    // Comparator_Interrupt_Enable();
}

九、轮询方式读取比较器结果

如果产品对响应速度要求不高,比如普通电池低压提醒,可以在主循环中定时读取比较器输出状态。

typedef enum {
    VOLTAGE_NORMAL = 0,
    VOLTAGE_LOW
} voltage_state_t;

volatile voltage_state_t voltage_state = VOLTAGE_NORMAL;

void Voltage_Check_Task(void)
{
    /*
     * 假设:
     * CMP_OUT = 1 表示待测电压高于参考电压;
     * CMP_OUT = 0 表示待测电压低于参考电压。
     *
     * 实际逻辑要根据比较器输入端连接方式和输出极性确认。
     */

    if (CMP_OUT) {
        voltage_state = VOLTAGE_NORMAL;
    } else {
        voltage_state = VOLTAGE_LOW;
    }
}

主循环示例:

int main(void)
{
    System_Init();
    Comparator_Init();

    while (1) {
        Voltage_Check_Task();

        if (voltage_state == VOLTAGE_LOW) {
            Low_Voltage_Process();
        } else {
            Normal_Work_Process();
        }

        DelayMs(10);
    }
}

轮询方式优点是简单、稳定、容易调试。缺点是响应速度取决于查询周期。

十、增加软件滤波,避免临界点误判

实际产品中,电池电压、电源输入、电机负载、电感开关、LED 驱动都会带来纹波和干扰。如果只判断一次比较器输出,可能会误判。更可靠的方式是连续多次确认

#define LOW_CONFIRM_COUNT       5
#define NORMAL_CONFIRM_COUNT    5

void Voltage_Check_Filter(void)
{
    static unsigned char low_count = 0;
    static unsigned char normal_count = 0;

    if (CMP_OUT == 0) {
        /*
         * 电压低于阈值
         */
        if (low_count < LOW_CONFIRM_COUNT) {
            low_count++;
        }

        normal_count = 0;

        if (low_count >= LOW_CONFIRM_COUNT) {
            voltage_state = VOLTAGE_LOW;
        }
    } else {
        /*
         * 电压高于阈值
         */
        if (normal_count < NORMAL_CONFIRM_COUNT) {
            normal_count++;
        }

        low_count = 0;

        if (normal_count >= NORMAL_CONFIRM_COUNT) {
            voltage_state = VOLTAGE_NORMAL;
        }
    }
}

如果每 10ms 检测一次,连续 5 次确认,相当于需要约 50ms 才改变状态。这样可以有效过滤瞬间抖动。

十一、迟滞设计:比较器稳定性的关键

比较器检测电压时,最常见的问题是阈值附近反复跳变

比如低压阈值设为 3.0V,当电池电压在 2.99V 到 3.01V 之间波动时,比较器输出可能频繁变化,导致系统一会儿低压、一会儿正常。解决这个问题,最好加入迟滞

1. 软件迟滞

软件迟滞的思路是:进入低压和恢复正常使用不同阈值。

低于 3.0V:判定为低压
高于 3.2V:恢复为正常

这样电压必须明显回升后才恢复,系统不会在临界点来回抖动。

如果只有一个比较器固定阈值,也可以通过状态机、延时确认、不同处理策略实现类似效果。

2. 硬件迟滞

硬件迟滞通常通过正反馈电阻实现,使比较器翻转后阈值发生轻微变化。它的响应更直接,但需要额外计算电阻参数,并验证实际波形。

3. 内部迟滞

部分 MCU 比较器可能支持内部迟滞功能。如果应广具体型号支持,应优先查看规格书中的比较器迟滞配置位。

工程经验上,低压检测不建议只做一次判断,至少要有以下其中一种措施:

  • 软件多次确认;
  • 软件迟滞;
  • 硬件 RC 滤波;
  • 硬件迟滞;
  • 芯片内部迟滞。

十二、中断方式检测电压变化

如果需要快速响应电压变化,例如掉电检测、过压保护、外部电源插入唤醒,可以使用比较器中断。

示例代码框架如下:

void Comparator_ISR(void)
{
    /*
     * 不同应广型号中断入口和标志位名称不同,
     * 以下仅表示处理流程。
     */

    if (Comparator_Get_Flag()) {
        Comparator_Clear_Flag();

        if (CMP_OUT) {
            voltage_state = VOLTAGE_NORMAL;
        } else {
            voltage_state = VOLTAGE_LOW;
            low_voltage_flag = 1;
        }
    }
}

中断方式的优点:

  • 响应速度快;
  • 不需要频繁轮询;
  • 适合保护类功能;
  • 可用于低功耗唤醒。

中断方式的缺点:

  • 阈值附近抖动可能导致频繁中断;
  • 需要正确清除中断标志;
  • 需要处理误触发;
  • 中断内不宜执行复杂任务。

建议中断中只设置标志位,具体处理放到主循环中完成。

if (low_voltage_flag) {
    low_voltage_flag = 0;

    /*
     * 在主循环中执行低压处理
     * 例如关闭负载、停止 PWM、提示用户等。
     */
    Low_Voltage_Process();
}

十三、完整软件框架示例

下面给出一个更接近实际项目的框架,包含初始化、滤波和状态处理。依旧需要根据具体应广单片机型号修改底层寄存器。

/*
 * 应广单片机比较器电压检测完整框架
 *
 * 功能:
 * - 使用比较器检测电压是否低于设定阈值
 * - 包含软件滤波,防止误触发
 * - 状态变化回调处理
 * - 适用于电池低压检测、电源插入检测等场景
 */

#include 
#include 

/* ===== 硬件配置 ===== */
#define CMP_OUT              (P0 & (1 << 0))  // 比较器输出引脚
#define LOW_CONFIRM_COUNT    5
#define NORMAL_CONFIRM_COUNT 5

/* ===== 状态定义 ===== */
typedef enum {
    VOLTAGE_NORMAL = 0,
    VOLTAGE_LOW
} voltage_state_t;

/* ===== 全局变量 ===== */
voltage_state_t voltage_state = VOLTAGE_NORMAL;
volatile bool low_voltage_pending = false;

/* ===== 比较器初始化 ===== */
void Comparator_Init(void)
{
    /*
     * 1. 配置输入引脚
     * 2. 开启比较器
     * 3. 选择输入通道和参考电压
     * 4. 设置输出极性
     * 5. 等待稳定
     */
    // 具体寄存器配置请参考对应型号数据手册
}

/* ===== 滤波检测 ===== */
void Voltage_Check_Filter(void)
{
    static uint8_t low_count = 0;
    static uint8_t normal_count = 0;

    if (CMP_OUT == 0) {
        if (low_count < LOW_CONFIRM_COUNT) {
            low_count++;
        }
        normal_count = 0;

        if (low_count >= LOW_CONFIRM_COUNT) {
            if (voltage_state != VOLTAGE_LOW) {
                voltage_state = VOLTAGE_LOW;
                low_voltage_pending = true;
            }
        }
    } else {
        if (normal_count < NORMAL_CONFIRM_COUNT) {
            normal_count++;
        }
        low_count = 0;

        if (normal_count >= NORMAL_CONFIRM_COUNT) {
            if (voltage_state != VOLTAGE_NORMAL) {
                voltage_state = VOLTAGE_NORMAL;
                low_voltage_pending = true;
            }
        }
    }
}

/* ===== 低压处理函数 ===== */
void Low_Voltage_Process(void)
{
    // 关闭非关键负载
    // 停止 PWM 输出
    // 点亮低压指示灯
    // 或进入低功耗模式
}

/* ===== 恢复正常处理函数 ===== */
void Normal_Voltage_Process(void)
{
    // 恢复负载
    // 恢复 PWM
    // 关闭低压指示灯
}

/* ===== 主循环 ===== */
int main(void)
{
    System_Init();
    Comparator_Init();

    while (1) {
        // 定时检测(约 10ms)
        Voltage_Check_Filter();

        if (low_voltage_pending) {
            low_voltage_pending = false;

            if (voltage_state == VOLTAGE_LOW) {
                Low_Voltage_Process();
            } else {
                Normal_Voltage_Process();
            }
        }

        DelayMs(10);
    }
}

十四、实际项目调试技巧

以下3条调试经验来自实际项目,可帮助缩短开发周期:

技巧1:确认阈值前先测量分压点真实电压

电阻精度、NTC 误差、PCB 漏电都会影响分压比。建议在焊接后先用万用表测量比较器输入引脚的实际电压,确认是否与理论计算一致。如果偏差超过 ±5%,需调整电阻或修正阈值。

技巧2:量产时预留阈值调整位

不同批次芯片的比较器偏移电压可能有差异。建议在 PCB 上预留一个 0Ω 电阻或小型电位器,方便量产时微调分压比,确保阈值一致性。

技巧3:用示波器观察比较器输出波形

在阈值附近,比较器输出可能出现高频振荡(尤其是输入信号有纹波时)。使用示波器观察 CMP_OUT 引脚波形,确认是否有异常抖动。如有抖动,优先增加软件滤波次数(如从 5 次改为 10 次),其次考虑增加硬件 RC 滤波。

重要提醒:以上代码为框架说明,不可直接复制编译。应广单片机不同型号的寄存器定义、比较器通道、参考电压选项均有差异,请务必以具体型号的 数据手册(Datasheet)官方开发环境 为准进行移植。

结语

应广单片机内部比较器是一个被很多工程师低估的模块。在电池低压检测、电源插入检测、过压保护、掉电预警等场景中,它可以用最少的硬件成本和最简洁的代码完成可靠的电压阈值判断。

关键不在于“怎么写代码”,而在于:

  • 硬件上——分压安全、参考稳定、滤波合理;
  • 软件上——防抖可靠、迟滞合理、状态切换平滑;
  • 工程上——确认芯片型号支持、验证量产一致性。

应广单片机技术资料

  • 台湾应广单片机官网
  • 应广单片机例程
  • 应广单片机编程指南
  • 应广单片机定时器
  • 技术开发工具
  • 应广单片机IDE&仿真器
  • 应广单片机烧录器
  • 代码生成器
5S-P-005 应广烧录器使用指南:通用型单片机编程器 | 自动检测封装引脚 | PADAUK

5S-P-005 应广烧录器使用指南:通用型单片机编程器 | 自动检测封装引脚 | PADAUK


应广单片机PMS150C温控PWM风扇控制器开发案例:电路、BOM、代码与量产参数|逐高电子

应广单片机PMS150C温控PWM风扇控制器开发案例:电路、BOM、代码与量产参数|逐高电子


应广单片机OTP能不能反复烧?PMS150C/PFS154烧录区别与量产避坑指南

应广单片机OTP能不能反复烧?PMS150C/PFS154烧录区别与量产避坑指南


PMD040B 24位称重ADC内置温度传感器_应广科技授权代理商_逐高电子

PMD040B 24位称重ADC内置温度传感器_应广科技授权代理商_逐高电子


应广PADAUK单片机Mini-C IDE搭建与点灯实战 | 从零到LED闪烁附OTP避坑

应广PADAUK单片机Mini-C IDE搭建与点灯实战 | 从零到LED闪烁附OTP避坑


PMD040B体重秤完整开发案例:硬件设计/固件代码/产线校准_量产级24位ADC低功耗方案

PMD040B体重秤完整开发案例:硬件设计/固件代码/产线校准_量产级24位ADC低功耗方案


应广单片机程序可以不加看门狗吗?3种情况决定关闭还是开启WDT,逐高电子方案支持

应广单片机程序可以不加看门狗吗?3种情况决定关闭还是开启WDT,逐高电子方案支持


应广单片机采集数据总“飘”?5个设置技巧,从根源解决问题 | 逐高电子技术分享

应广单片机采集数据总“飘”?5个设置技巧,从根源解决问题 | 逐高电子技术分享


应广单片机热点问题实战解决方案 - 开发/烧录/选型/PWM/低功耗/滚码 | 逐高电子·应广技术方案

应广单片机热点问题实战解决方案 - 开发/烧录/选型/PWM/低功耗/滚码 | 逐高电子·应广技术方案


应广单片机入门实战:基于PMS150G与5S-I-S02B仿真器的LED闪烁完整教程

应广单片机入门实战:基于PMS150G与5S-I-S02B仿真器的LED闪烁完整教程


STM32太贵?试试应广单片机:成本低至9毛钱,功耗0.5μA,抗干扰±4kV | 逐高电子

STM32太贵?试试应广单片机:成本低至9毛钱,功耗0.5μA,抗干扰±4kV | 逐高电子


PMD040B 24位Δ-Σ ADC | 内置PGA/温度传感器/电源开关 | 应广科技高精度模数转换器

PMD040B 24位Δ-Σ ADC | 内置PGA/温度传感器/电源开关 | 应广科技高精度模数转换器


PMS150C LED球泡灯方案:原理图+代码+过零检测(PA0)与可控硅调光(MOC3052) | BOM成本¥1.2

PMS150C LED球泡灯方案:原理图+代码+过零检测(PA0)与可控硅调光(MOC3052) | BOM成本¥1.2


单片机选型指南:PMS150C、PMS152、PMS154C、PMS133 - 申请样品

单片机选型指南:PMS150C、PMS152、PMS154C、PMS133 - 申请样品


国产OTP单片机替代方案选型 | 应广科技专场 | 逐高电子

国产OTP单片机替代方案选型 | 应广科技专场 | 逐高电子


开发实力

专业资深的软硬件开发工程师团队,熟悉行业客户产品硬件技术平台解决方案

全球渠道

为客户提供高性价比的产品和服务,满足客户及时快速的电子生产制造需求

品质保证

专业的测试保证团队,保证每批方案的稳定性,兼容性,和抗干扰性

售后服务

专业的技术服务团队,24小时为客户提供各种软硬件的技术支持和售后服务

服务热线

0755-88364040
18902464556

义隆代理

烧录开发

技术支持

申请样品

扫描微信二维码