One Shot Mode - Polling Mode

This example uses the ADC one shot mode for voltage detection.

This example performs ADC sampling by polling the ADC_INT_ONE_SHOT_DONE interrupt. When sampling completion is detected, the raw data in the ADC FIFO is read and voltage conversion calculations are performed.

In this example, the voltage sampling range of the ADC can be selected by configuring the macro ADC_MODE_DIVIDE_OR_BYPASS.

Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL8752H HDK

RTL8752H EVB

For more requirements, please refer to Quick Start.

Wiring

Connect P2_4, P2_5 and P2_7 to the external voltage input.

Configurations

The macros that can be configured in this example are as follows:

  1. ADC_MODE_DIVIDE_OR_BYPASS : Configures the ADC voltage sampling range, with the following selectable values.

    • ADC_DIVIDE_MODE : In Divide Mode, the ADC samples voltage values ranging from 0 to 3.3V.

    • ADC_BYPASS_MODE : In Bypass Mode, the ADC samples voltage values ranging from 0 to 0.9V.

Building and Downloading

This sample can be found in the SDK folder:

Project file: board\evb\io_sample\ADC\OneShotMode_Polling\mdk

Project file: board\evb\io_sample\ADC\OneShotMode_Polling\gcc

Please follow these steps to build and run the example:

  1. Open sample project file.

  2. To build the target, follow the steps listed on the Generating App Image in Quick Start.

  3. After a successful compilation, the app bin app_MP_xxx.bin will be generated in the directory mdk\bin or gcc\bin.

  4. To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.

  5. Press reset button on EVB board and it will start running.

Experimental Verification

  1. ADC Configurations:

    1. If the ADC is configured as ADC_DIVIDE_MODE, print the following log.

      [ADC]ADC sample mode is divide mode !
      
    2. If the ADC is configured as ADC_BYPASS_MODE, print the following log.

      [ADC]ADC sample mode is bypass mode !
      
  2. After the ADC sampling is finished, the raw data acquired and the converted voltage values are printed within the Debug Analyzer.

    [io_adc] io_adc_voltage_calculate: ADC one shot mode sample data_0 = xxx, voltage_0 = xxxmV
    [io_adc] io_adc_voltage_calculate: ADC one shot mode sample data_1 = xxx, voltage_1 = xxxmV
    ...
    

Code Overview

This chapter will be introduced according to the following several parts:

  1. Source Code Directory.

  2. Peripheral initialization will be introduced in chapter Initialization.

  3. Functional implementation after initialization will be introduced in chapter Function Implementation.

Source Code Directory

  • Project directory: sdk\board\evb\io_sample\ADC\OneShotMode_Polling

  • Source code directory: sdk\src\sample\io_sample\ADC\OneShotMode_Polling

Source files are currently categorized into several groups as below.

└── Project: adc_oneshot_polling
    └── secure_only_app
        └── include
            ├── app_define.h
            └── rom_uuid.h
        ├── cmsis                    includes CMSIS header files and startup files
            ├── overlay_mgr.c
            ├── system_rtl876x.c
            └── startup_rtl876x.s
        ├── lib                      includes all binary symbol files that user application is built on
            ├── rtl8752h_sdk.lib
            ├── gap_utils.lib
            ├── ROM.lib
            └── adc.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl876x_rcc.c
            ├── rtl876x_pinmux.c
            ├── rtl876x_nvic.c
            └── rtl876x_adc.c
        ├── profile
        └── app                      includes the ble_peripheral user application implementation
            ├── main.c
            ├── ancs.c
            ├── app.c
            ├── app_task.c
            └── io_adc.c

Initialization

When the EVB resets and starts, it executes the main function and follows this process:

int main(void)
{
    extern uint32_t random_seed_value;
    srand(random_seed_value);
    adc_demo();

    while (1)
    {
        DBG_DIRECT("[ADC]Polling reads adc sample data !");
        adc_sample_demo();
        for (uint32_t i = 500000; i > 0; i--);
        ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE);
    }
}

