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 参考
以下 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。
/* 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,脉冲引脚写推挽输出。
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。
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);
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 输出随之翻转。
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,按型号切换复用值。
/* -------- 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 的刹车输入。
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);
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 使能刹车并配置死区与自动输出。
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 波形。
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 相关条目。