5.3 COMP 使用说明

本章说明 N32G41x 标准外设库中 COMP 驱动的文件组成与 21 个公开函数,内容包括 3 个比较器的复位与初始化、输入选择、极性、迟滞与消隐、滤波、窗口模式与锁定、参考电压以及输出状态与中断管理;示例包含 COMP_OUT 与 CompBreak 两个工程。比较器的工作模式、互联关系与寄存器位定义请配合用户手册的“比较器(COMP)”章节阅读,CompBreak 的刹车输入还涉及用户手册的 ATIM 定时器章节,芯片已知问题以勘误手册为准。

5.3.1 相关文件

相对路径 作用
firmware/n32g41x_std_periph_driver/inc/n32g41x_comp.h 定义 COMP_InitType 结构体与输入选择、迟滞、消隐、极性、时钟、参考电压等枚举与掩码宏,并按复位与初始化、输入与输出、迟滞与消隐、滤波、低功耗与锁定、参考电压、输出与中断七个区段声明 21 个公开函数
firmware/n32g41x_std_periph_driver/src/n32g41x_comp.c 实现上述 21 个函数:外设复位,CTRL、FILC、FILP、LOCK、WINMODE、INTEN、INTSTS 与 INVREF 寄存器的读改写配置与状态读取
projects/n32g41x_EVAL/examples/COMP/ COMP 示例根目录,含 COMP_OUT、CompBreak 2 个示例
projects/n32g41x_EVAL/examples/COMP/COMP_OUT/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32g41x_EVAL/bsp/ COMP_OUT 引用的公共日志接口:inc/log.h 提供 log_init 与 log_info 等打印宏

5.3.2 API 参考

搜索 API共 21 个函数

以下 21 个公开函数按 n32g41x_comp.h 的声明顺序分为 7 组;每个条目给出功能摘要与 n32g41x_comp.c 中该函数正上方的注释原文。

复位与初始化

COMP_DeInit、COMP_StructInit、COMP_Init、COMP_Enable

输入与输出配置

COMP_SetInpSel、COMP_SetInmSel、COMP_OutputPolarityConfig

迟滞与消隐配置

COMP_SetHyst、COMP_EnableDoubleHyst、COMP_SetBlanking

滤波配置

COMP_SetFilterControl、COMP_SetFilterPrescaler

低功耗与锁定配置

COMP_WindowModeEnable、COMP_SetLock、COMP_StopOrLowpower32KClkSel、COMP_StopOrLowpowerMode

参考电压配置

COMP_SetRefScl

输出状态、中断与标志管理

COMP_GetOutStatus、COMP_SetIntEn、COMP_GetIntStsOneComp、COMP_ClearIntStsOneComp

void COMP_DeInit(void)复位 COMP 寄存器。
源码注释
name    COMP_DeInit.
fun     Reset the COMP registers.
return  none

使用提示: 实现通过对 COMP 所在的 APB1 外设复位(RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP))来复位 COMP 寄存器。

void COMP_StructInit(COMP_InitType *COMP_InitStruct)为 COMP_InitType 的每个成员填入默认值。
源码注释
name    COMP_StructInit.
fun     Fills all COMP_InitType members with default value.
param   COMP_InitStruct :
          - ClockSelect
          - LowPoweMode
          - Blking
          - DoubleHyst
          - Hyst
          - PolRev
          - InpSel
          - InmSel
          - FilterEn
          - SampWindow
          - Threshold
          - ClkPsc
          - En
return  none

使用提示: 实现把 Blking、DoubleHyst、Hyst、PolRev 分别置为 COMP_BLKING_NO、COMP_DOUBLEHYST_DIS、COMP_HYST_NO、COMP_OUTPOL_NREV,InpSel、InmSel 置为对应的保留值,FilterEn、En 置为 DISABLE,SampWindow、Threshold、ClkPsc、ClockSelect、LowPoweMode 置为 0。

void COMP_Init(COMPX COMPx, const COMP_InitType *COMP_InitStruct)按 COMP_InitStruct 中的参数初始化 COMP 外设。
源码注释
name    COMP_Init.
fun     Initializes the COMP peripheral according to the specified parameters in the COMP_InitStruct
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   COMP_InitStruct :
param   ClockSelect :
          - COMP_CLKSEL_SYSTEMCLK
          - COMP_CLKSEL_LSX
