5.3 COMP Guide
This chapter describes the file composition and the 21 public functions of the COMP driver in the N32G41x standard peripheral library: reset and initialization of the three comparators, input selection, polarity, hysteresis and blanking, filtering, window mode and lock, reference voltage, and output status and interrupt management. Two examples are included: COMP_OUT and CompBreak. Read the comparator operating modes, the interconnect and the register bit definitions together with the “Comparator (COMP)” chapter of the user manual; the break input of CompBreak also involves the ATIM timer chapters of the user manual, and take the errata sheet as the authority on known chip issues.
5.3.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_comp.h |
Defines the COMP_InitType structure and the input-selection, hysteresis, blanking, polarity, clock and reference-voltage enums and mask macros, and declares 21 public functions in the seven sections reset and initialization, input and output, hysteresis and blanking, filter, low-power and lock, voltage reference, and output and interrupt |
firmware/n32g41x_std_periph_driver/src/n32g41x_comp.c |
Implements those 21 functions: peripheral reset and read-modify-write configuration and status reads of the CTRL, FILC, FILP, LOCK, WINMODE, INTEN, INTSTS and INVREF registers |
projects/n32g41x_EVAL/examples/COMP/ |
COMP example root, containing the 2 examples COMP_OUT and CompBreak |
projects/n32g41x_EVAL/examples/COMP/COMP_OUT/ |
Composition of that example project directory: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32g41x_EVAL/bsp/ |
The shared log interface used by COMP_OUT: inc/log.h provides log_init and the log_info printing macros |
5.3.2 API reference
The following 21 public functions are listed in the declaration order of n32g41x_comp.h in 7 groups; each entry gives a summary and the original comment above the function in n32g41x_comp.c.
Reset and initialization
COMP_DeInit, COMP_StructInit, COMP_Init, COMP_Enable
Input and output configuration
COMP_SetInpSel, COMP_SetInmSel, COMP_OutputPolarityConfig
Hysteresis and blanking configuration
COMP_SetHyst, COMP_EnableDoubleHyst, COMP_SetBlanking
Filter configuration
COMP_SetFilterControl, COMP_SetFilterPrescaler
Low-power and lock configuration
COMP_WindowModeEnable, COMP_SetLock, COMP_StopOrLowpower32KClkSel, COMP_StopOrLowpowerMode
Voltage reference configuration
COMP_SetRefScl
Output status, interrupt and flag management
COMP_GetOutStatus, COMP_SetIntEn, COMP_GetIntStsOneComp, COMP_ClearIntStsOneComp
void COMP_DeInit(void)Reset the COMP registers.
name COMP_DeInit.
fun Reset the COMP registers.
return none
Use note: The implementation resets the COMP registers through the APB1 peripheral reset of COMP (RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP)).
void COMP_StructInit(COMP_InitType *COMP_InitStruct)Fills all COMP_InitType members with default value.
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
Use note: The implementation sets Blking, DoubleHyst, Hyst and PolRev to COMP_BLKING_NO, COMP_DOUBLEHYST_DIS, COMP_HYST_NO and COMP_OUTPOL_NREV, InpSel and InmSel to the corresponding reserved values, FilterEn and En to DISABLE, and SampWindow, Threshold, ClkPsc, ClockSelect and LowPoweMode to 0.
void COMP_Init(COMPX COMPx, const COMP_InitType *COMP_InitStruct)Initializes the COMP peripheral according to the specified parameters in the COMP_InitStruct
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
Use note: The implementation first writes the FILC bit fields (SampWindow, Threshold, FilterEn) and the FILP register (ClkPsc), then read-modify-writes CTRL for the clock, mode, blanking, hysteresis, polarity and input selection, and finally sets or clears the enable bit according to En.
void COMP_Enable(COMPX COMPx, FunctionalState Cmd)Configures COMPx enable or disable.
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)Configures COMP inpsel input selection.
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)Configures COMP inmsel input selection.
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)Configures COMP output signal polarity overturn or not.
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
Use note: In the implementation, when POL is not COMP_OUTPOL_NREV the POL bit of CTRL is set, otherwise it is cleared.
void COMP_SetHyst(COMPX COMPx, COMP_CTRL_HYST HYST)Configure COMP hysteresis level.
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)Configure COMP hysteresis double enable or disable.
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)Configures timer output signal to control COMP Blking.
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)Configure the COMP filter value.
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
Use note: The implementation overwrites FILC without preserving the other bits: SampPW goes to SAMPW, TheresNum to THRESH and FilEn to FILEN.
void COMP_SetFilterPrescaler(COMPX COMPx, uint16_t FilPreVal)Configure The COMP low filter prescale.
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)Configures COMPx window mode enable or disable.
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)Configures which COMPx will be Locked.
name COMP_SetLock.
fun Configures which COMPx will be Locked.
param Lock :
- COMP1_LOCK
- COMP2_LOCK
- COMP3_LOCK
return none
Use note: The implementation ORs Lock into LOCK; the lock bits are write-once and can only be cleared by a system reset.
void COMP_StopOrLowpower32KClkSel(COMPX COMPx, FunctionalState Cmd)Select LSx as COMPx operation clock enable or disable.
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)Configures COMPx low power mode enable or disable.
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)Configures the COMP reference voltage.
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
Use note: The implementation writes the three references into INVREF1, INVREF2 and INVREF3, with bit 0 as the enable and bits 8:1 as the corresponding Trim value.
FlagStatus COMP_GetOutStatus(COMPX COMPx)Get COMPx output status.
name COMP_GetOutStatus.
fun Get COMPx output status.
param COMPx :
- COMP1
- COMP2
- COMP3
return FlagStatus:
- SET
- RESET
Use note: The implementation reads the OUT bit of that comparator’s CTRL and returns SET for 1 and RESET for 0.
void COMP_SetIntEn(uint32_t IntEn, FunctionalState Cmd)Configures COMPx interrupt enable or disable.
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)Get COMPx interrupt Status.
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;
Use note: The implementation reads the bit of INTSTS that corresponds to COMPx.
void COMP_ClearIntStsOneComp(COMPX COMPx)Clear COMPx interrupt Status.
name COMP_ClearIntStsOneComp.
fun Clear COMPx interrupt Status.
param COMPx :
- COMP1
- COMP2
- COMP3
return none
Use note: The implementation writes 1 to the bit of INTSTS that corresponds to COMPx and 0 to the other bits; that bit is cleared by writing 1.
5.3.3 Demo descriptions
This section describes the 2 COMP examples: COMP_OUT configures COMP1 with an internal reference voltage and a filter and outputs the comparison result on PA11 while triggering an interrupt; CompBreak routes the COMP1 output to the break inputs of ATIM1 and ATIM2 and blocks the PWM waveform while the comparator output is low.
5.3.3.1 COMP_OUT comparator output
Example directory: projects/n32g41x_EVAL/examples/COMP/COMP_OUT/
Enable the COMP and filter clocks→Configure PB10 and PB1 as analog inputs and PA11 as an alternate push-pull output→Configure the COMP1 positive and negative inputs, the filter and the internal reference voltage and enable the interrupt→The main loop toggles PB2 and PB3 to drive INP and INM→The comparison result is output on PA11 and triggers an interrupt on a change
| Item | Source analysis |
|---|---|
| Function | Configures COMP1 with an internal reference voltage and a filter, outputs the comparison of INP (PB10) and INM (PB1) on PA11, and triggers the COMP1 interrupt through EXTI Line21 when the result changes. |
| Source files | src/main.c: main and RCC_Configuration, NVIC_Configuration, GPIO_Configuration, COMP_Configuration, ChangeVmVp;inc/main.h: pin and alternate-function macros and function declarations;src/n32g41x_it.c, inc/n32g41x_it.h: interrupt handlers such as COMP123_IRQHandler;readme.txt: function, environment and usage;MDK-ARM/, EWARM/: Keil and IAR projects. |
| Key configuration | COMP1 INP is PB10 and INM is PB1, both configured as GPIO_MODE_ANALOG;OUT is PA11, configured as GPIO_MODE_AF_PP with the alternate value GPIO_AF7;SampWindow=30 and Threshold=18, and the filter enable defaults to DISABLE from COMP_StructInit;the reference voltage COMP_SetRefScl(0, false, 0, false, 32, true) enables only VREF_VC1;the pulse pins PB2 and PB3 are push-pull outputs; EXTI Line21 triggers on the rising edge and the NVIC channel COMP123_IRQn has preemption and sub-priority 0;the log UART USART1 has TX on PA9 at 115200 bps. The system clock is HSI+PLL, 80 MHz for N32G412 and 96 MHz for N32G415. |
| Program and data path | main calls log_init, runs RCC_Configuration, NVIC_Configuration, GPIO_Configuration and COMP_Configuration in turn, then enters while(1) and repeatedly calls ChangeVmVp;ChangeVmVp uses GPIO_SetBits/GPIO_ResetBits to drive PB2 (INP) and PB3 (INM) high alternately, and after COMP1 compares them the result is output on PA11, with COMP123_IRQHandler entered when it changes. |
| Main APIs | COMP_SetRefScl, COMP_StructInit, COMP_Init, COMP_SetIntEn, COMP_Enable, GPIO_InitStruct, GPIO_InitPeripheral, GPIO_SetBits, GPIO_ResetBits, EXTI_InitPeripheral, NVIC_Init |
| Verification | Wire PB2 to PB10 and PB3 to PB1, run the program and observe PA11 with an oscilloscope or logic analyzer: PA11 is high when PB2 is high (INP > INM) and low when PB2 is low (INP < INM); the COMP1 interrupt is entered when the result changes. |
| Use note | The COMP1 INP and INM pins must be configured as analog inputs, and the OUT pin must be configured as alternate push-pull with the correct AF; the readme lists a filter window of 18 and a threshold of 12, while the source sets SampWindow=30 and Threshold=18, so take the source values.The development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1, supporting N32G412 and N32G415. |
Core-code walkthrough and porting
The example follows the comparator output path through the pin macros, the GPIO modes, the COMP1 configuration and the main-loop toggling.
Data path: main → RCC_Configuration enables the COMP and GPIO clocks → GPIO_Configuration sets PB10 and PB1 as analog inputs and PA11 as alternate push-pull → COMP_Configuration writes COMP1_FILC, COMP1_CTRL and the reference voltage → ChangeVmVp toggles PB2 and PB3 → PA11 output and COMP123_IRQHandler
1. Define the comparator and pulse pins with macros. inc/main.h places the COMP1 INP on PB10, INM on PB1 and OUT on PA11, and gives the pulse generator pins PB2 and 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
The conditional compilation gives GPIO_AF7 for both N32G412 and N32G415; when porting to another board, check the INP, INM, OUT and pulse pin macros together.
2. Configure the pin modes by role. GPIO_Configuration reuses one structure: INP and INM get the analog mode, OUT gets alternate push-pull with the AF, and the pulse pins get push-pull output.
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 writes the alternate field only in the analog and alternate modes, so GPIO_Alternate has no effect for PB2 and PB3; change the port and the alternate value together when moving the pins.
3. Configure COMP1 and its interrupt. COMP_Configuration first enables the internal reference voltage, then takes the defaults with COMP_StructInit, fills in the input and filter parameters and calls COMP_Init, and finally enables the interrupt and the comparator; NVIC_Configuration connects EXTI Line21 and the COMP interrupt channel to the 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);
The source sets SampWindow to 30 and Threshold to 18 while the readme states a filter window of 18 and a threshold of 12; Threshold must be greater than SampWindow/2 (15 here), so keep this relation when porting.
4. Change the INP and INM levels in the main loop. ChangeVmVp drives PB2 and PB3 high alternately and delays with empty loops, so the PA11 output flips accordingly.
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++)
;
The toggling pace is set by the iteration count of the two empty loops and must be adjusted for waveform observation; PB2 must be wired to PB10 and PB3 to PB1 to form the actual inputs.
Corresponding source files: src/main.c, inc/main.h
5.3.3.2 CompBreak comparator break
Example directory: projects/n32g41x_EVAL/examples/COMP/CompBreak/
Enable the COMP, ATIM1 and ATIM2 clocks→Configure PB10 and PB1 as analog inputs, PB6 as the comparator output and PB2 and PB3 as pulse outputs→Configure the ATIM1 PWM, dead time and break→Route the COMP1 output to the break inputs of ATIM1 and ATIM2→The main loop alternates INP and INM so that a low comparator output blocks the PWM waveform
| Item | Source analysis |
|---|---|
| Function | Uses the COMP1 output as the break input of ATIM1 and ATIM2: when INP (PB10) is lower than INM (PB1) the comparator output goes low, the break is triggered and the ATIM1 PWM waveform is blocked; the waveform is restored when the comparator output goes high again. |
| Source files | src/main.c: main and RCC_Configuration, GPIO_CompConfiguration, GPIO_TimConfiguration, TIM_Initial, COMP_Configuration, ChangeVmVp;inc/main.h: comparator and ATIM1, ATIM2 pin and alternate-function macros and function declarations;src/n32g41x_it.c, inc/n32g41x_it.h: interrupt handlers;readme.txt: function, environment and usage;MDK-ARM/, EWARM/: Keil and IAR projects. |
| Key configuration | Pins: COMP1 INP is PB10 and INM is PB1, both analog inputs; OUT is PB6, an alternate push-pull output; Reference: enables only VREF_VC1; AF: ATIM1 CH1 is PA8, GPIO_AF2 for N32G412 and GPIO_AF1 for N32G415;Timer: Prescaler=0 and Period=50, CH1 Pulse 24 for about 50% duty, TIM_OCMODE_PWM2, DeadTime=1, break TIM_BREAK_IN_ENABLE with high polarity and AutomaticOutput enabled;Break input: COMP1 connected to the ATIM1 and ATIM2 breaks through TIM_BreakInputSourceEnable;Clock: HSI+PLL, 80 MHz for N32G412 and 96 MHz for N32G415. |
| Program and data path | main runs RCC_Configuration, GPIO_CompConfiguration and GPIO_TimConfiguration in turn, calls TIM_Initial(ATIM1) to configure and start the ATIM1 PWM, then calls COMP_Configuration to connect COMP1 to the two timer breaks and enable COMP1, and enters while(1) and repeatedly calls ChangeVmVp;ChangeVmVp drives PB2 (INP) and PB3 (INM) high alternately so that the ATIM1 waveform is blocked while the COMP1 output is low and continues after it recovers. |
| Main APIs | 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 |
| Verification | Wire PB2 to PB10 and PB3 to PB1, run the program in debug mode and observe PA8 (ATIM1 CH1) with an oscilloscope or logic analyzer: the ATIM1 waveform disappears when the PB2 level is higher than PB3, and is output normally otherwise. |
| Use note | N32G41x uses TIM_BreakInputSourceEnable to connect COMP to a timer break input and does not use COMP_SetOutTrig;ATIM1 channels 1 to 4 all support complementary output; the ATIM1 alternate-function AF values of PA8 and PA9 differ between N32G412 and N32G415 and are switched by conditional compilation macros. The hardware is based on N32G41x-STB and the development environment is KEIL MDK-ARM V5.06 or IAR EWARM V8.50. |
Core-code walkthrough and porting
The example follows the path from the comparator output to the timer break through the pin macros, the GPIO and COMP configuration, the TIM PWM and break configuration and the main-loop toggling.
Data path: main → RCC_Configuration enables the COMP and the ATIM1 and ATIM2 clocks → GPIO_CompConfiguration configures PB10, PB1, PB6, PB2 and PB3 → COMP_Configuration writes COMP1 and calls TIM_BreakInputSourceEnable → TIM_Initial starts the ATIM1 PWM → ChangeVmVp toggles PB2 and PB3 → the comparator output blocks or restores the PA8 waveform through the break input
1. Define the comparator and ATIM1 pins with macros. inc/main.h gives the COMP1 pins and places ATIM1 CH1 on PA8, switching the alternate value by model.
/* -------- 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
ATIM1 CH1 on PA8 uses GPIO_AF2 for N32G412 and GPIO_AF1 for N32G415; when porting to another board, check this group of AF macros and the observation pin together.
2. Configure the comparator and timer pins and connect the break. GPIO_CompConfiguration configures the COMP1 inputs, output and pulse pins by role; COMP_Configuration writes COMP1 and uses TIM_BreakInputSourceEnable to connect the COMP1 output to the ATIM1 and ATIM2 break inputs.
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 comes after the break connection, so the break is taken as soon as the comparator output goes low; the two TIM_BreakInputSourceEnable calls correspond to ATIM1 and ATIM2 and must match the timers in use when porting.
3. Configure the ATIM1 PWM, dead time and break. TIM_Initial uses the TIMx parameter to serve both ATIM1 and ATIM2: it sets the time base, configures the CH1 PWM2 output, and then enables the break and sets the dead time and automatic output through 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 is 50 and the computed Pulse is about 24, so the PWM frequency and duty follow these two values and Prescaler; the break polarity is TIM_BREAK_POLARITY_HIGH and, together with the active level of the comparator output, determines the blocking condition.
4. Change the INP and INM levels in the main loop. ChangeVmVp drives PB2 and PB3 high alternately so the comparator output changes and the ATIM1 waveform is controlled through the break input.
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++)
;
The toggling pace is set by the iteration count of the two empty loops; the jumper wires between PB2 and PB10 and between PB3 and PB1 are the precondition for the actual comparison input, otherwise the break is never triggered.
Corresponding source files: src/main.c, inc/main.h
5.3.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Threshold and sampling window relation | COMPx_FILC.THRESH[4:0] must be greater than SAMPW[4:0]/2, and the sampling window size is SAMPW+1;set SAMPW first with COMP_SetFilterControl or COMP_Init, then give THRESH a value greater than half of it. |
User manual |
| Enable order of the filter and the comparator | Enable the filter through COMPx_FILC.FILEN before enabling the comparator through COMPx_CTRL.EN;the comparator must be enabled after the filter (if used) has been configured and enabled. |
User manual |
| No further configuration after locking | After setting the corresponding CMPxLK bit in COMP_LOCK, COMPx_CTRL, COMPx_FILC and COMPx_FILP become read-only and only a system reset releases the lock, so complete all configuration before locking. |
User manual |
| Shared input pins in window mode | After window mode is enabled, CMP12MD makes COMP1 and COMP2 share PA1 on their non-inverting inputs and CMP23MD makes COMP2 and COMP3 share PA11, with the port output being the exclusive OR of the two comparator results. |
User manual |
| Interrupt trigger level condition | With COMPx_CTRL.POL not inverted and the interrupt enabled, INPSEL > INMSEL sets OUT to 1 in hardware and produces an interrupt;with POL inverted the interrupt is produced when INPSEL < INMSEL. |
User manual |
The N32G412 and N32G415 series errata sheet V1.0.0 (2026.6.30) lists a single row for revision A chips with an empty errata link column, and gives no COMP-related entries.