5.1 ADC Guide
This chapter describes the file composition and the 44 public functions of the ADC driver in the N32G41x standard peripheral library: reset and initialization, regular-channel and injected-channel conversion control, software and external trigger configuration, multi-ADC cooperation, the analog watchdog, the temperature sensor and internal reference, oversampling, offset compensation, interrupt and flag management and the ADC clock configuration; it also describes 9 example projects. Read the register bit definitions, the dual-ADC modes and the sampling timing together with the “Analog/digital converter (ADC)” chapter of the user manual, and take the errata sheet as the authority on known chip issues.
5.1.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_adc.h |
Defines the ADC_InitType and ADC_OffsetType structures and the configuration macros for work mode, channels, sample times, trigger sources, the analog watchdog, oversampling and offset, and declares the 44 public functions of the API reference in eleven sections |
firmware/n32g41x_std_periph_driver/src/n32g41x_adc.c |
Implements those 44 functions: power-up and ready polling, sequencer length and channel rank writes, software and external trigger starts, analog watchdog threshold and channel configuration, oversampling and offset register configuration, and flag and interrupt management |
projects/n32g41x_EVAL/examples/ADC/ |
ADC example root directory, holding the 9 examples ADC_Offset, ADC_SingleRead, ADC_TEMP, ADC1_DMA, ADC1_Oversampling, AnalogWatchdog, ExtLinesTrigger, RegSimul_DualMode and TIMTrigger_AutoInjection |
projects/n32g41x_EVAL/examples/ADC/ADC1_DMA/ |
Layout of that example: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32g41x_EVAL/bsp/ |
Board support files shared by the examples: evaluation-board LED and key definitions, a millisecond delay function and a UART logging interface |
5.1.2 API reference
The following 44 public functions are listed in the declaration order of n32g41x_adc.h in 11 groups; each entry gives a summary and the original comment above the function in n32g41x_adc.c.
Reset and initialization
ADC_DeInit, ADC_Init, ADC_InitStruct, ADC_Enable, ADC_EnableDMA
Regular conversion control
ADC_EnableSoftwareStartConv, ADC_GetSoftwareStartConvStatus, ADC_StopRegularConv, ADC_ConfigRegularChannel, ADC_GetDat, ADC_GetMutiModeConversionDat, ADC_ConfigDiscModeChannelCount, ADC_EnableDiscMode
Injected conversion control
ADC_EnableSoftwareStartInjectedConv, ADC_GetSoftwareStartInjectedConvCmdStatus, ADC_StopInjectedConv, ADC_ConfigInjectedChannel, ADC_ConfigInjectedSequencerLength, ADC_GetInjectedConversionDat, ADC_EnableAutoInjectedConv, ADC_EnableInjectedDiscMode
Trigger configuration
ADC_SetRegularTriggerEdge, ADC_SetInjectTriggerEdge, ADC_ConfigExternalTrigInjectedConv, ADC_ConfigExternalTrigRegularConv, ADC_ConfigRegularExtLineTrigSource, ADC_ConfigInjectedExtLineTrigSource
Multi-mode configuration
ADC_SetMultiTwoSamplingDelay
Analog watchdog
ADC_ConfigAnalogWatchdogWorkChannelType, ADC_ConfigAnalogWatchdogThresholds, ADC_ConfigAnalogWatchdogSingleChannel
Temperature sensor and internal reference
ADC_EnableTempSensorVrefint, Reference_VoltageSelect
Oversampling
ADC_ConfigOverSamplingRatioAndShift, ADC_SetOverSamplingScope, ADC_EnableOverSamplingDiscont
Offset
ADC_SetOffsetConfig, ADC_GetOffsetConfig
Interrupt and flag management
ADC_GetFlagStatus, ADC_ClearFlag, ADC_ConfigInt, ADC_GetIntStatus, ADC_ClearIntPendingBit
Clock configuration
ADC_ClockModeConfig
void ADC_DeInit(const ADC_Module *ADCx)Reset the ADC registers.
name ADC_DeInit.
fun Reset the ADC registers.
param ADCx :
- ADC1
- ADC2
return none
void ADC_Init(ADC_Module *ADCx, const ADC_InitType *ADC_InitParam)Initializes the ADCx peripheral according to the specified parameters in the ADC_InitParam.
name ADC_Init.
fun Initializes the ADCx peripheral according to the specified parameters in the ADC_InitParam.
param ADCx :
- ADC1
- ADC2
param ADC_InitParam :
- WorkMode
- ADC_WORKMODE_INDEPENDENT
- ADC_WORKMODE_DUAL_REG_INJECT_SIMULT
- ADC_WORKMODE_DUAL_INJ_SIMULT
- ADC_WORKMODE_DUAL_REG_SIMULT
- ADC_WORKMODE_DUAL_INTERL
- ADC_WORKMODE_DUAL_ALTER_TRIG
- MultiChEn
- ENABLE
- DISABLE
- ContinueConvEn
- ENABLE
- DISABLE
- ExtTrigSelect
- ADC_EXT_TRIG_REG_CONV_ATIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_ATIM1_TRGO2
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC1
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC2
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC3
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC4
- ADC_EXT_TRIG_REG_CONV_ATIM2_TRGO
- ADC_EXT_TRIG_REG_CONV_ATIM2_CC1
- ADC_EXT_TRIG_REG_CONV_ATIM2_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM1_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM1_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM2_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM2_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM2_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM3_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM4_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC4
- ADC_EXT_TRIG_REG_CONV_BTIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_EXT_INT0_15
- ADC_EXT_TRIG_REG_CONV_SOFTWARE
- DatAlign
- ADC_DAT_ALIGN_R
- ADC_DAT_ALIGN_L
- ChsNumber: This parameter must be between 1 to 16.
return none
void ADC_InitStruct(ADC_InitType *ADC_InitStructure)Fills all ADC_InitStructure member with default value.
name ADC_InitStruct.
fun Fills all ADC_InitStructure member with default value.
param ADC_InitStructure :
- WorkMode
- MultiChEn
- ContinueConvEn
- ExtTrigSelect
- DatAlign
- ChsNumber
return none
void ADC_Enable(ADC_Module *ADCx, FunctionalState Cmd)Configures the specified ADC enable or disable.
name ADC_Enable.
fun Configures the specified ADC enable or disable.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_EnableDMA(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the specified ADC DMA request.
name ADC_EnableDMA.
fun Enables or disables the specified ADC DMA request.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_EnableSoftwareStartConv(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the selected ADC software start conversion.
name ADC_EnableSoftwareStartConv.
fun Enables or disables the selected ADC software start conversion.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
FlagStatus ADC_GetSoftwareStartConvStatus(const ADC_Module *ADCx)Gets the selected ADC Software start conversion Status.
name ADC_GetSoftwareStartConvStatus.
fun Gets the selected ADC Software start conversion Status.
param ADCx :
- ADC1
- ADC2
return The new state of ADC software start conversion (SET or RESET).
void ADC_StopRegularConv(ADC_Module *ADCx)Stop ADC group regular channels conversion.
name ADC_StopRegularConv.
fun Stop ADC group regular channels conversion.
param ADCx :
- ADC1
- ADC2
return none
void ADC_ConfigRegularChannel(ADC_Module *ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)Configures for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
name ADC_ConfigRegularChannel.
fun Configures for the selected ADC regular channel its corresponding
rank in the sequencer and its sample time.
param ADCx :
- ADC1
- ADC2
param ADC_Channel :
- ADC_CH_0 : ADC Channel0 selected
- ADC_CH_1 : ADC Channel1 selected
- ADC_CH_2 : ADC Channel2 selected
- ADC_CH_3 : ADC Channel3 selected
- ADC_CH_4 : ADC Channel4 selected
- ADC_CH_5 : ADC Channel5 selected
- ADC_CH_6 : ADC Channel6 selected
- ADC_CH_7 : ADC Channel7 selected
- ADC_CH_8 : ADC Channel8 selected
- ADC_CH_9 : ADC Channel9 selected
- ADC_CH_10 : ADC Channel10 selected
- ADC_CH_11 : ADC Channel11 selected
- ADC_CH_12 : ADC Channel12 selected
- ADC_CH_13 : ADC Channel13 selected
- ADC_CH_14 : ADC Channel14 selected
- ADC_CH_15 : ADC Channel15 selected
- ADC_CH_16 : ADC Channel16 selected
- ADC_CH_17 : ADC Channel17 selected
param Rank : The rank in the regular group sequencer. This parameter must be between 1 to 16.
param ADC_SampleTime : The sample time value to be set for the selected channel.
- ADC_SAMP_TIME_CYCLES_4
- ADC_SAMP_TIME_CYCLES_6
- ADC_SAMP_TIME_CYCLES_8
- ADC_SAMP_TIME_CYCLES_14
- ADC_SAMP_TIME_CYCLES_29
- ADC_SAMP_TIME_CYCLES_42
- ADC_SAMP_TIME_CYCLES_56
- ADC_SAMP_TIME_CYCLES_72
- ADC_SAMP_TIME_CYCLES_88
- ADC_SAMP_TIME_CYCLES_120
- ADC_SAMP_TIME_CYCLES_182
- ADC_SAMP_TIME_CYCLES_240
- ADC_SAMP_TIME_CYCLES_300
- ADC_SAMP_TIME_CYCLES_400
- ADC_SAMP_TIME_CYCLES_480
- ADC_SAMP_TIME_CYCLES_600
return none
uint16_t ADC_GetDat(const ADC_Module *ADCx)Get the last ADCx conversion result data for regular channel
name ADC_GetDat.
fun Get the last ADCx conversion result data for regular channel
param ADCx :
- ADC1
- ADC2
return The Data conversion value.
uint32_t ADC_GetMutiModeConversionDat(void)Get the last ADC conversion result data in dual-ADC mode.
name ADC_GetMutiModeConversionDat.
fun Get the last ADC conversion result data in dual-ADC mode.
return The Data conversion value in dual-ADC mode.
void ADC_ConfigDiscModeChannelCount(ADC_Module *ADCx, uint8_t Number)Configures the discontinuous numbers for the selected ADC regular group channels.
name ADC_ConfigDiscModeChannelCount.
fun Configures the discontinuous numbers for the selected ADC regular
group channels.
param ADCx :
- ADC1
- ADC2
param Number : specifies the discontinuous mode regular channel
count value. This number must be range from 1 to 8.
return none
void ADC_EnableDiscMode(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the discontinuous mode on regular group channel for the specified ADC.
name ADC_EnableDiscMode.
fun Enables or disables the discontinuous mode on regular group
channel for the specified ADC.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_EnableSoftwareStartInjectedConv(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the selected ADC start of the injected channels conversion.
name ADC_EnableSoftwareStartInjectedConv.
fun Enables or disables the selected ADC start of the injected channels conversion.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(const ADC_Module *ADCx)Gets the selected ADC Software start injected conversion Status.
name ADC_GetSoftwareStartInjectedConvCmdStatus.
fun Gets the selected ADC Software start injected conversion Status.
param ADCx :
- ADC1
- ADC2
return The new state of ADC software start injected conversion (SET or RESET).
void ADC_StopInjectedConv(ADC_Module *ADCx)Stop ADC group injected channels conversion.
name ADC_StopInjectedConv.
fun Stop ADC group injected channels conversion.
param ADCx :
- ADC1
- ADC2
return none
void ADC_ConfigInjectedChannel(ADC_Module *ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time.
name ADC_ConfigInjectedChannel.
fun Configures for the selected ADC injected channel its corresponding
rank in the sequencer and its sample time.
param ADCx :
- ADC1
- ADC2
param ADC_Channel :
- ADC_CH_0 : ADC Channel0 selected
- ADC_CH_1 : ADC Channel1 selected
- ADC_CH_2 : ADC Channel2 selected
- ADC_CH_3 : ADC Channel3 selected
- ADC_CH_4 : ADC Channel4 selected
- ADC_CH_5 : ADC Channel5 selected
- ADC_CH_6 : ADC Channel6 selected
- ADC_CH_7 : ADC Channel7 selected
- ADC_CH_8 : ADC Channel8 selected
- ADC_CH_9 : ADC Channel9 selected
- ADC_CH_10 : ADC Channel10 selected
- ADC_CH_11 : ADC Channel11 selected
- ADC_CH_12 : ADC Channel12 selected
- ADC_CH_13 : ADC Channel13 selected
- ADC_CH_14 : ADC Channel14 selected
- ADC_CH_15 : ADC Channel15 selected
- ADC_CH_16 : ADC Channel16 selected
- ADC_CH_17 : ADC Channel17 selected
param Rank : The rank in the injected group sequencer. This parameter must be between 1 to 4.
param ADC_SampleTime : The sample time value to be set for the selected channel.
- ADC_SAMP_TIME_CYCLES_4
- ADC_SAMP_TIME_CYCLES_6
- ADC_SAMP_TIME_CYCLES_8
- ADC_SAMP_TIME_CYCLES_14
- ADC_SAMP_TIME_CYCLES_29
- ADC_SAMP_TIME_CYCLES_42
- ADC_SAMP_TIME_CYCLES_56
- ADC_SAMP_TIME_CYCLES_72
- ADC_SAMP_TIME_CYCLES_88
- ADC_SAMP_TIME_CYCLES_120
- ADC_SAMP_TIME_CYCLES_182
- ADC_SAMP_TIME_CYCLES_240
- ADC_SAMP_TIME_CYCLES_300
- ADC_SAMP_TIME_CYCLES_400
- ADC_SAMP_TIME_CYCLES_480
- ADC_SAMP_TIME_CYCLES_600
return none
void ADC_ConfigInjectedSequencerLength(ADC_Module *ADCx, uint8_t Length)Configures the sequencer length for injected channels
name ADC_ConfigInjectedSequencerLength.
fun Configures the sequencer length for injected channels
param ADCx :
- ADC1
- ADC2
param Length : The sequencer length. This parameter must be a number between 1 to 4.
return none
uint16_t ADC_GetInjectedConversionDat(const ADC_Module *ADCx, uint8_t ADC_InjectedChannelOffset)Get the ADC injected channel conversion result.
name ADC_GetInjectedConversionDat.
fun Get the ADC injected channel conversion result.
param ADCx :
- ADC1
- ADC2
param ADC_InjectedChannelOffset :
- ADC_INJECT_DATA_OFFSET_1
- ADC_INJECT_DATA_OFFSET_2
- ADC_INJECT_DATA_OFFSET_3
- ADC_INJECT_DATA_OFFSET_4
return The data conversion value. this data is range 0 - 0xFFFF.
void ADC_EnableAutoInjectedConv(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the selected ADC automatic injected group conversion after regular one
name ADC_EnableAutoInjectedConv.
fun Enables or disables the selected ADC automatic injected group
conversion after regular one
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_EnableInjectedDiscMode(ADC_Module *ADCx, FunctionalState Cmd)Enables or disables the discontinuous mode on injected group channel for the specified ADC.
name ADC_EnableInjectedDiscMode.
fun Enables or disables the discontinuous mode on injected group
channel for the specified ADC.
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_SetRegularTriggerEdge(ADC_Module *ADCx, uint32_t ExternalRegularTriggerEdge)Set ADCx group regular conversion trigger polarity.
name ADC_SetRegularTriggerEdge.
fun Set ADCx group regular conversion trigger polarity.
param ADCx :
- ADC1
- ADC2
param ExternalRegularTriggerEdge :
- ADC_REG_TRIG_EXT_SOFTWARE
- ADC_REG_TRIG_EXT_RISING
- ADC_REG_TRIG_EXT_FALLING
- ADC_REG_TRIG_EXT_RISINGFALLING
return none
void ADC_SetInjectTriggerEdge(ADC_Module *ADCx, uint32_t ExternalInjectTriggerEdge)Set ADCx group injected conversion trigger polarity.
name ADC_SetInjectTriggerEdge.
fun Set ADCx group injected conversion trigger polarity.
param ADCx :
- ADC1
- ADC2
param ExternalInjectTriggerEdge :
- ADC_INJ_TRIG_EXT_SOFTWARE
- ADC_INJ_TRIG_EXT_RISING
- ADC_INJ_TRIG_EXT_FALLING
- ADC_INJ_TRIG_EXT_RISINGFALLING
return none
void ADC_ConfigExternalTrigInjectedConv(ADC_Module *ADCx, uint32_t ADC_ExternalTrigInjecConv)Configures the ADCx external trigger source for injected channels conversion.
name ADC_ConfigExternalTrigInjectedConv.
fun Configures the ADCx external trigger source for injected channels conversion.
param ADCx :
- ADC1
- ADC2
param ADC_ExternalTrigInjecConv :
- ADC_EXT_TRIG_INJ_CONV_ATIM1_TRGO
- ADC_EXT_TRIG_INJ_CONV_ATIM1_TRGO2
- ADC_EXT_TRIG_INJ_CONV_ATIM1_CC1
- ADC_EXT_TRIG_INJ_CONV_ATIM1_CC2
- ADC_EXT_TRIG_INJ_CONV_ATIM1_CC3
- ADC_EXT_TRIG_INJ_CONV_ATIM1_CC4
- ADC_EXT_TRIG_INJ_CONV_ATIM2_TRGO
- ADC_EXT_TRIG_INJ_CONV_ATIM2_CC1
- ADC_EXT_TRIG_INJ_CONV_ATIM2_CC4
- ADC_EXT_TRIG_INJ_CONV_GTIM1_TRGO
- ADC_EXT_TRIG_INJ_CONV_GTIM1_CC2
- ADC_EXT_TRIG_INJ_CONV_GTIM1_CC4
- ADC_EXT_TRIG_INJ_CONV_GTIM2_TRGO
- ADC_EXT_TRIG_INJ_CONV_GTIM2_CC1
- ADC_EXT_TRIG_INJ_CONV_GTIM2_CC4
- ADC_EXT_TRIG_INJ_CONV_GTIM3_TRGO
- ADC_EXT_TRIG_INJ_CONV_GTIM3_CC1
- ADC_EXT_TRIG_INJ_CONV_GTIM3_CC2
- ADC_EXT_TRIG_INJ_CONV_GTIM3_CC4
- ADC_EXT_TRIG_INJ_CONV_GTIM4_TRGO
- ADC_EXT_TRIG_INJ_CONV_GTIM4_CC1
- ADC_EXT_TRIG_INJ_CONV_GTIM4_CC2
- ADC_EXT_TRIG_INJ_CONV_GTIM4_CC4
- ADC_EXT_TRIG_INJ_CONV_BTIM1_TRGO
- ADC_EXT_TRIG_INJ_CONV_EXT_INT0_15
- ADC_EXT_TRIG_INJ_CONV_SOFTWARE
return none
void ADC_ConfigExternalTrigRegularConv(ADC_Module *ADCx, uint32_t ADC_ExternalTrigRegularConv)Configures the ADCx external trigger source for regular channels conversion.
name ADC_ConfigExternalTrigRegularConv.
fun Configures the ADCx external trigger source for regular channels conversion.
param ADCx :
- ADC1
- ADC2
param ADC_ExternalTrigRegularConv :
- ADC_EXT_TRIG_REG_CONV_ATIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_ATIM1_TRGO2
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC1
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC2
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC3
- ADC_EXT_TRIG_REG_CONV_ATIM1_CC4
- ADC_EXT_TRIG_REG_CONV_ATIM2_TRGO
- ADC_EXT_TRIG_REG_CONV_ATIM2_CC1
- ADC_EXT_TRIG_REG_CONV_ATIM2_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM1_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM1_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM2_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM2_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM2_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM3_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM3_CC4
- ADC_EXT_TRIG_REG_CONV_GTIM4_TRGO
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC1
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC2
- ADC_EXT_TRIG_REG_CONV_GTIM4_CC4
- ADC_EXT_TRIG_REG_CONV_BTIM1_TRGO
- ADC_EXT_TRIG_REG_CONV_EXT_INT0_15
- ADC_EXT_TRIG_REG_CONV_SOFTWARE
return none
void ADC_ConfigRegularExtLineTrigSource(ADC_Module *ADCx, uint32_t ADC_trigger)Configure ADC external line trigger source for regular channel.
name ADC_ConfigRegularExtLineTrigSource.
fun Configure ADC external line trigger source for regular channel.
param ADCx :
- ADC1
- ADC2
param ADC_trigger :
specifies the external line trigger source be configured.
- ADC_TRIG_EXTI_0
- ADC_TRIG_EXTI_1
- ADC_TRIG_EXTI_2
- ADC_TRIG_EXTI_3
- ADC_TRIG_EXTI_4
- ADC_TRIG_EXTI_5
- ADC_TRIG_EXTI_6
- ADC_TRIG_EXTI_7
- ADC_TRIG_EXTI_8
- ADC_TRIG_EXTI_9
- ADC_TRIG_EXTI_10
- ADC_TRIG_EXTI_11
- ADC_TRIG_EXTI_12
- ADC_TRIG_EXTI_13
- ADC_TRIG_EXTI_14
- ADC_TRIG_EXTI_15
return none
void ADC_ConfigInjectedExtLineTrigSource(ADC_Module *ADCx, uint32_t ADC_trigger)Configure ADC external line trigger source for injected channel.
name ADC_ConfigInjectedExtLineTrigSource.
fun Configure ADC external line trigger source for injected channel.
param ADCx :
- ADC1
- ADC2
param ADC_trigger :
specifies the external line trigger source be configured.
- ADC_TRIG_EXTI_0
- ADC_TRIG_EXTI_1
- ADC_TRIG_EXTI_2
- ADC_TRIG_EXTI_3
- ADC_TRIG_EXTI_4
- ADC_TRIG_EXTI_5
- ADC_TRIG_EXTI_6
- ADC_TRIG_EXTI_7
- ADC_TRIG_EXTI_8
- ADC_TRIG_EXTI_9
- ADC_TRIG_EXTI_10
- ADC_TRIG_EXTI_11
- ADC_TRIG_EXTI_12
- ADC_TRIG_EXTI_13
- ADC_TRIG_EXTI_14
- ADC_TRIG_EXTI_15
return none
void ADC_SetMultiTwoSamplingDelay(ADC_Module *ADCx, uint32_t MultiTwoSamplingDelay)Set ADC multimode delay between 2 sampling phases.
name ADC_SetMultiTwoSamplingDelay.
fun Set ADC multimode delay between 2 sampling phases.
param ADCx :
- ADC1
- ADC2
param MultiTwoSamplingDelay
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_1
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_2
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_3
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_4
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_5
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_6
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_7
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_8
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_9
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_10
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_11
- ADC_ADC_MULTI_TWOSMP_DELAY_CYCLE_12
return none
void ADC_ConfigAnalogWatchdogWorkChannelType(ADC_Module *ADCx, uint32_t ADC_AnalogWatchdog)Enables or disables the analog watchdog on single/all regular or injected channels.
name ADC_ConfigAnalogWatchdogWorkChannelType.
fun Enables or disables the analog watchdog on single/all regular or injected channels.
param ADCx :
- ADC1
- ADC2
param ADC_AnalogWatchdog :
- ADC_ANALOG_WTDG_NONE
- ADC_ANALOG_WTDG_SINGLEREG_ENABLE
- ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE
- ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE
- ADC_ANALOG_WTDG_ALLREG_ENABLE
- ADC_ANALOG_WTDG_ALLINJEC_ENABLE
- ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE
return none.
void ADC_ConfigAnalogWatchdogThresholds(ADC_Module *ADCx, uint16_t HighThreshold, uint16_t LowThreshold)Configures the high and low thresholds of the analog watchdog .
name ADC_ConfigAnalogWatchdogThresholds.
fun Configures the high and low thresholds of the analog watchdog .
param ADCx :
- ADC1
- ADC2
param HighThreshold : the ADC analog watchdog high threshold value.
- This parameter must be a 12bit value.
param LowThreshold : the ADC analog watchdog low threshold value.
- This parameter must be a 12bit value.
return none
void ADC_ConfigAnalogWatchdogSingleChannel(ADC_Module *ADCx, uint8_t ADC_Channel)Configures the analog watchdog guarded on single channel.
name ADC_ConfigAnalogWatchdogSingleChannel.
fun Configures the analog watchdog guarded on single channel.
param ADCx :
- ADC1
- ADC2
param ADC_Channel :
- ADC_CH_0 : ADC Channel0 selected
- ADC_CH_1 : ADC Channel1 selected
- ADC_CH_2 : ADC Channel2 selected
- ADC_CH_3 : ADC Channel3 selected
- ADC_CH_4 : ADC Channel4 selected
- ADC_CH_5 : ADC Channel5 selected
- ADC_CH_6 : ADC Channel6 selected
- ADC_CH_7 : ADC Channel7 selected
- ADC_CH_8 : ADC Channel8 selected
- ADC_CH_9 : ADC Channel9 selected
- ADC_CH_10 : ADC Channel10 selected
- ADC_CH_11 : ADC Channel11 selected
- ADC_CH_12 : ADC Channel12 selected
- ADC_CH_13 : ADC Channel13 selected
- ADC_CH_14 : ADC Channel14 selected
- ADC_CH_15 : ADC Channel15 selected
- ADC_CH_16 : ADC Channel16 selected
- ADC_CH_17 : ADC Channel17 selected
return none.
void ADC_EnableTempSensorVrefint(FunctionalState Cmd)Enables or disables the temperature sensor and Vrefint channel of ADC1
name ADC_EnableTempSensorVrefint.
fun Enables or disables the temperature sensor and Vrefint channel of ADC1
param Cmd :
- ENABLE
- DISABLE
return none
void Reference_VoltageSelect(uint32_t Ref_Type)Selects the reference voltage.
name Reference_VoltageSelect
fun Selects the reference voltage.
param Ref_Type: Select reference voltage of ADC.
- ADC_VREFSEL_VDDA Select VDDA as reference voltage
- ADC_VREFSEL_VREFP Select VREF+ as reference voltage
- ADC_VREFSEL_VREFBUFF_2_4V Select VREFBUFF_2.4V as reference voltage
- ADC_VREFSEL_OFF All three switching transistors of VREFP are turned off
return none
void ADC_ConfigOverSamplingRatioAndShift(ADC_Module *ADCx, uint32_t Ratio, uint32_t Shift)Set ADC oversampling rate times and shift bit.
name ADC_ConfigOverSamplingRatioAndShift.
fun Set ADC oversampling rate times and shift bit.
param ADCx :
- ADC1
- ADC2
param Ratio : ADC oversampling ratio times
- ADC_OVERSAMPE_RATE_TIMES_1
- ADC_OVERSAMPE_RATE_TIMES_2
- ADC_OVERSAMPE_RATE_TIMES_4
- ADC_OVERSAMPE_RATE_TIMES_8
- ADC_OVERSAMPE_RATE_TIMES_16
- ADC_OVERSAMPE_RATE_TIMES_32
- ADC_OVERSAMPE_RATE_TIMES_64
- ADC_OVERSAMPE_RATE_TIMES_128
- ADC_OVERSAMPE_RATE_TIMES_256
param Shift : ADC oversampling data right shift
- ADC_OVERSAMPE_DATA_SHIFT_0
- ADC_OVERSAMPE_DATA_SHIFT_1
- ADC_OVERSAMPE_DATA_SHIFT_2
- ADC_OVERSAMPE_DATA_SHIFT_3
- ADC_OVERSAMPE_DATA_SHIFT_4
- ADC_OVERSAMPE_DATA_SHIFT_5
- ADC_OVERSAMPE_DATA_SHIFT_6
- ADC_OVERSAMPE_DATA_SHIFT_7
- ADC_OVERSAMPE_DATA_SHIFT_8
return none
void ADC_SetOverSamplingScope(ADC_Module *ADCx, uint32_t OversampleScope)Set ADC oversampling scope.
name ADC_SetOverSamplingScope.
fun Set ADC oversampling scope.
param ADCx :
- ADC1
- ADC2
param OversampleScope :This parameter can be one of the following values
- ADC_OVERSAMPE_DISABLE
- ADC_OVERSAMPE_REGULAR_CONTINUED
- ADC_OVERSAMPE_REGULAR_RESUMED
- ADC_OVERSAMPE_INJECTED
- ADC_OVERSAMPE_REGULAR_INJECTED
return none
void ADC_EnableOverSamplingDiscont(ADC_Module *ADCx, FunctionalState Cmd)Set ADC oversampling discontinuous mode (triggered mode).
name ADC_EnableOverSamplingDiscont.
fun Set ADC oversampling discontinuous mode (triggered mode).
param ADCx :
- ADC1
- ADC2
param Cmd :
- ENABLE
- DISABLE
return none
void ADC_SetOffsetConfig(ADC_Module *ADCx, uint8_t ADC_Offset, const ADC_OffsetType *ADC_OffsetStruct)Set the specified channel conversion offset configuration.
name ADC_SetOffsetConfig.
fun Set the specified channel conversion offset configuration.
param ADCx :
- ADC1
- ADC2
param ADC_Offset :
- ADC_REGESTER_OFFSET_1
- ADC_REGESTER_OFFSET_2
- ADC_REGESTER_OFFSET_3
- ADC_REGESTER_OFFSET_4
param ADC_OffsetStruct :
- OffsetData : Set the selected channel data offset .This parameter must be range from 0 to 0xfff.
- OffsetChannel : Set the selected channel .This parameter must be range from 0 to 0x11. means CH0 - CH17.
- OffsetDirPositiveEn : Enable or disable the selected channel offset positive direction.
- ENABLE
- DISABLE
- OffsetSatenEn : Enable or disable the selected channel offset saturation .
- ENABLE
- DISABLE
- OffsetEn : Enable or disable the selected channel offset.
- ENABLE
- DISABLE
return none
void ADC_GetOffsetConfig(const ADC_Module *ADCx, uint8_t ADC_Offset, ADC_OffsetType *ADC_OffsetStruct)Get the specified channel conversion offset configuration.
name ADC_GetOffsetConfig.
fun Get the specified channel conversion offset configuration.
param ADCx :
- ADC1
- ADC2
param ADC_Offset :
- ADC_REGESTER_OFFSET_1
- ADC_REGESTER_OFFSET_2
- ADC_REGESTER_OFFSET_3
- ADC_REGESTER_OFFSET_4
param ADC_OffsetStruct :
- OffsetData : Set the selected channel data offset .This parameter must be range from 0 to 0xfff.
- OffsetChannel : Set the selected channel .This parameter must be range from 0 to 0x11. means CH0 - CH17.
- OffsetDirPositiveEn : Enable or disable the selected channel offset positive direction.
- ENABLE
- DISABLE
- OffsetSatenEn : Enable or disable the selected channel offset saturation .
- ENABLE
- DISABLE
- OffsetEn : Enable or disable the selected channel offset.
- ENABLE
- DISABLE
return none
FlagStatus ADC_GetFlagStatus(const ADC_Module *ADCx, uint16_t ADC_FLAG)Checks whether the specified ADC flag is set or not.
name ADC_GetFlagStatus.
fun Checks whether the specified ADC flag is set or not.
param ADCx :
- ADC1
- ADC2
param ADC_FLAG :
- ADC_FLAG_ENDC
- ADC_FLAG_EOC_ANY
- ADC_FLAG_JENDC
- ADC_FLAG_JEOC_ANY
- ADC_FLAG_AWDG
- ADC_FLAG_OVERRUN
- ADC_FLAG_RDY
- ADC_FLAG_PDRDY
- ADC_FLAG_EOSAMP
- ADC_FLAG_TCFLAG
- ADC_FLAG_STR
- ADC_FLAG_JSTR
- ADC_FLAG_VREFRDY
return The new state of ADC_FLAG (SET or RESET).
void ADC_ClearFlag(ADC_Module *ADCx, uint16_t ADC_FLAG)Clears pending flags of the specified ADC.
name ADC_ClearFlag.
fun Clears pending flags of the specified ADC.
param ADCx :
- ADC1
- ADC2
param ADC_FLAG :
- ADC_FLAG_ENDC
- ADC_FLAG_EOC_ANY
- ADC_FLAG_JENDC
- ADC_FLAG_JEOC_ANY
- ADC_FLAG_AWDG
- ADC_FLAG_OVERRUN
- ADC_FLAG_RDY
- ADC_FLAG_PDRDY
- ADC_FLAG_EOSAMP
- ADC_FLAG_TCFLAG
- ADC_FLAG_STR
- ADC_FLAG_JSTR
return none.
void ADC_ConfigInt(ADC_Module *ADCx, uint16_t ADC_IT, FunctionalState Cmd)Enables or disables the specified ADC interrupts.
name ADC_ConfigInt.
fun Enables or disables the specified ADC interrupts.
param ADCx :
- ADC1
- ADC2
param ADC_IT :
- ADC_INT_ENDC
- ADC_INT_ENDCA
- ADC_INT_JENDC
- ADC_INT_JENDCA
- ADC_INT_AWDG
- ADC_INT_OVERRUN
- ADC_INT_RDY
- ADC_INT_PDRDY
- ADC_INT_EOSAMP
param Cmd :
- ENABLE
- DISABLE
return none.
INTStatus ADC_GetIntStatus(const ADC_Module *ADCx, uint16_t ADC_IT)Checks whether the specified ADC interrupt has occurred or not.
name ADC_GetIntStatus.
fun Checks whether the specified ADC interrupt has occurred or not.
param ADCx :
- ADC1
- ADC2
param ADC_IT : specifies the ADC interrupt source to check.
- ADC_INT_ENDC
- ADC_INT_ENDCA
- ADC_INT_JENDC
- ADC_INT_JENDCA
- ADC_INT_AWDG
- ADC_INT_RDY
- ADC_INT_PDRDY
- ADC_INT_EOSAMP
- ADC_INT_OVERRUN
return The new state of ADC_IT (SET or RESET).
void ADC_ClearIntPendingBit(ADC_Module *ADCx, uint16_t ADC_IT)Clears interrupt pending bits of the specified ADC.
name ADC_ClearIntPendingBit.
fun Clears interrupt pending bits of the specified ADC.
param ADCx :
- ADC1
- ADC2
param ADC_IT :
- ADC_INT_ENDC
- ADC_INT_ENDCA
- ADC_INT_JENDC
- ADC_INT_JENDCA
- ADC_INT_AWDG
- ADC_INT_OVERRUN
- ADC_INT_RDY
- ADC_INT_PDRDY
- ADC_INT_EOSAMP
return none.
void ADC_ClockModeConfig(uint32_t RCC_ADCCLKprescaler)Configures the ADCCLK prescaler.
name ADC_ClockModeConfig
fun Configures the ADCCLK prescaler.
param RCC_ADCCLKprescaler:
- RCC_ADCSYSCLK_DIV1 ADC clock = SYSCLK
- RCC_ADCSYSCLK_DIV2 ADC clock = SYSCLK/2
- RCC_ADCSYSCLK_DIV3 ADC clock = SYSCLK/3
- RCC_ADCSYSCLK_DIV4 ADC clock = SYSCLK/4
- RCC_ADCSYSCLK_DIV5 ADC clock = SYSCLK/5
- RCC_ADCSYSCLK_DIV6 ADC clock = SYSCLK/6
- RCC_ADCSYSCLK_DIV8 ADC clock = SYSCLK/8
- RCC_ADCSYSCLK_DIV10 ADC clock = SYSCLK/10
- RCC_ADCSYSCLK_DIV12 ADC clock = SYSCLK/12
- RCC_ADCSYSCLK_DIV16 ADC clock = SYSCLK/16
- RCC_ADCSYSCLK_DIV32 ADC clock = SYSCLK/32
- RCC_ADCSYSCLK_DIV64 ADC clock = SYSCLK/64
return none
5.1.3 Demo descriptions
This section describes the 9 ADC examples in alphabetical order of their directory names, covering single-channel reading, DMA acquisition, the internal temperature sensor, oversampling, the analog watchdog, external line triggering, dual-ADC simultaneous mode and timer automatic injection.
5.1.3.1 ADC_Offset Offset compensation
Example directory: projects/n32g41x_EVAL/examples/ADC/ADC_Offset/
PB1 analog input→ADC1 regular channel 9 continuous conversion→offset register 1 adds 0x400 to the result→result saturated to 0x000 to 0xFFF→DMA moves the value to memory in a loop
| Item | Source analysis |
|---|---|
| Function | Adds a positive offset of 0x400 to the conversion result of ADC1 regular channel 9 (PB1) with saturation enabled, showing how the offset compensation register is used. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration and DMA_Config;inc/main.h: channel, port and pin macros;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Single channel, continuous conversion, software trigger, sample time ADC_SAMP_TIME_CYCLES_240;offset register ADC_REGESTER_OFFSET_1 with OffsetData set to OFFSET_VALUE (0x400) and both OffsetDirPositiveEn and OffsetSatenEn enabled;DMA channel 1 in circular mode, half-word transfers, buffer size 1. |
| Program and data path | main calls RCC_Configuration, GPIO_Configuration, DMA_Config and ADC_Initial in turn, then starts continuous conversion with ADC_EnableSoftwareStartConv;the result is written to ADC1->DAT and moved by DMA into the memory variable ADCConvertedValue, whose value is the raw result plus 0x400. |
| Main APIs | ADC_InitStruct, ADC_Init, ADC_ConfigRegularChannel, ADC_SetOffsetConfig, ADC_Enable, ADC_GetFlagStatus, ADC_EnableDMA, ADC_EnableSoftwareStartConv |
| Verification | Apply a known voltage to PB1 and inspect ADCConvertedValue in the Keil or IAR watch window;it should equal the raw sample plus 0x400, and values above the 12-bit range are saturated to 0xFFF. |
| Use note | The offset registers have no effect while oversampling is enabled and the OFFSCHxEN bits are ignored;a positive offset adds to the result while a negative offset ( OffsetDirPositiveEn set to DISABLE) subtracts. |
Core-code walkthrough and porting
The example lets the voltage on PB1 be converted continuously on ADC1 channel 9 and adds a fixed offset to the result through offset register 1.
Data path: PB1 voltage -> ADC_ConfigRegularChannel selects channel 9 -> ADC_SetOffsetConfig writes offset register 1 -> each result is increased by 0x400 and saturated -> DMA writes it into ADCConvertedValue in a loop
1. Initializing single-channel continuous conversion. ADC_Initial first fills the structure with defaults, then sets independent mode, one channel, continuous conversion and software trigger.
ADC_InitStruct(&ADC_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CH_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
2. Writing the compensation parameters of offset register 1. An offset register binds a channel, an offset value, a direction and a saturation flag, all written in one call.
/* ADC1 channel offset compensation configuration
* Offset register 1 monitors ADC_CH_CHANNEL (PB1)
* Positive direction offset: result = ADC_raw + OFFSET_VALUE
* Saturation enabled: clamp result to 0x000~0xFFF range
*/
ADC_OffsetStructure.OffsetChannel = ADC_CH_CHANNEL;
ADC_OffsetStructure.OffsetData = OFFSET_VALUE;
ADC_OffsetStructure.OffsetDirPositiveEn = ENABLE;
ADC_OffsetStructure.OffsetSatenEn = ENABLE;
ADC_OffsetStructure.OffsetEn = ENABLE;
ADC_SetOffsetConfig(ADC1, ADC_REGESTER_OFFSET_1, &ADC_OffsetStructure);
The four offset registers (ADC_REGESTER_OFFSET_1 to ADC_REGESTER_OFFSET_4) map to ADC_OFFSET1 to ADC_OFFSET4, and each register can bind only one channel.
3. Enabling the ADC, waiting for ready and then opening the DMA request. The DMA request is enabled only after power-up and the ready check, so the peripheral is prepared when conversion data is moved.
/* Enable ADC1 */
ADC_Enable(ADC1, ENABLE);
/* Check ADC Ready */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY) == RESET)
;
/* Enable ADC1 DMA */
ADC_EnableDMA(ADC1, ENABLE);
4. Starting continuous conversion. After initialization main issues one software start, and in continuous mode the ADC keeps converting the same channel.
/* Start ADC1 Software Conversion */
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
Corresponding source files: src/main.c
5.1.3.2 ADC_SingleRead Single-channel reading
Example directory: projects/n32g41x_EVAL/examples/ADC/ADC_SingleRead/
PA0 and PA1 analog inputs→main loop switches between ADC1 regular channel 0 and channel 1→software start and ENDC polling→DAT read into an array
| Item | Source analysis |
|---|---|
| Function | Reads voltages channel by channel in polling mode without DMA, storing the results of channel 0 (PA0) and channel 1 (PA1) in an array. |
| Source files | src/main.c: ADC_Initial, ADC_GetData, main, RCC_Configuration and GPIO_Configuration;inc/main.h: channel, port and pin macros;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Single channel, single conversion (ContinueConvEn is DISABLE), software trigger, sample time ADC_SAMP_TIME_CYCLES_240;ADC_GetData reconfigures the channel before each read, so scan mode is not needed. |
| Program and data path | main calls ADC_Initial(ADC1) and then reads channel 0 and channel 1 in while(1) through ADC_GetData, storing the results in ADC1ConvertedValue[0] and ADC1ConvertedValue[1];ADC_GetData configures the channel, starts the conversion, polls ADC_FLAG_ENDC, clears ENDC and STR and reads ADC_GetDat. |
| Main APIs | ADC_InitStruct, ADC_Init, ADC_Enable, ADC_GetFlagStatus, ADC_ConfigRegularChannel, ADC_EnableSoftwareStartConv, ADC_ClearFlag, ADC_GetDat |
| Verification | Apply different voltages to PA0 and PA1 and inspect the two elements of ADC1ConvertedValue in the watch window;they should correspond to the two voltages, with right-aligned data. |
| Use note | In single conversion mode a new channel must be configured and started again for every read; clearing ADC_FLAG_STR before reading avoids the previous state affecting the check. |
Core-code walkthrough and porting
The example reads voltages channel by channel in polling mode without DMA, refreshing the two results in the main loop.
Data path: PA0 and PA1 voltages -> ADC_ConfigRegularChannel switches the channel -> ADC_EnableSoftwareStartConv starts it -> polling ADC_FLAG_ENDC -> ADC_GetDat reads it back -> stored in ADC1ConvertedValue
1. Initializing single conversion mode. Compared with the continuous example, ContinueConvEn is DISABLE here, so each start performs one conversion.
ADC_InitStruct(&ADC_InitStructure);
/* ADCx configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADCx, &ADC_InitStructure);
/* Enable ADCx */
ADC_Enable(ADCx, ENABLE);
/* Check ADC Ready */
while(ADC_GetFlagStatus(ADCx, ADC_FLAG_RDY) == RESET)
;
2. Reconfiguring the channel and waiting for the end of conversion on each read. ADC_GetData chains configuration, start, polling and reading together, completing one channel per call.
ADC_ConfigRegularChannel(ADCx, ADC_Channel, 1, ADC_SAMP_TIME_CYCLES_240);
/* Start ADC Software Conversion */
ADC_EnableSoftwareStartConv(ADCx, ENABLE);
while(ADC_GetFlagStatus(ADCx, ADC_FLAG_ENDC) == 0){
}
ADC_ClearFlag(ADCx, ADC_FLAG_ENDC);
ADC_ClearFlag(ADCx, ADC_FLAG_STR);
dat = ADC_GetDat(ADCx);
return dat;
3. Reading the two channels in turn in the main loop. Both channels share the same initialization and differ only in the channel argument of ADC_GetData.
while (1)
{
ADC1ConvertedValue[0] = ADC_GetData(ADC1, ADC_CH0_CHANNEL);
ADC1ConvertedValue[1] = ADC_GetData(ADC1, ADC_CH1_CHANNEL);
}
Corresponding source files: src/main.c
5.1.3.3 ADC_TEMP Internal temperature sensor
Example directory: projects/n32g41x_EVAL/examples/ADC/ADC_TEMP/
Enable the internal temperature sensor channel→ADC1 channel 17 samples with 600 cycles→DMA moves the conversion value→temperature computed from the factory calibration value→printed on the serial port
| Item | Source analysis |
|---|---|
| Function | Samples the on-chip temperature sensor, converts it using the factory calibration value and prints the temperature, showing the internal channel and a longer sample time. |
| Source files | src/main.c: ADC_Initial, TempratureCalculate, main, RCC_Configuration and DMA_Config;inc/main.h: pin and log configuration macros;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Single channel, continuous conversion, channel ADC1_Channel_17_Temperture_Sensor, sample time ADC_SAMP_TIME_CYCLES_600;ADC_EnableTempSensorVrefint(ENABLE) before the conversion;reference voltage VREF_VALUE defaults to 3.3, and is changed to 4.7 with a different VTS_ADDR when VDDA on the board is 5 V;DMA in circular mode with buffer size 1. |
| Program and data path | main initializes clocks, logging, DMA and the ADC, starts the conversion and waits for ENDC, then passes ADCConvertedValue to TempratureCalculate in while(1) and prints the temperature through log_debug. |
| Main APIs | ADC_ConfigRegularChannel, ADC_EnableTempSensorVrefint, ADC_EnableDMA, ADC_Enable, ADC_GetFlagStatus, ADC_EnableSoftwareStartConv |
| Verification | With logging on PA9 at 115200, 8 data bits, no parity and 1 stop bit, the port periodically prints a temperature such as Temperature = 25.0 C;the value changes with the ambient temperature. |
| Use note | The ideal sample time of the temperature sensor is at least 17.1 us and the example uses 600 cycles; the conversion needs the calibration value written at production, and the reading is stable only when the sample time is long enough. |
Core-code walkthrough and porting
The example samples the on-chip temperature sensor and converts it with the factory calibration value and the temperature slope.
Data path: temperature sensor -> ADC1 channel 17 -> ADC_EnableTempSensorVrefint enables it -> DMA moves the value into ADCConvertedValue -> TempratureCalculate uses VTS_ADDR and AVG_SLOPE -> serial output
1. Selecting the internal temperature sensor channel and increasing the sample time. The internal channel is on ADC1 channel 17, and the sample time is set to 600 cycles so that it settles fully.
/* ADC1 regular channel16 configuration (internal temperature sensor) */
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_17_Temperture_Sensor, 1, ADC_SAMP_TIME_CYCLES_600);
/* Enable Temperature Sensor */
ADC_EnableTempSensorVrefint(ENABLE);
/* Enable ADC1 DMA */
ADC_EnableDMA(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Enable(ADC1, ENABLE);
2. Converting the sample value into a voltage and a temperature. The 12-bit sample is first turned into a voltage, then the factory calibration value is read and the temperature is computed from the slope.
float Temperate,tempValue,VTS;
uint32_t TSValue;
/* Voltage value of temperature sensor */
tempValue=TempAdVal*(VREF_VALUE/4095);
TSValue= (((*(uint32_t*)(VTS_ADDR)) & 0x0000FFFF));
VTS = TSValue /1000.0f;
/* Get the temperature inside the chip */
Temperate= ((VTS - tempValue)/AVG_SLOPE) + 25;
AVG_SLOPE is 0.0041, the voltage change per degree Celsius; the calibration value is the voltage of the temperature sensor at 25 degrees Celsius, in millivolts.
3. Converting and printing in the main loop. The conversion is moved continuously by DMA, so the main loop only reads the latest value and outputs it.
while (1)
{
TempValue = TempratureCalculate(ADCConvertedValue);
log_debug("\r\n Temperature = %.1f C\r\n", TempValue);
SysTick_Delay_Ms(1);
}
Corresponding source files: src/main.c
5.1.3.4 ADC1_DMA Circular acquisition
Example directory: projects/n32g41x_EVAL/examples/ADC/ADC1_DMA/
PB1 analog input→ADC1 channel 9 continuous conversion→DMA channel 1 circular transfer→memory variable refreshed continuously
| Item | Source analysis |
|---|---|
| Function | Lets ADC1 convert continuously and have DMA move each result to memory, with no CPU involvement in the transfer. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration and DMA_Config;inc/main.h: channel, port and pin macros;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Single channel, continuous conversion, software trigger, sample time ADC_SAMP_TIME_CYCLES_240;DMA channel 1 in circular mode, peripheral to memory, half-word transfers, buffer size 1, memory increment disabled. |
| Program and data path | main initializes clocks, GPIO, DMA and the ADC, then starts continuous conversion with ADC_EnableSoftwareStartConv;afterwards every conversion issues a DMA request that writes ADC1->DAT into ADCConvertedValue. |
| Main APIs | ADC_InitStruct, ADC_Init, ADC_ConfigRegularChannel, ADC_Enable, ADC_GetFlagStatus, ADC_EnableDMA, ADC_EnableSoftwareStartConv |
| Verification | Apply a voltage that varies over time to PB1 and inspect ADCConvertedValue in the watch window;it should follow the input continuously without any CPU read. |
| Use note | Enable the order is ADC_Enable with a wait for ADC_FLAG_RDY first and ADC_EnableDMA afterwards;circular mode reloads the DMA buffer after each transfer, which suits continuous acquisition. |
Core-code walkthrough and porting
The example lets ADC1 convert continuously and uses DMA to move the result into a memory variable without CPU intervention.
Data path: PB1 voltage -> ADC_ConfigRegularChannel selects channel 9 -> ADC_EnableSoftwareStartConv starts it -> each end of conversion triggers DMA -> ADCConvertedValue is updated
1. Initializing continuous conversion mode. The scan bit is cleared and the continuous bit set, so the conversion continues on its own after a software start.
ADC_InitStruct(&ADC_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel9 configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CH_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
2. Enabling the ADC, waiting for ready and then opening DMA. The DMA request is enabled once the ADC is ready, so the transfer does not start before data is available.
/* Enable ADC1 */
ADC_Enable(ADC1, ENABLE);
/* Check ADC Ready */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY) == RESET)
;
/* Enable ADC1 DMA */
ADC_EnableDMA(ADC1, ENABLE);
3. DMA channel 1 moving half-words in a loop. The peripheral address is fixed at ADC1->DAT and the memory address at a single variable, and the buffer reloads automatically in circular mode.
DMA_DeInit(DMA_CH1);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;
DMA_InitStructure.MemAddr = (uint32_t)&ADCConvertedValue;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = 1;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_DISABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC1, DMA, DMA_CH1, ENABLE);
/* Enable DMA channel1 */
DMA_EnableChannel(DMA_CH1, ENABLE);
Corresponding source files: src/main.c
5.1.3.5 ADC1_Oversampling Oversampling
Example directory: projects/n32g41x_EVAL/examples/ADC/ADC1_Oversampling/
PB0 and PB1 analog inputs→ADC1 channel 8 and channel 9 scanned→results oversampled by 2 with no shift→DMA writes 10 half-words in a loop
| Item | Source analysis |
|---|---|
| Function | Enables 2x oversampling on two regular channels and uses DMA to observe the oversampled data. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration and DMA_Config;inc/main.h: channel, port and pin macros;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Multi-channel scan, continuous conversion, ChsNumber set to 2;oversampling ratio ADC_OVERSAMPE_RATE_TIMES_2, no shift (ADC_OVERSAMPE_DATA_SHIFT_0) and scope ADC_OVERSAMPE_REGULAR_CONTINUED;DMA channel 1 in circular mode with memory increment and buffer size 10. |
| Program and data path | main initializes clocks, GPIO, DMA and the ADC, and after the start the oversampled results of the two channels are written continuously by DMA into ADCConvertedValue[10]. |
| Main APIs | ADC_ConfigRegularChannel, ADC_ConfigOverSamplingRatioAndShift, ADC_SetOverSamplingScope, ADC_Enable, ADC_GetFlagStatus, ADC_EnableDMA, ADC_EnableSoftwareStartConv |
| Verification | Apply voltages to PB0 and PB1 and inspect ADCConvertedValue in the watch window;the values equal the corresponding voltages as 12-bit results from 2x oversampling with no shift. |
| Use note | With no shift the oversampled result can exceed 12 bits and must be scaled back by the ratio; offset compensation has no effect while oversampling is enabled, and data alignment is not supported either. |
Core-code walkthrough and porting
The example enables 2x oversampling on two regular channels and uses DMA to observe the oversampled data continuously.
Data path: PB0 and PB1 voltages -> a two-channel regular sequence -> ADC_ConfigOverSamplingRatioAndShift sets 2x -> ADC_SetOverSamplingScope applies it to continuous regular conversions -> DMA writes into ADCConvertedValue[10]
1. Initializing multi-channel scan mode. The scan bit is set and the channel count is 2, with the two channels in sequence positions 1 and 2.
ADC_InitStruct(&ADC_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CH1_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
ADC_ConfigRegularChannel(ADC1, ADC_CH2_CHANNEL, 2, ADC_SAMP_TIME_CYCLES_240);
2. Setting the oversampling ratio, shift and scope. Oversampling is 2x with no shift and applies to continuous regular conversions.
/* Enable ADC1 oversampling, x2 and no shift */
ADC_ConfigOverSamplingRatioAndShift(ADC1, ADC_OVERSAMPE_RATE_TIMES_2, ADC_OVERSAMPE_DATA_SHIFT_0);
/* Config ADC1 oversampling scope */
ADC_SetOverSamplingScope(ADC1, ADC_OVERSAMPE_REGULAR_CONTINUED);
3. Having DMA move 10 half-words with address increment. The buffer is larger than the channel count, which shows the variation of successive oversampled results.
DMA_DeInit(DMA_CH1);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;
DMA_InitStructure.MemAddr = (uint32_t)ADCConvertedValue;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = 10;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
Corresponding source files: src/main.c
5.1.3.6 AnalogWatchdog Analog watchdog
Example directory: projects/n32g41x_EVAL/examples/ADC/AnalogWatchdog/
PB1 analog input→ADC1 channel 9 conversion→result compared with the high and low thresholds→an out-of-range result raises the AWD interrupt→the handler increments a counter
| Item | Source analysis |
|---|---|
| Function | Uses the analog watchdog to guard a single regular channel and counts the interrupts raised when the conversion result leaves the threshold window. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration and NVIC_Configuration;inc/main.h: channel, port and pin macros;src/n32g41x_it.c: ADC1_IRQHandler and the gCntAwdg definition;inc/n32g41x_it.h: interrupt declarations;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | Single channel, continuous conversion, sample time ADC_SAMP_TIME_CYCLES_240;high threshold 0x0B00 and low threshold 0x0300 with watch type ADC_ANALOG_WTDG_SINGLEREG_ENABLE;interrupt ADC_INT_AWDG enabled;NVIC priority group 2 with ADC1_IRQn preemption and sub priority both 0. |
| Program and data path | main initializes clocks, GPIO, NVIC and the ADC, starts continuous conversion and enters while(1) incrementing gCnt;when a result leaves the window, ADC1_IRQHandler clears the ADC_INT_AWDG pending bit and increments gCntAwdg. |
| Main APIs | ADC_ConfigRegularChannel, ADC_ConfigAnalogWatchdogThresholds, ADC_ConfigAnalogWatchdogSingleChannel, ADC_ConfigAnalogWatchdogWorkChannelType, ADC_ConfigInt, ADC_GetIntStatus, ADC_ClearIntPendingBit |
| Verification | Drive PB1 outside the threshold window and inspect gCntAwdg in the watch window;it keeps growing, and stops growing while the voltage stays inside the window. |
| Use note | The threshold comparison happens before data alignment, so both thresholds are compared against the unshifted result;ADC_ConfigAnalogWatchdogSingleChannel is meaningful only in single-channel mode. |
Core-code walkthrough and porting
The example uses the analog watchdog to guard a single regular channel and lets ADC1_IRQHandler count the out-of-range events.
Data path: PB1 voltage -> channel 9 -> ADC_ConfigAnalogWatchdogThresholds sets the thresholds -> ADC_ConfigAnalogWatchdogSingleChannel selects the channel -> ADC_ConfigInt enables ADC_INT_AWDG -> the interrupt counts
1. Configuring the thresholds, the guarded channel and the interrupt. Both thresholds are written at once and the guarded channel is selected in single-channel mode.
/* ADC1 regular channel9 configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CH_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
/* Configure high and low analog watchdog thresholds */
ADC_ConfigAnalogWatchdogThresholds(ADC1, 0x0B00, 0x0300);
/* Configure channel as the single analog watchdog guarded channel */
ADC_ConfigAnalogWatchdogSingleChannel(ADC1, ADC_CH_CHANNEL);
/* Enable analog watchdog on one regular channel */
ADC_ConfigAnalogWatchdogWorkChannelType(ADC1, ADC_ANALOG_WTDG_SINGLEREG_ENABLE);
/* Enable AWD interrupt */
ADC_ConfigInt(ADC1, ADC_INT_AWDG, ENABLE);
2. Enabling the ADC1 interrupt in the NVIC. The watchdog interrupt reaches the CPU only after the interrupt controller is configured and the channel is enabled.
NVIC_InitType NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
3. Clearing the flag and counting in the handler. The handler first checks the interrupt source, clears the pending bit and then increments the counter.
if(ADC_GetIntStatus(ADC1, ADC_INT_AWDG) != RESET)
{
/* Clear ADC1 AWD pending interrupt bit */
ADC_ClearIntPendingBit(ADC1, ADC_INT_AWDG);
gCntAwdg++;
}
Corresponding source files: src/main.c, src/n32g41x_it.c
5.1.3.7 ExtLinesTrigger External line trigger
Example directory: projects/n32g41x_EVAL/examples/ADC/ExtLinesTrigger/
PA12 and PA11 rising edges→EXTI events trigger→ADC1 regular and injected conversions→the JENDC interrupt reads the injected results→DMA moves the regular results
| Item | Source analysis |
|---|---|
| Function | Uses two external EXTI lines to trigger regular and injected conversions, with the regular results going through DMA and the injected results read in the interrupt. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration, EXTI_Configuration, DMA_Config and NVIC_Configuration;inc/main.h: channel and EXTI trigger pin macros;src/n32g41x_it.c: ADC1_IRQHandler and the Index definition;inc/n32g41x_it.h: interrupt declarations;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | The regular group is PA0 and PA1 and the injected group is PA2 and PA3, both with sequence length 2;ContinueConvEn is DISABLE, the regular trigger source is ADC_EXT_TRIG_REG_CONV_EXT_INT0_15 and the injected trigger source is ADC_EXT_TRIG_INJ_CONV_EXT_INT0_15;PA12 uses EXTI line 10 and PA11 uses EXTI line 11, both in event mode on the rising edge; DMA in circular mode with buffer size 64. |
| Program and data path | main initializes clocks, NVIC, GPIO, EXTI, DMA and the ADC;the regular results are written by DMA into ADC_RegularConvertedValueTab[64] and at the end of each injected conversion ADC1_IRQHandler reads the two injected values into ADC_InjectedConvertedValueTab[32]. |
| Main APIs | ADC_ConfigRegularChannel, ADC_ConfigInjectedChannel, ADC_ConfigInjectedSequencerLength, ADC_ConfigExternalTrigInjectedConv, ADC_ConfigRegularExtLineTrigSource, ADC_ConfigInjectedExtLineTrigSource, ADC_ConfigInt, ADC_GetInjectedConversionDat |
| Verification | Apply rising edges to PA12 and PA11 with a signal source; the regular results should update in ADC_RegularConvertedValueTab and the injected results should appear in pairs in ADC_InjectedConvertedValueTab. |
| Use note | The injected data registers are read-only and can be read only by offset through ADC_GetInjectedConversionDat;external line triggering requires mapping the EXTI lines to the ADC triggers with ADC_ConfigRegularExtLineTrigSource and ADC_ConfigInjectedExtLineTrigSource first. |
Core-code walkthrough and porting
The example uses two EXTI lines to trigger regular and injected conversions at the same time, handling the two kinds of results with DMA and an interrupt.
Data path: PA12 and PA11 rising edges -> EXTI events -> ADC external trigger -> regular results written by DMA into ADC_RegularConvertedValueTab -> the JENDC interrupt reads injected values into ADC_InjectedConvertedValueTab
1. Regular channels and external line triggering. Two channels are placed in the regular sequence, and after choosing ADC_EXT_TRIG_REG_CONV_EXT_INT0_15 the specific EXTI line is selected in software.
ADC_InitStruct(&ADC_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_EXT_INT0_15;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration */
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_00_PA0, 1, ADC_SAMP_TIME_CYCLES_240);
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_01_PA1, 2, ADC_SAMP_TIME_CYCLES_240);
2. Injected channels, trigger source and interrupt. The injected sequence length, the channels and the external trigger source are set in turn, and finally the two EXTI lines are mapped to the ADC.
/* Set injected sequencer length */
ADC_ConfigInjectedSequencerLength(ADC1, 2);
/* ADC1 injected channel configuration */
ADC_ConfigInjectedChannel(ADC1, ADC1_Channel_02_PA2, 1, ADC_SAMP_TIME_CYCLES_240);
ADC_ConfigInjectedChannel(ADC1, ADC1_Channel_03_PA3, 2, ADC_SAMP_TIME_CYCLES_240);
/* ADC1 injected external trigger configuration */
ADC_ConfigExternalTrigInjectedConv(ADC1, ADC_EXT_TRIG_INJ_CONV_EXT_INT0_15);
/* Enable JENDC interrupt */
ADC_ConfigInt(ADC1, ADC_INT_JENDC, ENABLE);
ADC_ConfigRegularExtLineTrigSource(ADC1, Regular_ExtLine_TrigSource);
ADC_ConfigInjectedExtLineTrigSource(ADC1, Injected_ExtLine_TrigSource);
3. Configuring the two EXTI lines as event mode on the rising edge. Each EXTI line is first associated with a GPIO pin and then set to event mode, so the event triggers the ADC instead of the CPU.
EXTI_InitStruct(&EXTI_InitStructure);
GPIO_ConfigEXTILine(REG_EXTI_PortSOURCE, REG_EXTI_PinSOURCE);
/* EXTI line10 configuration -----------------------------------------------*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_Line = REG_EXTI_LINE;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
GPIO_ConfigEXTILine(INJ_EXTI_PortSOURCE, INJ_EXTI_PinSOURCE);
/* EXTI line11 configuration -----------------------------------------------*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_Line = INJ_EXTI_LINE;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
4. Reading the two injected values in the handler. It clears JENDC and then reads the injected data registers by offset, writing them in a ring.
if(ADC_GetIntStatus(ADC1, ADC_INT_JENDC) != RESET)
{
/* Clear ADC1 JEOC pending interrupt bit */
ADC_ClearIntPendingBit(ADC1, ADC_INT_JENDC);
/* Get injected channel1 and channel2 converted value */
ADC_InjectedConvertedValueTab[Index++] = ADC_GetInjectedConversionDat(ADC1, ADC_INJECT_DATA_OFFSET_1);
ADC_InjectedConvertedValueTab[Index++] = ADC_GetInjectedConversionDat(ADC1, ADC_INJECT_DATA_OFFSET_2);
if (Index == 32)
{
Index = 0;
}
}
Corresponding source files: src/main.c, src/n32g41x_it.c
5.1.3.8 RegSimul_DualMode Regular simultaneous dual mode
Example directory: projects/n32g41x_EVAL/examples/ADC/RegSimul_DualMode/
PB0 and PB1 with PA4 and PA5 analog inputs→ADC1 and ADC2 in regular simultaneous mode→the two results packed into one 32-bit word→DMA moves 16 words
| Item | Source analysis |
|---|---|
| Function | Puts ADC1 and ADC2 in regular simultaneous mode so that the results of two channels are packed into one 32-bit word moved by DMA. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration and DMA_Config;inc/main.h: channel, port and pin macros for both ADCs;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | The WorkMode of both ADC1 and ADC2 is ADC_WORKMODE_DUAL_REG_SIMULT, MultiChEn and ContinueConvEn are both enabled, ChsNumber is 2 and the sample time is ADC_SAMP_TIME_CYCLES_600;DMA channel 1 in normal mode, word transfers, buffer size 16. |
| Program and data path | main initializes clocks, GPIO, DMA and the ADC, starts the software conversion and waits for the DMA transfer complete flag DMA_FLAG_TC1 before clearing it;each pair of simultaneous results occupies one 32-bit cell of ADC_DualConvertedValueTab, with the low 16 bits for ADC1 and the high 16 bits for ADC2. |
| Main APIs | ADC_InitStruct, ADC_Init, ADC_ConfigRegularChannel, ADC_Enable, ADC_GetFlagStatus, ADC_EnableDMA, ADC_EnableSoftwareStartConv |
| Verification | Apply voltages to the two pin groups and inspect ADC_DualConvertedValueTab in the watch window;the low and high 16 bits of each 32-bit word should correspond to the ADC1 and ADC2 channels respectively. |
| Use note | The work mode bits of the slave ADC must match the master, and changing the channel configuration causes a dual-ADC restart and loss of synchronisation, so the dual ADC should be disabled first; DMA moves only the low 16 bits, and the high 16 bits must be read as a word. |
Core-code walkthrough and porting
The example puts ADC1 and ADC2 in regular simultaneous mode, where the two results are packed into one 32-bit word moved by DMA.
Data path: ADC1 and ADC2 channels -> ADC_WORKMODE_DUAL_REG_SIMULT -> simultaneous conversion -> DMA moves the word -> ADC_DualConvertedValueTab[16]
1. Configuring ADC1 for regular simultaneous mode. The master ADC is initialized in the dual mode first and then given two regular channels.
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStruct(&ADC_InitStructure);
ADC_InitStructure.WorkMode = ADC_WORKMODE_DUAL_REG_SIMULT;
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration */
ADC_ConfigRegularChannel(ADC1, ADC1_CH1_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_600);
ADC_ConfigRegularChannel(ADC1, ADC1_CH2_CHANNEL, 2, ADC_SAMP_TIME_CYCLES_600);
2. Configuring ADC2 with the same mode. The slave ADC keeps the same mode bits as the master, otherwise synchronisation cannot be established.
/* ADC2 configuration ------------------------------------------------------*/
ADC_InitStruct(&ADC_InitStructure);
ADC_InitStructure.WorkMode = ADC_WORKMODE_DUAL_REG_SIMULT;
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 2;
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channel configuration */
ADC_ConfigRegularChannel(ADC2, ADC2_CH1_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_600);
ADC_ConfigRegularChannel(ADC2, ADC2_CH2_CHANNEL, 2, ADC_SAMP_TIME_CYCLES_600);
3. Enabling both ADCs, waiting for ready and then opening DMA. Both ADCs must be enabled and ready, and the DMA request is issued by the master ADC.
/* Enable ADC1 ADC2 */
ADC_Enable(ADC1, ENABLE);
ADC_Enable(ADC2, ENABLE);
/* Check ADC1 Ready */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY) == RESET)
;
/* Check ADC2 Ready */
while(ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY) == RESET)
;
/* Enable ADC1 DMA */
ADC_EnableDMA(ADC1, ENABLE);
4. Having DMA move 16 words with word transfers in normal mode. In simultaneous mode one 32-bit word carries both results, so the transfer width is a word.
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;
DMA_InitStructure.MemAddr = (uint32_t)ADC_DualConvertedValueTab;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = 16;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_WORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
5. Waiting for the DMA transfer to finish in the main loop. In normal mode the transfer complete flag is raised after the configured number of words, and the main program polls and clears it.
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
/* Test on DMA channel1 transfer complete flag */
while (!DMA_GetFlagStatus(DMA_FLAG_TC1, DMA))
;
/* Clear DMA channel1 transfer complete flag */
DMA_ClearFlag(DMA_FLAG_TC1, DMA);
Corresponding source files: src/main.c
5.1.3.9 TIMTrigger_AutoInjection Timer trigger with automatic injection
Example directory: projects/n32g41x_EVAL/examples/ADC/TIMTrigger_AutoInjection/
GTIM1 CH4 compare event triggers→ADC1 regular channel conversion→an injected channel runs automatically after the regular one→the JENDC interrupt reads the injected value→PC6 toggles as an indicator
| Item | Source analysis |
|---|---|
| Function | Uses the GTIM1 CH4 compare event to trigger a regular conversion, then injects one channel automatically once the regular conversion finishes, reading the injected value in the interrupt. |
| Source files | src/main.c: ADC_Initial, main, RCC_Configuration, GPIO_Configuration, TIM_Configuration, DMA_Config and NVIC_Configuration;inc/main.h: channel, trigger and pin macros;src/n32g41x_it.c: ADC1_IRQHandler and the Index definition;inc/n32g41x_it.h: interrupt declarations;readme.txt: function and environment notes;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | The regular channel is PA1 and the injected channel is PB1, with both sequence lengths 1;MultiChEn and ContinueConvEn are DISABLE and the regular trigger source is ADC_EXT_TRIG_REG_CONV_GTIM1_CC4;ADC_EnableAutoInjectedConv and ADC_INT_JENDC are enabled;GTIM1 is prescaled to 16 MHz with period 1600 and CH1 and CH4 in PWM1 mode with pulse 800; DMA in circular mode with buffer size 32. |
| Program and data path | main initializes clocks, NVIC, GPIO, GTIM1, DMA and the ADC, and finally starts the timer with TIM_Enable(GTIM1, ENABLE);the regular results are written by DMA into ADC_RegularConvertedValueTab[32], and at the end of each automatic injection ADC1_IRQHandler toggles PC6 and reads the injected value into ADC_InjectedConvertedValueTab[32]. |
| Main APIs | ADC_ConfigRegularChannel, ADC_ConfigInjectedSequencerLength, ADC_ConfigInjectedChannel, ADC_EnableAutoInjectedConv, ADC_ConfigInt, ADC_GetInjectedConversionDat, ADC_EnableDMA |
| Verification | Observe the GTIM1 CH4 PWM output on PA3 with an oscilloscope and confirm in the watch window that ADC_RegularConvertedValueTab and ADC_InjectedConvertedValueTab update together;PC6 emits one pulse on every injection interrupt. |
| Use note | Automatic injection and the discontinuous mode of the regular group cannot be used at the same time; the injected sequence needs its own length setting, and the argument of ADC_ConfigInjectedChannel is the channel position in the injected sequence. |
Core-code walkthrough and porting
The example uses the GTIM1 CH4 event to trigger a regular conversion, with an injected channel running automatically once the regular one finishes.
Data path: GTIM1 CH4 event -> ADC regular trigger -> regular conversion finishes -> the injected channel runs automatically -> the JENDC interrupt reads the injected value and toggles PC6
1. Regular group triggered by GTIM1_CC4, one channel and a single conversion. Only one channel is placed in the regular sequence and the trigger source is timer channel 4.
ADC_InitStruct(&ADC_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_GTIM1_CC4;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration */
ADC_ConfigRegularChannel(ADC1, ADC_REG_CH_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
2. Configuring automatic injection and enabling the JENDC interrupt. The injected sequence length is 1, and once automatic injection is enabled a regular conversion triggers one injected conversion when it finishes.
/* Set injected sequencer length */
ADC_ConfigInjectedSequencerLength(ADC1, 1);
/* ADC1 injected channel configuration */
ADC_ConfigInjectedChannel(ADC1, ADC_INJ_CH_CHANNEL, 1, ADC_SAMP_TIME_CYCLES_240);
/* Enable automatic injected conversion start after regular one */
ADC_EnableAutoInjectedConv(ADC1, ENABLE);
/* Enable JENDC interrupt */
ADC_ConfigInt(ADC1, ADC_INT_JENDC, ENABLE);
3. Configuring the GTIM1 time base and the PWM1 output of CH1 and CH4. The timer prescales the clock to 16 MHz with period 1600 and pulse 800 on both channels, where CH4 acts as the ADC trigger source.
PrescalerValue = (uint32_t)(SystemCoreClock / 16000000) - 1;
/* Time base configuration */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 1600;
TIM_TimeBaseStructure.Prescaler = PrescalerValue;
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_TimeBaseStructure.CounterMode = TIM_CNT_MODE_UP;
TIM_InitTimeBase(GTIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_InitOcStruct(&TIM_OCInitStructure);
TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = Pluse_Val;
TIM_OCInitStructure.OCPolarity = TIM_OC_POLARITY_HIGH;
TIM_InitOc1(GTIM1, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(GTIM1, TIM_OC_PRE_LOAD_ENABLE);
/* PWM1 Mode configuration: Channel4 */
TIM_InitOc4(GTIM1, &TIM_OCInitStructure);
TIM_ConfigOc4Preload(GTIM1, TIM_OC_PRE_LOAD_ENABLE);
TIM_ConfigArPreload(GTIM1, ENABLE);
4. Reading the injected value and toggling PC6 in the handler. The handler sets PC6 on entry, resets it after reading the injected result, and uses the pin level to indicate that an injected conversion has occurred.
GPIO_SetBits(GPIO_TOGGLE_PORT, GPIO_TOGGLE_PIN);
if(ADC_GetIntStatus(ADC1, ADC_INT_JENDC) != RESET)
{
/* Clear ADC1 JEOC pending interrupt bit */
ADC_ClearIntPendingBit(ADC1, ADC_INT_JENDC);
/* Get injected channel1 converted value */
ADC_InjectedConvertedValueTab[Index++] = ADC_GetInjectedConversionDat(ADC1, ADC_INJECT_DATA_OFFSET_1);
/* Reset toggle pin */
GPIO_ResetBits(GPIO_TOGGLE_PORT, GPIO_TOGGLE_PIN);
if (Index == 32)
{
Index = 0;
}
}
Corresponding source files: src/main.c, src/n32g41x_it.c
5.1.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| ADCCLK above the limit | The ADC clock must not exceed 36 MHz; select a divider of 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 32 or 64 with ADC_ClockModeConfig and choose a larger divider at a high system clock so that ADCCLK stays within 36 MHz. |
User manual |
| Changing the sequence during a conversion | ADC_RSEQx and ADC_JSEQ may be changed only while the ADC is idle;rewriting the sequence during a conversion disturbs the channel order, so stop the conversion before configuring. |
User manual |
| Discontinuous mode conflicting with automatic injection | Only one of the regular and injected groups may use discontinuous mode, and automatic injection and discontinuous mode cannot be used at the same time; disable automatic injection when discontinuous conversions are needed. |
User manual |
| Oversampling and offset compensation | Offset compensation has no effect once oversampling is enabled and the OFFSCHxEN bits are ignored;data alignment is not supported with oversampling either, so neither can be combined with it. |
User manual |
| Master and slave dual-ADC configuration | The work mode bits of the slave ADC must match the master; changing the channel configuration causes a dual-ADC restart and loss of synchronisation, so disable the dual ADC before modifying the configuration. |
User manual |
| Same-channel sample windows in simultaneous mode | When the two ADCs sample the same channel in simultaneous mode the sample windows must not overlap, otherwise the results are not reliable; stagger the sample times or use another mode. |
User manual |
| Temperature sensor accuracy | The ideal sample time of the temperature sensor is at least 17.1 us and its maximum error is about 3 degrees Celsius, making it better for observing temperature trends than for measuring absolute temperature; a longer sample time setting reduces the error. |
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 ADC-related entries.