param   LowPoweMode :
          - COMP_CTRL_PWRMD_NORMAL
          - COMP_CTRL_PWRMD_LOWPWR
       -Blking :
            - COMP_BLKING_NO
            - COMP_BLKING_ATIM1_OC5
            - COMP_BLKING_ATIM2_OC5
            - COMP_BLKING_ATIM1_OC4
            - COMP_BLKING_GTIM1_OC3
            - COMP_BLKING_GTIM2_OC3
            - COMP_BLKING_ATIM2_OC1
       -DoubleHyst :
            - COMP_DOUBLEHYST_EN
            - COMP_DOUBLEHYST_DIS
       -Hyst :
          - COMP_HYST_NO
          - COMP_HYST_LOW
          - COMP_HYST_MID
          - COMP_HYST_HIGH
       -PolRev :
          - COMP_OUTPOL_REV
          - COMP_OUTPOL_NREV
       -InpSel :
           comp1 inp sel
            - COMP1_INPSEL_PA0
            - COMP1_INPSEL_PA1
            - COMP1_INPSEL_PA2
            - COMP1_INPSEL_PA3
            - COMP1_INPSEL_PA6
            - COMP1_INPSEL_PA12
            - COMP1_INPSEL_PB2
            - COMP1_INPSEL_PB3
            - COMP1_INPSEL_PB4
            - COMP1_INPSEL_PB10
            - COMP1_INPSEL_PC5
            - COMP1_INPSEL_VREF_VC1
           comp2 inp sel
            - COMP2_INPSEL_PA1
            - COMP2_INPSEL_PA3
            - COMP2_INPSEL_PA6
            - COMP2_INPSEL_PA7
            - COMP2_INPSEL_PA11
            - COMP2_INPSEL_PA15
            - COMP2_INPSEL_PB0
            - COMP2_INPSEL_PB4
            - COMP2_INPSEL_PB6
            - COMP2_INPSEL_PB7
            - COMP2_INPSEL_PB11
            - COMP2_INPSEL_PB12
            - COMP2_INPSEL_VREF_VC2
           comp3 inp sel
            - COMP3_INPSEL_PA5
            - COMP3_INPSEL_PA11
            - COMP3_INPSEL_PB0
            - COMP3_INPSEL_PB1
            - COMP3_INPSEL_PB11
            - COMP3_INPSEL_PB12
            - COMP3_INPSEL_PB14
            - COMP3_INPSEL_VREF_VC3
       -InmSel :
          comp1 inm sel
            - COMP1_INMSEL_PA0
            - COMP1_INMSEL_PA4
            - COMP1_INMSEL_PA5
            - COMP1_INMSEL_PB1
            - COMP1_INMSEL_PB5
            - COMP1_INMSEL_PC4
            - COMP1_INMSEL_VREF_VC1
           comp2 inm sel
            - COMP2_INMSEL_PA4
            - COMP2_INMSEL_PA2
            - COMP2_INMSEL_PA5
            - COMP2_INMSEL_PA6
            - COMP2_INMSEL_PB3
            - COMP2_INMSEL_PB7
            - COMP2_INMSEL_VREF_VC2
           comp3 inm sel
            - COMP3_INMSEL_PA5
            - COMP3_INMSEL_PA12
            - COMP3_INMSEL_PB1
            - COMP3_INMSEL_PB11
            - COMP3_INMSEL_PB14
            - COMP3_INMSEL_VREF_VC3
       -ClkPsc:
          Value can be set from 0 to 65535.
       -FilterEn:
          - ENABLE
          - DISABLE
       -Threshold:
          - this value must be greater than SAMPW / 2 .
       -SampWindow:
          - from 0 to 31.
       -En
          - ENABLE
          - DISABLE
return  none

使用提示: 实现先按位组合写入 FILC(SampWindow、Threshold、FilterEn)并写入 FILP(ClkPsc),再读改写 CTRL 配置时钟、模式、消隐、迟滞、极性与输入选择,最后按 En 置位或清除使能位。

void COMP_Enable(COMPX COMPx, FunctionalState Cmd)配置 COMPx 使能或禁用。
源码注释
name    COMP_Enable.
fun     Configures COMPx enable or disable.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   Cmd : new state of the COMP peripheral.
          - ENABLE
          - DISABLE
return  none
void COMP_SetInpSel(COMPX COMPx, COMP_CTRL_INPSEL VpSel)配置 COMP 正端输入选择。
源码注释
name    COMP_SetInpSel.
fun     Configures COMP inpsel input selection.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   VpSel :
       comp1 inp sel
            - COMP1_INPSEL_PA0
            - COMP1_INPSEL_PA1
            - COMP1_INPSEL_PA2
            - COMP1_INPSEL_PA3
            - COMP1_INPSEL_PA6
            - COMP1_INPSEL_PA12
            - COMP1_INPSEL_PB2
            - COMP1_INPSEL_PB3
            - COMP1_INPSEL_PB4
            - COMP1_INPSEL_PB10
            - COMP1_INPSEL_PC5
            - COMP1_INPSEL_VREF_VC1
       comp2 inp sel
            - COMP2_INPSEL_PA1
            - COMP2_INPSEL_PA3
            - COMP2_INPSEL_PA6
            - COMP2_INPSEL_PA7
            - COMP2_INPSEL_PA11
            - COMP2_INPSEL_PA15
            - COMP2_INPSEL_PB0
            - COMP2_INPSEL_PB4
            - COMP2_INPSEL_PB6
            - COMP2_INPSEL_PB7
            - COMP2_INPSEL_PB11
            - COMP2_INPSEL_PB12
            - COMP2_INPSEL_VREF_VC2
       comp3 inp sel
            - COMP3_INPSEL_PA5
            - COMP3_INPSEL_PA11
            - COMP3_INPSEL_PB0
            - COMP3_INPSEL_PB1
            - COMP3_INPSEL_PB11
            - COMP3_INPSEL_PB12
            - COMP3_INPSEL_PB14
            - COMP3_INPSEL_VREF_VC3
return  none
void COMP_SetInmSel(COMPX COMPx, COMP_CTRL_INMSEL VmSel)配置 COMP 负端输入选择。
源码注释
name    COMP_SetInmSel.
fun     Configures COMP inmsel input selection.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   VmSel :
          comp1 inm sel
            - COMP1_INMSEL_PA0
            - COMP1_INMSEL_PA4
            - COMP1_INMSEL_PA5
            - COMP1_INMSEL_PB1
            - COMP1_INMSEL_PB5
            - COMP1_INMSEL_PC4
            - COMP1_INMSEL_VREF_VC1
           comp2 inm sel
            - COMP2_INMSEL_PA4
            - COMP2_INMSEL_PA2
            - COMP2_INMSEL_PA5
            - COMP2_INMSEL_PA6
            - COMP2_INMSEL_PB3
            - COMP2_INMSEL_PB7
            - COMP2_INMSEL_VREF_VC2
           comp3 inm sel
            - COMP3_INMSEL_PA5
            - COMP3_INMSEL_PA12
            - COMP3_INMSEL_PB1
            - COMP3_INMSEL_PB11
            - COMP3_INMSEL_PB14
            - COMP3_INMSEL_VREF_VC3
