Continuous Mode
This sample demonstrates voltage detection using the ADC continuous sampling mode. The configuration can be modified to control whether GDMA is used for data transfer.
In continuous sampling mode, the ADC’s sampled data is stored in the ADC FIFO by default. If the GDMA transfer function is used, the GDMA transfers data from the ADC FIFO to memory.
Users can change the sampling mode of the ADC channel, input voltage range, and other information in the sample through different macro configurations. For specific macro configurations, see Configurations.
Requirements
For requirements, please refer to the Requirements.
Wiring
Use a Dupont wire to connect P2_4 to external voltage input.
Configurations
The following macro can be configured to modify whether to use GDMA for transferring ADC FIFO data.
1
indicates using GDMA,0
indicates not using GDMA.#define ADC_CONFIG_GDMA_MODE_EN 0 /*< Set this macro to configure whether to use GDMA for transferring ADC FIFO data. */
The following macro can be configured to modify the ADC input voltage range.
#define ADC_DIVIDE_MODE 1 /*< Divide Mode, input voltage range is 0V~Vbat. */ #define ADC_BYPASS_MODE 0 /*< Bypass Mode, input voltage range is 0V~0.9V. */ #define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE /*< Set this macro to select the ADC input voltage range. */
The following macro can be configured to modify the pin definitions.
#define ADC_SAMPLE_PIN_0 P2_4 #define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_4
The following macro can be configured to modify the GDMA channel-related configurations.
// Set the following macros to modify the ADC GDMA Channel configurations. #define ADC_GDMA_CHANNEL_NUM 0 #define ADC_GDMA_Channel GDMA_Channel0 #define ADC_GDMA_Channel_IRQn GDMA0_Channel0_IRQn #define ADC_GDMA_Channel_Handler GDMA0_Channel0_Handler
The following macro can be configured to modify the data transfer length for ADC GDMA.
#define GDMA_TRANSFER_SIZE 100 /*< Set this macro to modify the transfer size. */
The following macro can be configured to modify the sampling period time for ADC continuous sampling mode.
#define ADC_CONTINUOUS_SAMPLE_PERIOD (200-1)//20us /*< Set this macro to modify the ADC sample period. */
Building and Downloading
For building and downloading, please refer to the Building and Downloading.
Experimental Verification
When the EVB starts, observe the following log within the Debug Analyzer.
Start ADC Continuous Mode test !
ADC Configurations:
If
ADC_MODE_DIVIDE_OR_BYPASS
is configured asADC_DIVIDE_MODE
, the following log will be printed:[ADC]ADC sample mode is divide mode !
If
ADC_MODE_DIVIDE_OR_BYPASS
is configured asADC_BYPASS_MODE
, the following log will be printed:[ADC]ADC sample mode is bypass mode !
After initialization is complete, the ADC begins sampling. When the data in the ADC FIFO reaches the threshold, it will trigger an ADC interrupt. When the data transferred by the GDMA reaches the set value, it will trigger a GDMA interrupt. Within the interrupt function, print the raw data obtained from sampling and the converted voltage values.
[io_adc]io_adc_voltage_calculate: ADC rawdata_0 = xxx, voltage_0 = xxxmV [io_adc]io_adc_voltage_calculate: ADC rawdata_1 = xxx, voltage_1 = xxxmV ...
If the ADC FIFO overflows, it will trigger the
ADC_INT_FIFO_OVERFLOW
interrupt, and the log will print relevant information.ADC_INT_FIFO_OVERFLOW
If data is read when the ADC FIFO is empty, it will trigger the
ADC_INT_FIFO_RD_ERR
interrupt, and the log will print relevant information.ADC_INT_FIFO_RD_ERR
Code Overview
This section introduces the code and process description for initialization and corresponding function implementation in the sample.
Source Code Directory
The directory for project file and source code are as follows:
Project directory:
sdk\samples\peripheral\adc\continuous_gdma\proj
Source code directory:
sdk\samples\peripheral\adc\continuous_gdma\src
Initialization
The initialization flow for peripherals can refer to Initialization Flow in General Introduction.
Call
Pad_Config()
andPinmux_Config()
to configure the PAD and PINMUX of the corresponding pins. Please ensure that the PAD is configured in Shutdown mode to prevent leakage.void board_adc_init(void) { Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW); }
Call
RCC_PeriphClockCmd()
to enable the ADC clock.Initialize the ADC peripheral:
Define the
ADC_InitTypeDef
typeADC_InitStruct
, and callADC_StructInit()
to pre-fillADC_InitStruct
with default values.Modify the
ADC_InitStruct
parameters as needed. WhenADC_CONFIG_GDMA_MODE_EN
is configured with different values, the initialization configuration will be different. The ADC initialization parameter configuration is shown in the table below.Call
ADC_Init()
to initialize the ADC peripheral.
ADC Hardware Parameters |
Setting in the |
|
|
---|---|---|---|
Sample Time |
199 |
199 |
|
Schedule Index |
Index 0 is set to |
Index 0 is set to |
|
Bit Map |
0x01 |
0x01 |
|
Data Write to FIFO |
|||
ADC Water Level |
- |
4 |
|
FIFO Threshold Level |
16 |
- |
|
Power Always On |
If
ADC_MODE_DIVIDE_OR_BYPASS
is configured asADC_BYPASS_MODE
, the functionADC_BypassCmd()
must be called to enable the Bypass mode for the corresponding pin.Call
ADC_INTConfig()
to configure the ADC interrupt and NVIC. For NVIC configurations, refer to Interrupt Configuration.If
ADC_CONFIG_GDMA_MODE_EN
is configured as0
, configure the ADC FIFO threshold interruptADC_INT_FIFO_THD
.If
ADC_CONFIG_GDMA_MODE_EN
is configured as1
, configure the ADC FIFO overflow interruptADC_INT_FIFO_OVERFLOW
and ADC FIFO read error interruptADC_INT_FIFO_RD_ERR
.
Before the ADC begins sampling, it is necessary to call
ADC_CalibrationInit()
for ADC voltage calibration. If the return value is false, it indicates that the IC has not been calibrated and cannot accurately convert voltage values, but raw data can still be read.If
ADC_CONFIG_GDMA_MODE_EN
is configured as1
, initialize the GDMA peripheral:Define a
GDMA_InitTypeDef
typeGDMA_InitStruct
, and callGDMA_StructInit()
to pre-fillGDMA_InitStruct
with default values.Modify the
GDMA_InitStruct
parameters as needed. The initialization parameters for the GDMA channel are configured as shown in the table below. CallGDMA_Init()
to initialize the GDMA peripheral.Configure the GDMA total transfer complete interrupt
GDMA_INT_Transfer
and NVIC. For NVIC configurations, refer to Interrupt Configuration.Call
GDMA_Cmd()
to enable the corresponding GDMA channel transfer.
GDMA Hardware Parameters |
Setting in the |
GDMA Channel |
---|---|---|
Channel Num |
0 |
|
Transfer Direction |
||
Buffer Size |
100 |
|
Source Address Increment or Decrement |
||
Destination Address Increment or Decrement |
||
Source Data Size |
||
Destination Data Size |
||
Source Burst Transaction Length |
||
Destination Burst Transaction Length |
||
Source Address |
|
|
Destination Address |
|
|
Source Handshake |
Functional Implementation
ADC Sampling Data Without Using GDMA Transfer
When ADC sampling data is not transferred using GDMA, the flow for continuous mode sampling is as shown in the figure:

