CIU32 COMP — GPIO 电压 vs 内部基准

CIU32 CIU32F003_STDLib V1.0.3 比较器 PB0 对比 0.8V 内部基准示例教学

COMP — GPIO 电压 vs 内部基准(COMP_GPIO_VS_VBGR)

固件库: CIU32F003_STDLib V1.0.3 芯片: CIU32F003(Cortex-M0) 源文件: CIU32/CIU32F003_STDLib_V1.0.3/Projects/COMP/COMP_GPIO_VS_VBGR/Source/


一、功能简介

本示例演示模拟比较器的用法:把比较器 COMP1 的正相输入端接到 PB0反相输入端接内部基准电压 VBGR(约 0.8V)。 程序在循环里不断读取比较结果——当 PB0 电压 高于 0.8V 时点亮 LED,否则熄灭 LED。 这相当于一个“0.8V 电压门槛检测器”,可用来判断某个模拟量是否越过了阈值。

二、硬件准备

  • CIU32F003 开发板
  • 一个可调电压源(电位器、分压电阻等)接到 PB0
  • 板载 LED(本示例 PB1,低电平点亮)
  • 接线:电压源正极 → PB0,负极 → GND

内部基准 VBGR 约 0.8V,由芯片内部带隙基准提供,无需外部元件。

三、完整代码

3.1 主流程 main.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "main.h"

int main(void)
{
    system_clock_config();   /* 系统时钟 RCH 48MHz */
    std_delay_init();        /* 初始化延时(COMP 使能后需短延时) */
    gpio_init();             /* LED(PB1) 输出 + PB0 模拟输入 */
    comp1_init();            /* 配置并使能比较器 COMP1 */

    /* 查询方式读取比较结果,控制 LED */
    while (1)
    {
        if (std_comp_get_output_result(COMP1))   /* 正相 > 反相(PB0 > 0.8V) */
        {
            std_gpio_reset_pin(LED_GPIO_PORT, LED_PIN);  /* 点亮 LED(低电平点亮) */
        }
        else                                     /* 正相 < 反相 */
        {
            std_gpio_set_pin(LED_GPIO_PORT, LED_PIN);    /* 熄灭 LED */
        }
    }
}

3.2 比较器与引脚初始化 common.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* COMP1 初始化 */
void comp1_init(void)
{
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_COMP);    /* 使能 COMP 时钟 */

    /* 正相输入 = IO1(PB0),反相输入 = 内部参考电压 */
    std_comp_input_config(COMP1, COMP_INPSEL_IO1, COMP_INMSEL_INVREF);

    std_comp_input_hysteresis_disable();             /* 关闭迟滞(回差) */
    std_comp_set_output_polarity(COMP1, COMP_OUTPOL_NON_INVERTED); /* 输出不反相 */
    std_comp_set_reference_source(COMP1, COMP_REFERENCE_VBGR);     /* 反相端用 0.8V 基准 */

    std_comp_enable(COMP1);                          /* 使能比较器 */
    std_delayus(COMP_EN_DELAY);                      /* 等待启动稳定(约 1us) */
}

/* GPIO 初始化 */
void gpio_init(void)
{
    std_gpio_init_t gpio_config = {0};
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);

    /* LED:PB1 推挽输出 */
    gpio_config.pin         = LED_PIN;          /* PB1 */
    gpio_config.mode        = GPIO_MODE_OUTPUT;
    gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
    gpio_config.pull        = GPIO_PULLUP;
    std_gpio_init(LED_GPIO_PORT, &gpio_config);

    /* 比较器正相输入:PB0 模拟模式 */
    gpio_config.pin   = GPIO_PIN_0;
    gpio_config.mode  = GPIO_MODE_ANALOG;        /* 模拟输入,禁止数字施密特 */
    gpio_config.pull  = GPIO_NOPULL;
    std_gpio_init(GPIOB, &gpio_config);

    std_gpio_set_pin(LED_GPIO_PORT, LED_PIN);    /* 初始熄灭 LED */
}

四、代码分段讲解

① 比较器输入选择

  • std_comp_input_config(COMP1, COMP_INPSEL_IO1, COMP_INMSEL_INVREF): 正相端选 IO1(对应 PB0),反相端选内部参考 INVREF
  • 内部参考源再经 std_comp_set_reference_source(..., COMP_REFERENCE_VBGR) 指定为 VBGR ≈ 0.8V

② 极性 COMP_OUTPOL_NON_INVERTED 表示输出与比较逻辑同向:正相 > 反相时输出 1。 若选反相,则结果取反。

③ 迟滞(hysteresis) 本例关闭迟滞。迟滞能在输入电压在阈值附近抖动时防止输出反复翻转(抗抖),对慢变信号很有用, 需要时可调用 std_comp_input_hysteresis_enable() 开启。

④ 启动延时 比较器使能后内部电路需要极短时间稳定(COMP_EN_DELAY 约 1us),之后读取结果才可靠。

⑤ 结果使用 std_comp_get_output_result(COMP1) 返回 1/0,直接驱动 LED。 也可把比较输出接到 EXTI 产生中断/唤醒(见 COMP_EXTI_Wakeup),让 MCU 睡下去等“越阈”再醒。

五、实验现象

  • 缓慢调高 PB0 电压,越过约 0.8V 时 LED 点亮;
  • 调低到 0.8V 以下,LED 熄灭;
  • 临界点附近可能因无迟滞而略有抖动(可开启迟滞改善)。

六、常见问题

现象 可能原因 解决办法
PB0 接了电压仍无反应 引脚未设模拟模式 确认 GPIO_MODE_ANALOG,否则数字缓冲会影响模拟
阈值明显不是 0.8V 参考源选错 确认 COMP_REFERENCE_VBGR
临界点疯狂抖 没开迟滞 调用 std_comp_input_hysteresis_enable()
上电误动作 没等启动稳定 使能后 std_delayus(COMP_EN_DELAY)

七、小结

比较器是“模拟电压门槛裁判”:正相 > 反相 → 输出高。 流程:开 COMP 时钟 → 选正/反相输入与参考源 → 设极性/迟滞 → 使能并短暂延时 → 读结果。 内部 VBGR(≈0.8V)免外部基准,非常适合做简单的电压越限检测。

八、拓展应用

  • 电池欠压保护:VBAT 分压进 PB0,低于 0.8V 关断负载;
  • 比较输出接 EXTI,实现超低功耗唤醒(见 COMP_EXTI_Wakeup);
  • 窗口比较:用 VDDA 分压作上下阈值,判断信号是否在安全区间内(见 COMP_VDDA_DIV_VS_GPIO_Window)。
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计