return  none
void COMP_OutputPolarityConfig(COMPX COMPx, uint32_t POL)配置 COMP 输出信号极性是否反转。
源码注释
name    COMP_OutputPolarityConfig.
fun     Configures COMP output signal polarity overturn or not.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   POL :
          - COMP_OUTPOL_REV
          - COMP_OUTPOL_NREV
return  none

使用提示: 实现中 POL 不等于 COMP_OUTPOL_NREV 时置位 CTRL 的 POL,否则清除该位。

void COMP_SetHyst(COMPX COMPx, COMP_CTRL_HYST HYST)配置 COMP 迟滞等级。
源码注释
name    COMP_SetHyst.
fun     Configure COMP hysteresis level.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   HYST :
          - COMP_HYST_NO
          - COMP_HYST_LOW
          - COMP_HYST_MID
          - COMP_HYST_HIGH
return  none
void COMP_EnableDoubleHyst(COMPX COMPx, FunctionalState Cmd)配置 COMP 双边迟滞的使能或禁用。
源码注释
name    COMP_EnableDoubleHyst.
fun     Configure COMP hysteresis double enable or disable.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void COMP_SetBlanking(COMPX COMPx, COMP_CTRL_BLKING BLK)配置定时器输出信号控制 COMP 消隐。
源码注释
name    COMP_SetBlanking.
fun     Configures timer output signal to control COMP Blking.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   BLK :
            - COMP_BLKING_NO
            - COMP_BLKING_ATIM1_OC5
            - COMP_BLKING_ATIM2_OC5
            - COMP_BLKING_ATIM1_OC4
            - COMP_BLKING_GTIM1_OC3
            - COMP_BLKING_GTIM2_OC3
            - COMP_BLKING_ATIM2_OC1
return  none
void COMP_SetFilterControl(COMPX COMPx, uint8_t FilEn, uint8_t TheresNum, uint8_t SampPW)配置 COMP 滤波器参数。
源码注释
name    COMP_SetFilterControl.
fun     Configure the COMP filter value.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   FilEn:
          - ENABLE.
          - DISABLE.
param   TheresNum:
          - this value must be greater than SAMPW / 2 .
param   SampPW:
          - from 0 to 31.
return  none

使用提示: 实现直接改写 FILC,不清除其它位:SampPW 写入 SAMPW、TheresNum 写入 THRESH、FilEn 写入 FILEN。

void COMP_SetFilterPrescaler(COMPX COMPx, uint16_t FilPreVal)配置 COMP 低通滤波时钟预分频。
源码注释
name    COMP_SetFilterPrescaler.
fun     Configure The COMP low filter prescale.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   FilPreVal:
          -  Value can be set from 0 to 65535.
return  none
void COMP_WindowModeEnable(uint32_t WinModeEn, FunctionalState Cmd)配置 COMPx 窗口模式使能或禁用。
源码注释
name    COMP_WindowModeEnable.
fun     Configures COMPx window mode enable or disable.
param   WinModeEn :
          - COMP_WINMODE_CMP12MD
          - COMP_WINMODE_CMP23MD
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void COMP_SetLock(uint32_t Lock)配置锁定哪些 COMPx。
源码注释
name    COMP_SetLock.
fun     Configures which COMPx will be Locked.
param   Lock :
          - COMP1_LOCK
          - COMP2_LOCK
          - COMP3_LOCK
return  none

使用提示: 实现按位或写入 LOCK;锁定位仅写一次,置位后只有系统复位才能清除。

void COMP_StopOrLowpower32KClkSel(COMPX COMPx, FunctionalState Cmd)选择 LSx 作为 COMPx 工作时钟的使能或禁用。
源码注释
name    COMP_StopOrLowpower32KClkSel.
fun     Select LSx as COMPx operation clock enable or disable.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   Cmd :
          - ENABLE : Select LSx as COMPx operation clock;
          - DISABLE : Select high speed clock as COMPx operation clock;
return  none
void COMP_StopOrLowpowerMode(COMPX COMPx, FunctionalState Cmd)配置 COMPx 低功耗模式使能或禁用。
源码注释
name    COMP_StopOrLowpowerMode.
fun     Configures COMPx low power mode enable or disable.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
param   Cmd :
          - ENABLE : Select low power mode for COMPx;
          - DISABLE : Select normal mode for COMPx;
return  none
void COMP_SetRefScl(uint8_t Vv3Trim, bool Vv3En, uint8_t Vv2Trim, bool Vv2En, uint8_t Vv1Trim, bool Vv1En)配置 COMP 参考电压。
源码注释
name    COMP_SetRefScl.
fun     Configures the COMP reference voltage.
param   Vv3Trim :
          - Value can be set from 0 to 255.
param   Vv3En :
          - false
          - true
param   Vv2Trim :
          - Value can be set from 0 to 255.
param   Vv2En :
          - false
          - true
param   Vv1Trim :
          - Value can be set from 0 to 255.
