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:
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:
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:
Open sample project file.
To build the target, follow the steps listed on the Generating App Image in Quick Start.
After a successful compilation, the app bin
app_MP_xxx.bin
will be generated in the directorymdk\bin
orgcc\bin
.To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.
Press reset button on EVB board and it will start running.
Experimental Verification
ADC Configurations:
If the ADC is configured as
ADC_DIVIDE_MODE
, print the following log.[ADC]ADC sample mode is divide mode !
If the ADC is configured as
ADC_BYPASS_MODE
, print the following log.[ADC]ADC sample mode is bypass mode !
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:
Peripheral initialization will be introduced in chapter Initialization.
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:
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:
Enable RCC clock.
Configure ADC sampling channels, configure all channels to P2_7 single-ended mode, set Bitmap to 0xFFFF.
If configured as bypass mode, execute
ADC_BypassCmd()
to enable the high resistance mode of the corresponding channel.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
Execute
ADC_Cmd()
to start the ADC sampling. In the main function, loop throughadc_sample_demo
to process the ADC sampling data.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.Execute
ADC_ReadRawData()
to read the ADC sampling data.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
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!
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