In adc_demo, it includes processes such as ADC calibration, PAD/PINMUX settings, and ADC peripheral initialization.

void adc_demo(void)
{
    /* Initialize adc k value! */
    bool adc_k_status;
    adc_k_status = ADC_CalibrationInit();
    if (false == adc_k_status)
    {
        APP_PRINT_ERROR0("[ADC]ADC_CalibrationInit fail!");
    }
    /* Configure pad and pinmux firstly! */
    board_adc_init();

    /* Initialize adc peripheral */
    driver_adc_init();

    /* Enable adc */
    ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE);
}

board_adc_init is used for PAD/PINMUX settings and includes the following processes:

  1. Config PAD: Set pin as SW mode, PowerOn, internal Pull-None, disable output.


driver_adc_init is the initialization of the ADC peripheral and includes the following process:

  1. Enable RCC clock.

  2. Configure ADC sampling channels, configure all channels to P2_7 single-ended mode, set Bitmap to 0xFFFF.

  3. If configured as bypass mode, execute ADC_BypassCmd() to enable the high resistance mode of the corresponding channel.

  4. Configure ADC interrupt ADC_INT_ONE_SHOT_DONE.

void driver_adc_init(void)
{
    RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);

    ADC_InitTypeDef ADC_InitStruct;
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.ADC_SampleTime       = 255;
    for (uint8_t i = 0; i < 16; i++)
    {
#ifdef INTERNAL_VBAT_TEST
        ADC_InitStruct.ADC_SchIndex[i] = INTERNAL_VBAT_MODE;
#else
        ADC_InitStruct.ADC_SchIndex[i]  = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_7);
#endif
    }
    ADC_InitStruct.ADC_Bitmap           = 0xFFFF;
    ADC_InitStruct.ADC_PowerAlwaysOnEn  = ADC_POWER_ALWAYS_ON_ENABLE;
    ADC_Init(ADC, &ADC_InitStruct);

#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE)
    /* High bypass resistance mode config, please notice that the input voltage of
    adc channel using high bypass mode should not be over 0.9V */
    ADC_BypassCmd(ADC_SAMPLE_CHANNEL_6, ENABLE);
    DBG_DIRECT("[ADC]ADC sample mode is bypass mode !");
#else
    DBG_DIRECT("[ADC]ADC sample mode is divide mode !");
#endif
    ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE);
}

Functional Implementation

  1. Execute ADC_Cmd() to start the ADC sampling. In the main function, loop through adc_sample_demo to process the ADC sampling data.

  2. In adc_sample_demo, it loops to check the ADC single conversion completion interrupt status. After the ADC single conversion is completed, clear the interrupt flag bit.

  3. Execute ADC_ReadRawData() to read the ADC sampling data.

  4. Execute ADC_GetVoltage() to convert the sampling data to a voltage value.

    void adc_sample_demo(void)
    {
        uint16_t sample_data[16] = {0};
        float sample_voltage[16] = {0};
        ADC_ErrorStatus error_status = NO_ERROR;
    
        while (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == RESET);
        ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE);
        for (uint8_t i = 0; i < 16; i++)
        {
            sample_data[i] = ADC_ReadRawData(ADC, ADC_Schedule_Index_0 + i);
        }
    
        for (uint8_t i = 0; i < 16; 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
            if (error_status < 0)
            {
                DBG_DIRECT("[ADC]adc_sample_demo: ADC parameter or efuse data error! i = %d, error_status = %d", i,
                        error_status);
            }
            else
            {
                DBG_DIRECT("[ADC] adc_sample_demo: ADC one shot mode sample data_%d = %d, voltage_%d = %dmV ", i,
                        sample_data[i], i, (uint32_t)sample_voltage[i]);
            }
        }
    }
    

Troubleshooting

  1. If the IC obtained has not been verified by FT, the ADC will not be able to convert to the correct voltage value. The following message will be printed within the log tool.

    [ADC]ADC_CalibrationInit fail!
    
  2. If the ADC sample value is incorrect, print the error status.

    [ADC]adc_sample_demo: ADC parameter or efuse data error! i = xxx, error_status = xxx