param   Vv1En :
          - false
          - true
return  none

使用提示: 实现把三路参考分别写入 INVREF1、INVREF2、INVREF3,位 0 为使能、位 8:1 为对应的 Trim 值。

FlagStatus COMP_GetOutStatus(COMPX COMPx)获取 COMPx 输出状态。
源码注释
name    COMP_GetOutStatus.
fun     Get COMPx output status.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
return  FlagStatus:
          - SET
          - RESET

使用提示: 实现读取该比较器 CTRL 的 OUT 位,为 1 返回 SET,为 0 返回 RESET。

void COMP_SetIntEn(uint32_t IntEn, FunctionalState Cmd)配置 COMPx 中断使能或禁用。
源码注释
name    COMP_SetIntEn.
fun     Configures COMPx interrupt enable or disable.
param   IntEn :
          - COMP_INTEN_CMP1IEN
          - COMP_INTEN_CMP2IEN
          - COMP_INTEN_CMP3IEN
param   Cmd :
          - ENABLE
          - DISABLE
return  none
FlagStatus COMP_GetIntStsOneComp(COMPX COMPx)获取 COMPx 中断状态。
源码注释
name    COMP_GetIntStsOneComp.
fun     Get COMPx interrupt Status.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
return  FlagStatus:
          - RESET : COMPx Interrupt status is reset;
          - SET   : COMPx Interrupt status is set;

使用提示: 实现读取 INTSTS 中与 COMPx 对应的那一位。

void COMP_ClearIntStsOneComp(COMPX COMPx)清除 COMPx 中断状态。
源码注释
name    COMP_ClearIntStsOneComp.
fun     Clear COMPx interrupt Status.
param   COMPx :
          - COMP1
          - COMP2
          - COMP3
return  none

使用提示: 实现把 INTSTS 中与 COMPx 对应的位写 1、其余位写 0,该位为写 1 清零。

5.3.3 Demo 示例说明

本节说明 COMP 的 2 个示例:COMP_OUT 用内部参考电压与滤波配置 COMP1,把比较结果从 PA11 输出并触发中断;CompBreak 把 COMP1 的输出接到 ATIM1、ATIM2 的刹车输入,比较器输出为低时封锁 PWM 波形。

5.3.3.1 COMP_OUT 比较器输出

工程目录: projects/n32g41x_EVAL/examples/COMP/COMP_OUT/

使能 COMP 与滤波器时钟→配置 PB10、PB1 为模拟输入,PA11 为复用推挽输出→配置 COMP1 的正负输入端、滤波与内部参考电压并开启中断→主循环让 PB2、PB3 交替输出高低电平改变 INP 与 INM→比较结果由 PA11 输出并在变化时触发中断

项目 源码解读
功能 用内部参考电压与滤波配置 COMP1,把 INP(PB10)与 INM(PB1)的比较结果从 PA11 输出,并在结果变化时通过 EXTI Line21 触发 COMP1 中断。
源码组成 src/main.c:main 与 RCC_Configuration、NVIC_Configuration、GPIO_Configuration、COMP_Configuration、ChangeVmVp;
inc/main.h:引脚与复用宏、函数声明;
src/n32g41x_it.c、inc/n32g41x_it.h:COMP123_IRQHandler 等中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 COMP1 INP 为 PB10、INM 为 PB1,均配为 GPIO_MODE_ANALOG;
OUT 为 PA11,配为 GPIO_MODE_AF_PP,复用值为 GPIO_AF7;
SampWindow=30、Threshold=18,滤波使能由 COMP_StructInit 默认置 DISABLE;
参考电压 COMP_SetRefScl(0, false, 0, false, 32, true) 只启用 VREF_VC1;
脉冲引脚 PB2、PB3 为推挽输出;
EXTI Line21 上升沿触发,NVIC 通道 COMP123_IRQn 的抢占与子优先级均为 0;
日志串口 USART1 的 TX 为 PA9,波特率 115200。
系统时钟为 HSI+PLL,N32G412 为 80 MHz,N32G415 为 96 MHz。
程序与数据路径 main 调用 log_init,依次执行 RCC_Configuration、NVIC_Configuration、GPIO_Configuration、COMP_Configuration,随后进入 while(1) 反复调用 ChangeVmVp;
ChangeVmVp 用 GPIO_SetBits/GPIO_ResetBits 让 PB2(INP)与 PB3(INM)交替为高,COMP1 比较后由 PA11 输出,结果变化时进入 COMP123_IRQHandler。
主要 API COMP_SetRefScl、COMP_StructInit、COMP_Init、COMP_SetIntEn、COMP_Enable、GPIO_InitStruct、GPIO_InitPeripheral、GPIO_SetBits、GPIO_ResetBits、EXTI_InitPeripheral、NVIC_Init
验证方法 用飞线把 PB2 接到 PB10、PB3 接到 PB1 后运行程序,用示波器或逻辑分析仪观察 PA11:PB2 为高(INP > INM)时 PA11 输出高,PB2 为低(INP < INM)时 PA11 输出低;
结果变化时进入 COMP1 中断。
使用提示 COMP1 的 INP、INM 引脚须配置为模拟输入,OUT 引脚须配置为复用推挽并选择正确的 AF;
readme 列出的滤波窗口 18、阈值 12 与源码中的 SampWindow=30、Threshold=18 不一致,以源码取值为准。
开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1,支持 N32G412、N32G415。
核心代码解读与移植

