One Shot Interrupt

This sample demonstrates voltage detection using the ADC single-sample interrupt mode.

When the ADC sampling is complete, an interrupt is triggered, and within the interrupt function, raw data is read and voltage conversion calculations are performed.

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

  1. The following macro can be configured to modify whether the ADC sample value is stored in the FIFO. 1 indicates that the ADC sample data is stored in the FIFO, while 0 indicates that the ADC data is stored in the corresponding Schedule Table.

    #define ADC_DATA_OUTPUT_TO_FIFO             0                   /*< Set this macro to configure whether ADC data is stored in the FIFO. */
    
  2. The following macro can be configured to modify the pin definitions.

    #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. */
    
  3. The following macros can be configured to modify the pin definitions.

    #define ADC_SAMPLE_PIN                      P2_4
    #define ADC_SAMPLE_CHANNEL                  ADC_Channel_Index_4
    

Building and Downloading

For building and downloading, please refer to the Building and Downloading.

Experimental Verification

  1. When the EVB starts, observe the following log within the Debug Analyzer

    Start ADC interrupt test!
    
  2. ADC Configurations:

    1. If ADC_MODE_DIVIDE_OR_BYPASS is configured as ADC_DIVIDE_MODE, the following log will be printed:

      [ADC]ADC sample mode is divide mode !
      
    2. If ADC_MODE_DIVIDE_OR_BYPASS is configured as ADC_BYPASS_MODE, the following log will be printed:

      [ADC]ADC sample mode is bypass mode !
      
  3. After initialization is completed, the ADC begins sampling. Once a single ADC sampling is finished, it will trigger an interrupt, within which the raw data obtained from sampling and the converted voltage value will be printed.

    into SAR_ADC_Handler
    [ADC] adc_sample_demo: ADC one shot mode sample data = xxx, voltage = xxx mV
    ...
    

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\oneshot_interrupt\proj

  • Source code directory: sdk\samples\peripheral\adc\oneshot_interrupt\src

Initialization

The initialization flow for peripherals can refer to Initialization Flow in General Introduction.

  1. Call Pad_Config() and Pinmux_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, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW);
    }
    
  2. Call RCC_PeriphClockCmd() to enable the ADC clock.

  3. Initialize the ADC peripheral:

    1. Define the ADC_InitTypeDef type ADC_InitStruct, and call ADC_StructInit() to pre-fill ADC_InitStruct with default values.

    2. Modify the ADC_InitStruct parameters as needed. When ADC_DATA_OUTPUT_TO_FIFO is configured with different values, the initialization configuration will be different. The ADC initialization parameter configuration is shown in the table below.

    3. Call ADC_Init() to initialize the ADC peripheral.

ADC Initialization Parameters

ADC Hardware Parameters

Setting in the ADC_InitStruct

ADC_DATA_OUTPUT_TO_FIFO=0

ADC_DATA_OUTPUT_TO_FIFO=1

Sample Time

ADC_InitTypeDef::ADC_SampleTime

255

255

Schedule Index

ADC_InitTypeDef::ADC_SchIndex

Index 0 is set to EXT_SINGLE_ENDED(4)

Index 0 is set to EXT_SINGLE_ENDED(4)

Bit Map

ADC_InitTypeDef::ADC_Bitmap

0x01

0x01

Data Write to FIFO

ADC_InitTypeDef::ADC_DataWriteToFifo

DISABLE

ENABLE

FIFO Threshold Level

ADC_InitTypeDef::ADC_FifoThdLevel

-

0x0A

Power Always On

ADC_InitTypeDef::ADC_PowerAlwaysOnEn

ENABLE

ENABLE

  1. If ADC_MODE_DIVIDE_OR_BYPASS is configured as ADC_BYPASS_MODE, the function ADC_BypassCmd() must be called to enable the Bypass mode for the corresponding pin.

  2. Call ADC_INTConfig() to configure the ADC interrupt and NVIC. For NVIC configurations, refer to Interrupt Configuration.

    1. If ADC_DATA_OUTPUT_TO_FIFO is configured as 0, configure the ADC one shot done interrupt ADC_INT_ONE_SHOT_DONE.

    2. If ADC_DATA_OUTPUT_TO_FIFO is configured as 1, configure the ADC FIFO threshold interrupt ADC_INT_FIFO_THD.

  3. 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.

Functional Implementation

ADC Sampling Data Not Stored in FIFO

When ADC sampling data is not stored in FIFO, the flow of one shot interrupt mode is shown in the figure:

Here should be ADC one shot interrupt not FIFO flow

ADC one shot interrupt mode flow(ADC Sampling Data Not Stored in FIFO)

  1. Loop call ADC_Cmd() to start ADC sampling.

  2. When ADC sampling is complete, trigger the ADC one shot done interrupt ADC_INT_ONE_SHOT_DONE. Within the interrupt function, call the ADC_ReadRawData() function to read the sampling data of the corresponding channel. Execute the ADC_GetVoltage() function, input the corresponding sampling mode, and convert the sampling data to a voltage value.

    void SAR_ADC_Handler(void)
    {
        DBG_DIRECT("into SAR_ADC_Handler");
        ADC_ErrorStatus error_status = NO_ERROR;
    
    #if (!ADC_DATA_OUTPUT_TO_FIFO)
        ...
    
        if (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == SET)
        {
            ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE);
    
            sample_data = ADC_ReadRawData(ADC, ADC_Schedule_Index_0);
    #if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE)
            sample_voltage = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data, &error_status);
    #else
            sample_voltage = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data, &error_status);
    #endif
            ...
        }
    #else
        ...
    #endif
    }
    

ADC Sampling Data Stored in FIFO

When ADC sampling data is stored in FIFO, the flow of one shot interrupt mode is as shown in the figure:

Here should be ADC one shot interrupt FIFO flow

ADC one shot interrupt mode flow(ADC Sampling Data Stored in FIFO)

  1. Before ADC sampling, call ADC_ClearFIFO() to clear the data in the ADC FIFO.

  2. Loop call ADC_Cmd() to start ADC sampling.

  3. When the sampled data in the FIFO reaches the threshold, trigger the ADC ADC_INT_FIFO_THD interrupt, and within the interrupt function, call ADC_GetFIFODataLen() to read the data length in the FIFO; call ADC_ReadFIFOData() function to read the data in the FIFO; call ADC_GetVoltage() function, input the corresponding sampling mode, and convert the sampled data to voltage values.

  4. After the data processing is complete, call ADC_ClearFIFO() to clear the data in the ADC FIFO.

    void SAR_ADC_Handler(void)
    {
        DBG_DIRECT("into SAR_ADC_Handler");
        ADC_ErrorStatus error_status = NO_ERROR;
    
    #if (!ADC_DATA_OUTPUT_TO_FIFO)
    ...
    #else
        if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_THD) == SET)
        {
            uint16_t data_len = ADC_GetFIFODataLen(ADC);
            ADC_ReadFIFOData(ADC, sample_data, data_len);
            for (uint8_t i = 0; i < data_len; i++)
            {
    #if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE)
                sample_voltage[i] = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data[i], &error_status);
    #else
                sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status);
    #endif
                ...
            }
            ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD);
            ADC_ClearFIFO(ADC);
        }
    #endif
    }