ADC Continuous Sampling Flow (Without Using GDMA Transfer)
Call
ADC_ClearFIFO()
to clear the data in the ADC FIFO before sampling.Call
ADC_Cmd()
to start continuous ADC sampling.When the sampled data in the FIFO reaches the set threshold, trigger the ADC
ADC_INT_FIFO_THD
interrupt. Within the interrupt function, callADC_GetFIFODataLen()
to read the data length in the FIFO; callADC_ReadFIFOData()
function to read the data in the FIFO; callADC_GetVoltage()
function, input the corresponding sampling mode, and convert the sampled data to voltage values.After data processing is completed, call
ADC_ClearFIFO()
to clear the data in the ADC FIFO.void SAR_ADC_Handler(void) { ... if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_THD) == SET) { ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); data_len = ADC_GetFIFODataLen(ADC); ADC_ReadFIFOData(ADC, sample_data, data_len); ADC_ClearFIFO(ADC); ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); for (uint8_t i = 0; i < data_len; i++) { sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status); ... } } for (uint32_t i = 0; i < 1000000; i++) {}; ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); }
ADC Sampling Data Using GDMA Transfer
When ADC sampling data is transferred using GDMA, the flow for continuous mode sampling is as shown in the figure:

ADC Continuous Sampling Flow (Using GDMA Transfer)
After enabling the GDMA transfer, when the sampled data in the ADC FIFO reaches the set threshold, it will trigger a GDMA transfer, and the GDMA will move the data from
(&(ADC->ADC_FIFO_READ))
toADC_Recv_Buffer
.After the GDMA data transfer is complete, it triggers the GDMA
GDMA_INT_Transfer
interrupt.In the interrupt function, call
ADC_Cmd()
to enable the ADC continuous sampling mode to prevent continued sampling during interrupt processing from causing ADC FIFO overflow.Call the
ADC_GetVoltage()
function to convert the sampled data into voltage values.Re-enable the source address and destination address of GDMA, and re-enable GDMA transfer.
Call
ADC_ClearFIFO()
to clear the data in the ADC FIFO, and callADC_Cmd()
to re-enable the ADC continuous sampling mode.void ADC_GDMA_Channel_Handler(void) { ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); DBG_DIRECT("into ADC_GDMA_Channel_Handler"); float sample_voltage = 0; ADC_ErrorStatus error_status = NO_ERROR; for (uint32_t i = 0; i < GDMA_TRANSFER_SIZE; i++) { uint16_t sample_data = ADC_Recv_Buffer[i]; sample_voltage = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data, &error_status); ... } platform_delay_ms(1000); /* Restart dma and adc */ GDMA_SetSourceAddress(ADC_GDMA_Channel, (uint32_t)(&(ADC->ADC_FIFO_READ))); GDMA_SetDestinationAddress(ADC_GDMA_Channel, (uint32_t)(ADC_Recv_Buffer)); GDMA_SetBufferSize(ADC_GDMA_Channel, GDMA_TRANSFER_SIZE); GDMA_ClearINTPendingBit(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer); GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); ADC_ClearFIFO(ADC); ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); }
When the ADC FIFO overflows, trigger the
ADC_INT_FIFO_OVERFLOW
interrupt, clear the ADC FIFO data within the ADC interrupt function, and print the relevant information.void SAR_ADC_Handler(void) { if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_RD_ERR) == SET) { DBG_DIRECT("ADC_INT_FIFO_RD_ERR!"); ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_RD_ERR); } if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_OVERFLOW) == SET) { ADC_WriteFIFOCmd(ADC, DISABLE); DBG_DIRECT("ADC_INT_FIFO_OVERFLOW"); ADC_ClearFIFO(ADC); ADC_WriteFIFOCmd(ADC, ENABLE); ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_OVERFLOW); } }