示例沿比较器输出这条链路给出引脚宏、GPIO 模式、COMP1 配置与主循环的翻转逻辑。

数据路径: main → RCC_Configuration 打开 COMP 与 GPIO 时钟 → GPIO_Configuration 把 PB10、PB1 设为模拟输入、PA11 设为复用推挽 → COMP_Configuration 写 COMP1_FILC、COMP1_CTRL 与参考电压 → ChangeVmVp 翻转 PB2、PB3 → PA11 输出与 COMP123_IRQHandler

1. 用宏定义比较器与脉冲引脚。 inc/main.h 把 COMP1 的 INP 定义在 PB10、INM 定义在 PB1、OUT 定义在 PA11,并给出脉冲发生引脚 PB2、PB3。

inc/main.hinc/main.h
/* COMP1 INP pin: PB10 (analog) */
#define COMP1_INP_PIN             GPIO_PIN_10
#define COMP1_INP_GPIO            GPIOB

/* COMP1 INM pin: PB1 (analog) */
#define COMP1_INM_PIN             GPIO_PIN_1
#define COMP1_INM_GPIO            GPIOB

/* COMP1 OUT pin: PA11 */
#define COMP1_OUT_PIN             GPIO_PIN_11
#define COMP1_OUT_GPIO            GPIOA

#if defined(N32G412)
#define COMP1_OUT_AF              GPIO_AF7
#elif defined(N32G415)
#define COMP1_OUT_AF              GPIO_AF7
#endif

/* Pulse generator pins: PB2 -> connect to INP(PB10), PB3 -> connect to INM(PB1) */
#define PULSE_INP_PIN             GPIO_PIN_2
#define PULSE_INP_GPIO            GPIOB
#define PULSE_INM_PIN             GPIO_PIN_3
#define PULSE_INM_GPIO            GPIOB

条件编译对 N32G412 与 N32G415 都给出 GPIO_AF7;移植到其它板卡时同步核对 INP、INM、OUT 与脉冲引脚这组宏。

2. 按角色配置引脚模式。 GPIO_Configuration 复用同一个结构体:INP、INM 写模拟模式,OUT 写复用推挽并选 AF,脉冲引脚写推挽输出。

src/main.csrc/main.c · GPIO_Configuration
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStruct(&GPIO_InitStructure);

    /* COMP1 INP: PB10 - analog input */
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
    GPIO_InitStructure.Pin       = COMP1_INP_PIN;
    GPIO_InitPeripheral(COMP1_INP_GPIO, &GPIO_InitStructure);

    /* COMP1 INM: PB1 - analog input */
    GPIO_InitStructure.Pin = COMP1_INM_PIN;
    GPIO_InitPeripheral(COMP1_INM_GPIO, &GPIO_InitStructure);

    /* COMP1 OUT: PA11 - alternate push-pull */
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Pin            = COMP1_OUT_PIN;
    GPIO_InitStructure.GPIO_Alternate = COMP1_OUT_AF;
    GPIO_InitPeripheral(COMP1_OUT_GPIO, &GPIO_InitStructure);

    /* Pulse generator: PB2, PB3 - push-pull output */
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF0;
    GPIO_InitStructure.Pin            = PULSE_INP_PIN;
    GPIO_InitPeripheral(PULSE_INP_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = PULSE_INM_PIN;
    GPIO_InitPeripheral(PULSE_INM_GPIO, &GPIO_InitStructure);

GPIO_InitPeripheral 只在模拟与复用模式下写复用字段,PB2、PB3 的 GPIO_Alternate 因此不起作用;换引脚时同时改端口与复用值。

3. 配置 COMP1 与其中断。 COMP_Configuration 先启用内部参考电压,再用 COMP_StructInit 取默认值、填入输入与滤波参数后调用 COMP_Init,最后使能中断与比较器;NVIC_Configuration 把 EXTI Line21 与 COMP 中断通道接到 NVIC。

src/main.csrc/main.c · COMP_Configuration
    COMP_InitType COMP_Initial;

    /* Set internal reference voltage (VREF_VC1) */
    COMP_SetRefScl(0, false, 0, false, 32, true);

    /* Initialize COMP1 */
    COMP_StructInit(&COMP_Initial);
    COMP_Initial.InpSel     = COMP1_INPSEL_PB10;
    COMP_Initial.InmSel     = COMP1_INMSEL_PB1;
    COMP_Initial.SampWindow = 30;       /* (0~31) */
    COMP_Initial.Threshold  = 18;       /* should be > SampWindow/2 and < SampWindow */
    COMP_Init(COMP1, &COMP_Initial);

    /* Enable COMP1 interrupt */
    COMP_SetIntEn(COMP_INTEN_CMP1IEN, ENABLE);

    /* Enable COMP1 */
    COMP_Enable(COMP1, ENABLE);
src/main.csrc/main.c · NVIC_Configuration
    NVIC_InitType NVIC_InitStructure;
    EXTI_InitType EXTI_InitStructure;

    /* Clear COMP1 EXTI pending bit */
    EXTI_ClrITPendBit(EXTI_LINE21);

    /* Configure EXTI Line21 (COMP1) */
    EXTI_InitStruct(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line    = EXTI_LINE21;
    EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitPeripheral(&EXTI_InitStructure);

    /* Configure COMP1/2/3 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = COMP123_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

源码把 SampWindow 设为 30、Threshold 设为 18,而 readme 写着滤波窗口 18、阈值 12;Threshold 须大于 SampWindow/2(实际 15),移植时按此关系取整。

4. 主循环改变 INP、INM 电平。 ChangeVmVp 让 PB2、PB3 交替为高,用空循环延时,使 PA11 输出随之翻转。

src/main.csrc/main.c · ChangeVmVp
    uint32_t i;

    /* INP high, INM low -> COMP1 OUT = high */
    GPIO_SetBits(PULSE_INP_GPIO, PULSE_INP_PIN);
    GPIO_ResetBits(PULSE_INM_GPIO, PULSE_INM_PIN);
    for (i = 0; i < 1000; i++)
        ;

    /* INP low, INM high -> COMP1 OUT = low */
    GPIO_ResetBits(PULSE_INP_GPIO, PULSE_INP_PIN);
    GPIO_SetBits(PULSE_INM_GPIO, PULSE_INM_PIN);
    for (i = 0; i < 1000; i++)
        ;

翻转节奏由这两个 for 空循环的次数决定,观察波形时需要按需调整;PB2 必须飞线到 PB10、PB3 必须飞线到 PB1 才能形成实际输入。

对应源码: src/main.c、inc/main.h

5.3.3.2 CompBreak 比较器刹车

工程目录: projects/n32g41x_EVAL/examples/COMP/CompBreak/

使能 COMP、ATIM1 与 ATIM2 时钟→配置 PB10、PB1 为模拟输入,PB6 为比较器输出,PB2、PB3 为脉冲输出→配置 ATIM1 的 PWM、死区与刹车→把 COMP1 的输出接入 ATIM1、ATIM2 的刹车输入→主循环让 INP、INM 交替变化,比较器输出为低时封锁 PWM 波形

项目 源码解读
功能 把 COMP1 的输出作为 ATIM1、ATIM2 的刹车输入:INP(PB10)低于 INM(PB1)使比较器输出为低时触发刹车,封锁 ATIM1 的 PWM 波形,比较器输出恢复为高后波形恢复输出。
源码组成 src/main.c:main 与 RCC_Configuration、GPIO_CompConfiguration、GPIO_TimConfiguration、TIM_Initial、COMP_Configuration、ChangeVmVp;
inc/main.h:比较器与 ATIM1、ATIM2 的引脚与复用宏、函数声明;
src/n32g41x_it.c、inc/n32g41x_it.h:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 引脚:COMP1 INP 为 PB10、INM 为 PB1,均为模拟输入;
OUT 为 PB6,复用推挽输出;
参考:只启用 VREF_VC1;
AF:ATIM1 CH1 为 PA8,N32G412 用 GPIO_AF2、N32G415 用 GPIO_AF1;
定时器:Prescaler=0、Period=50,CH1 Pulse 为 24、约 50% 占空比,TIM_OCMODE_PWM2、DeadTime=1、刹车 TIM_BREAK_IN_ENABLE、极性高、AutomaticOutput 使能;
刹车接入:COMP1 经 TIM_BreakInputSourceEnable 接入 ATIM1、ATIM2;
时钟:HSI+PLL,N32G412 80 MHz、N32G415 96 MHz。
程序与数据路径 main 依次执行 RCC_Configuration、GPIO_CompConfiguration、GPIO_TimConfiguration,调用 TIM_Initial(ATIM1) 配置并启动 ATIM1 PWM,再调用 COMP_Configuration 把 COMP1 接入两路定时器刹车并启用 COMP1,随后进入 while(1) 反复调用 ChangeVmVp;
ChangeVmVp 让 PB2(INP)与 PB3(INM)交替为高,COMP1 输出变低时 ATIM1 波形封锁,恢复后波形继续。
主要 API COMP_SetRefScl、COMP_StructInit、COMP_Init、COMP_Enable、TIM_BreakInputSourceEnable、TIM_InitTimBaseStruct、TIM_InitTimeBase、TIM_InitOcStruct、TIM_InitOc1、TIM_InitBkdtStruct、TIM_ConfigBkdt、TIM_Enable、TIM_EnableCtrlPwmOutputs、GPIO_InitPeripheral
验证方法 用飞线把 PB2 接到 PB10、PB3 接到 PB1,打开调试模式运行程序,用示波器或逻辑分析仪观察 PA8(ATIM1 CH1):PB2 电平高于 PB3 时 ATIM1 波形消失,反之波形正常输出。
使用提示 N32G41x 用 TIM_BreakInputSourceEnable 把 COMP 接到定时器刹车输入,不使用 COMP_SetOutTrig;
ATIM1 通道 1~4 均支持互补输出;
PA8、PA9 的 ATIM1 复用 AF 值在 N32G412 与 N32G415 间不同,已由条件编译宏切换。
硬件基于 N32G41x-STB,开发环境为 KEIL MDK-ARM V5.06 或 IAR EWARM V8.50。
核心代码解读与移植

示例沿比较器输出到定时器刹车的链路给出引脚宏、GPIO 与 COMP 配置、TIM 的 PWM 与刹车配置以及主循环的翻转逻辑。

数据路径: main → RCC_Configuration 打开 COMP 与 ATIM1、ATIM2 时钟 → GPIO_CompConfiguration 配置 PB10、PB1、PB6、PB2、PB3 → COMP_Configuration 写 COMP1 并调用 TIM_BreakInputSourceEnable → TIM_Initial 启动 ATIM1 PWM → ChangeVmVp 翻转 PB2、PB3 → 比较器输出经刹车输入封锁或恢复 PA8 波形

1. 用宏定义比较器与 ATIM1 引脚。 inc/main.h 给出 COMP1 的引脚并把 ATIM1 的 CH1 放在 PA8,按型号切换复用值。

inc/main.hinc/main.h
/* -------- COMP1 pins -------- */
/* COMP1 INP: PB10 (analog) */
#define COMP1_INP_PIN             GPIO_PIN_10
#define COMP1_INP_GPIO            GPIOB

/* COMP1 INM: PB1 (analog) */
#define COMP1_INM_PIN             GPIO_PIN_1
#define COMP1_INM_GPIO            GPIOB

/* COMP1 OUT: PB6 (for observation) */
#define COMP1_OUT_PIN             GPIO_PIN_6
#define COMP1_OUT_GPIO            GPIOB
#define COMP1_OUT_AF              GPIO_AF7    /* G412 & G415: PB6 COMP1_OUT = AF7 */

/* -------- ATIM1 (TIM1) pins -------- */
/* CH1: PA8 */
#define ATIM1_CH1_PIN             GPIO_PIN_8
#define ATIM1_CH1_GPIO            GPIOA
/* CH2: PA9 */
#define ATIM1_CH2_PIN             GPIO_PIN_9
#define ATIM1_CH2_GPIO            GPIOA
/* CH3: PA10 */
#define ATIM1_CH3_PIN             GPIO_PIN_10
#define ATIM1_CH3_GPIO            GPIOA
/* CH4: PA11 */
#define ATIM1_CH4_PIN             GPIO_PIN_11
#define ATIM1_CH4_GPIO            GPIOA

#if defined(N32G412)
/* G412: PA8=AF2, PA9=AF2 for ATIM1_CH1/CH2 */
#define ATIM1_CH1_AF              GPIO_AF2
#define ATIM1_CH2_AF              GPIO_AF2
#elif defined(N32G415)
/* G415: PA8=AF1, PA9=AF1 for ATIM1_CH1/CH2 */
#define ATIM1_CH1_AF              GPIO_AF1
#define ATIM1_CH2_AF              GPIO_AF1
#endif

PA8 的 ATIM1 CH1 在 N32G412 用 GPIO_AF2、在 N32G415 用 GPIO_AF1;移植到其它板卡时同步核对这组 AF 宏与观察引脚。

2. 配置比较器与定时器引脚并接入刹车。 GPIO_CompConfiguration 把 COMP1 的输入、输出与脉冲引脚按角色配置;COMP_Configuration 除写 COMP1 外,还用 TIM_BreakInputSourceEnable 把 COMP1 的输出接到 ATIM1、ATIM2 的刹车输入。

src/main.csrc/main.c · GPIO_CompConfiguration
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStruct(&GPIO_InitStructure);

    /* COMP1 INP: PB10 - analog input */
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
    GPIO_InitStructure.Pin       = COMP1_INP_PIN;
    GPIO_InitPeripheral(COMP1_INP_GPIO, &GPIO_InitStructure);

    /* COMP1 INM: PB1 - analog input */
    GPIO_InitStructure.Pin = COMP1_INM_PIN;
    GPIO_InitPeripheral(COMP1_INM_GPIO, &GPIO_InitStructure);

    /* COMP1 OUT: PB6 - alternate push-pull (for observation) */
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Pin            = COMP1_OUT_PIN;
    GPIO_InitStructure.GPIO_Alternate = COMP1_OUT_AF;
    GPIO_InitPeripheral(COMP1_OUT_GPIO, &GPIO_InitStructure);

    /* Pulse generator: PB2, PB3 - push-pull output */
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pin       = PULSE_INP_PIN;
    GPIO_InitPeripheral(PULSE_INP_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = PULSE_INM_PIN;
    GPIO_InitPeripheral(PULSE_INM_GPIO, &GPIO_InitStructure);
src/main.csrc/main.c · COMP_Configuration
    COMP_InitType COMP_Initial;

    /* Set internal reference voltage: Vv1Trim=32, Vv1En=true */
    COMP_SetRefScl(0, false, 0, false, 32, true);

    /* Initialize COMP1 */
    COMP_StructInit(&COMP_Initial);
    COMP_Initial.InpSel     = COMP1_INPSEL_PB10;
    COMP_Initial.InmSel     = COMP1_INMSEL_PB1;
    COMP_Initial.SampWindow = 30;       /* (0~31) */
    COMP_Initial.Threshold  = 18;       /* should be > SampWindow/2 and < SampWindow */
    COMP_Init(COMP1, &COMP_Initial);

    /* Enable COMP1 as break source for ATIM1 and ATIM2 */
    TIM_BreakInputSourceEnable(ATIM1, TIM_BREAK_COMP1, TIM_BREAK_COMP1P, ENABLE);
    TIM_BreakInputSourceEnable(ATIM2, TIM_BREAK_COMP1, TIM_BREAK_COMP1P, ENABLE);

    /* Enable COMP1 */
    COMP_Enable(COMP1, ENABLE);

COMP_Enable 放在接入刹车之后,比较器一旦输出变低即封锁 ATIM1;两路 TIM_BreakInputSourceEnable 分别对应 ATIM1 与 ATIM2,移植时需要与使用的定时器一一对应。

3. 配置 ATIM1 的 PWM、死区与刹车。 TIM_Initial 用 TIMx 参数同时适配 ATIM1、ATIM2:设时基、配 CH1 的 PWM2 输出,再经 TIM_ConfigBkdt 使能刹车并配置死区与自动输出。

src/main.csrc/main.c · TIM_Initial
    TimerPeriod   = 50;
    /* CH1 duty cycle 50% */
    Channel1Pulse = (uint16_t)(((uint32_t)5 * (TimerPeriod - 1)) / 10);

    /* Time Base configuration */
    TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.Prescaler   = 0;
    TIM_TimeBaseStructure.CounterMode = TIM_CNT_MODE_UP;
    TIM_TimeBaseStructure.Period      = TimerPeriod;
    TIM_TimeBaseStructure.ClkDiv      = 0;
    TIM_TimeBaseStructure.RepetCnt    = 0;
    TIM_InitTimeBase(TIMx, &TIM_TimeBaseStructure);

    /* Channel 1 Configuration in PWM mode */
    TIM_InitOcStruct(&TIM_OCInitStructure);
    TIM_OCInitStructure.OCMode       = TIM_OCMODE_PWM2;
    TIM_OCInitStructure.OutputState  = TIM_OUTPUT_STATE_ENABLE;
    TIM_OCInitStructure.OutputNState = TIM_OUTPUT_NSTATE_ENABLE;
    TIM_OCInitStructure.Pulse        = Channel1Pulse;
    TIM_OCInitStructure.OCPolarity   = TIM_OC_POLARITY_LOW;
    TIM_OCInitStructure.OCNPolarity  = TIM_OCN_POLARITY_HIGH;
    TIM_OCInitStructure.OCIdleState  = TIM_OC_IDLE_STATE_SET;
    TIM_OCInitStructure.OCNIdleState = TIM_OC_IDLE_STATE_RESET;
    TIM_InitOc1(TIMx, &TIM_OCInitStructure);

    /* Break and Dead Time configuration */
    TIM_InitBkdtStruct(&TIM_BDTRInitStructure);
    TIM_BDTRInitStructure.OSSRState       = TIM_OSSR_STATE_ENABLE;
    TIM_BDTRInitStructure.OSSIState       = TIM_OSSI_STATE_ENABLE;
    TIM_BDTRInitStructure.LOCKLevel       = TIM_LOCK_LEVEL_OFF;
    TIM_BDTRInitStructure.DeadTime        = 1;
    TIM_BDTRInitStructure.Break           = TIM_BREAK_IN_ENABLE;
    TIM_BDTRInitStructure.BreakPolarity   = TIM_BREAK_POLARITY_HIGH;
    TIM_BDTRInitStructure.AutomaticOutput = TIM_AUTO_OUTPUT_ENABLE;
    TIM_ConfigBkdt(TIMx, &TIM_BDTRInitStructure);

    /* Enable TIMx counter */
    TIM_Enable(TIMx, ENABLE);

    /* Enable TIMx Main Output */
    TIM_EnableCtrlPwmOutputs(TIMx, ENABLE);

Period 为 50、Pulse 由公式算出约 24,PWM 频率与占空比随这两个值和 Prescaler 联动;刹车极性为 TIM_BREAK_POLARITY_HIGH,与比较器输出的有效电平配合决定封锁条件。

4. 主循环改变 INP、INM 电平。 ChangeVmVp 让 PB2、PB3 交替为高,比较器输出随之变化,经刹车输入控制 ATIM1 波形。

src/main.csrc/main.c · ChangeVmVp
    uint32_t i;

    GPIO_SetBits(PULSE_INP_GPIO, PULSE_INP_PIN);
    GPIO_ResetBits(PULSE_INM_GPIO, PULSE_INM_PIN);
    for (i = 0; i < 1000; i++)
        ;

    GPIO_ResetBits(PULSE_INP_GPIO, PULSE_INP_PIN);
    GPIO_SetBits(PULSE_INM_GPIO, PULSE_INM_PIN);
    for (i = 0; i < 1000; i++)
        ;

翻转节奏由这两个空循环次数决定;PB2 与 PB10、PB3 与 PB1 之间的飞线是形成实际比较输入的前提,否则刹车不会触发。

对应源码: src/main.c、inc/main.h

5.3.4 注意与排障

场景 检查与建议 来源
阈值与采样窗口的取值关系 COMPx_FILC.THRESH[4:0] 必须大于 SAMPW[4:0]/2,采样窗口大小等于 SAMPW+1;
先用 COMP_SetFilterControl 或 COMP_Init 设好 SAMPW,再按大于其一半的要求给 THRESH。
用户手册
滤波与比较器的使能顺序 需先打开滤波使能 COMPx_FILC.FILEN,再打开比较器使能 COMPx_CTRL.EN;
比较器使能要在滤波(若启用)配置与使能完成之后进行。
用户手册
锁定后无法再配置 置位 COMP_LOCK 中对应的 CMPxLK 后,COMPx_CTRL、COMPx_FILC、COMPx_FILP 变为只读,只有系统复位才能解除锁定,需在锁定前完成全部配置。 用户手册
窗口模式共享输入引脚 使能窗口模式后,CMP12MD 让 COMP1、COMP2 的非反向输入端共享 PA1,CMP23MD 让 COMP2、COMP3 共享 PA11,端口输出为对应两比较器结果的异或。 用户手册
中断触发的电平条件 COMPx_CTRL.POL 不反转且中断使能时,INPSEL > INMSEL 使 OUT 被硬件置 1 并产生中断;
POL 反转时,INPSEL < INMSEL 时产生中断。
用户手册

N32G412、N32G415 系列勘误手册 V1.0.0(2026.6.30)的勘误列表只列出一行 A 版芯片条目,勘误链接列为空,未列出 COMP 相关条目。

国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计