ADC Key Detection

This sample code guide is designed to help users easily and comprehensively understand ADC sample. This sample demonstrates how to detect key presses using ADC and LPC.

Requirements

For hardware requirements, please refer to the Requirements.

Wiring

Connect P0_3 to an external key module.

The hardware connection of ADC sample code is shown in the figure below.

../../../_images/ADC_Key_Sample_Code_Hardware_Connection_Diagram.png

ADC Sample Code Hardware Connection Diagram

Configurations

  1. The entry function is as follows, call this function in main() to run this sample code. For more details, please refer to the Initialization.

    adc_key_demo();
    

Building and Downloading

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

Experimental Verification

  1. Press the Reset button on the EVB board, when a key is pressed, the key information will be printed in Debug Analyzer.

    io_demo_app_task: key mask xx, key_press 1
    
  2. When the key is released, the key information will be printed in Debug Analyzer.

    io_demo_app_task: key mask xx, key_press 0
    

Code Overview

This section introduces the code and process description for initialization and corresponding function implementation in the sample.

Source Code Directory

  • For project directory, please refer to Source Code Directory.

  • Source code directory: sdk\src\sample\io_demo\adc\adc_key\adc_key_demo.c.

Initialization

  1. 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. The ADC initialization parameter configuration is shown in the table below.

    3. Call adc_mgr_register_req() to request for a channel in ADC manager and initialize the ADC peripheral.

    ADC Initialization Parameters

    ADC Hardware Parameters

    Setting in the ADC_InitStruct Variables

    ADC

    Sample Time

    ADC_InitTypeDef::adcClock

    ADC_CLK_39K

    Bit Map

    ADC_InitTypeDef::bitmap

    0x0001

    Schedule Index

    ADC_InitTypeDef::schIndex

    Index 0 is set to EXT_SINGLE_ENDED(3).

  2. Call Pad_Config() and Pinmux_Config() to initialize the pin to LPC function.

    static void board_lpc_init(void)
    {
       Pad_Config(ADC_SAMPLE_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                   PAD_OUT_HIGH);
       Pinmux_Config(ADC_SAMPLE_PIN, IDLE_MODE);
    }
    
  3. Initialize the LPC peripheral:

    1. Define the LPC_InitTypeDef type LPC_InitStruct, and call LPC_StructInit() to pre-fill LPC_InitStruct with default values.

    2. Modify the LPC_InitStruct parameters as needed. The LPC initialization parameter configuration is shown in the table below.

    3. Call LPC_Init() to initialize the LPC peripheral.

    LPC Initialization Parameters

    LPC Hardware Parameters

    Setting in the LPC_InitStruct

    LPC

    Channel

    LPC_InitTypeDef::LPC_Channel

    ADC_SAMPLE_PIN

    Edge

    LPC_InitTypeDef::LPC_Edge

    LPC_Vin_Below_Vth

    Threshold Voltage

    LPC_InitTypeDef::LPC_Threshold

    LPC_3000_mV

  4. Call LPC_CounterReset() to reset the LPC counter.

  5. Call LPC_WriteComparator() to set LPC comparator value.

  6. Call LPC_INTConfig() to enable the LPC comparator interrupt LPC_INT_COUNT_COMP.

  7. For RTL87x3D, call LPC_INTConfig() to enable interrupt signal to CPU NVIC, for RTL87x3E and RTL87x3EP, call RTC_CpuNVICEnable() to enable interrupt signal to CPU NVIC.

  8. For RTL87x3D, call NVIC_Init() to enable NVIC of LPC, for RTL87x3E and RTL87x3EP, call NVIC_Init() to enable NVIC of RTC.

  9. Call LPC_Cmd() to enable the LPC.

  10. Call LPC_CounterCmd() to enable the LPC counter.

DLPS Mode Initialization

  1. Call io_dlps_register() to initialize IO store/restore and do not need to worry about which IO peripheral requires specific handling.

  2. Call io_dlps_register_enter_cb() to register callbacks to DLPS enter stage. Function io_dlps_enter_callback will be executed while entering from DLPS:

    1. Call RTC_SystemWakeupConfig() to enable the LPC system wakeup function.

  3. Call bt_power_mode_set() to set Bluetooth MAC deep sleep mode.

  4. Call power_mode_set() to switch the system to DLPS mode.

Functional Implementation

LPC Interrupt Handle

When the LPC detects that the input voltage exceeds the set voltage threshold (LPC_3000_mV), it triggers an interrupt:

  1. Call LPC_GetINTStatus() to check LPC_INT_COUNT_COMP interrupt status flag.

  2. Call LPC_CounterReset() to reset the LPC counter.

  3. Call LPC_ClearINTPendingBit() to clear the LPC comparator interrupt LPC_INT_COUNT_COMP.

  4. Send a message to the task, and after the task receives the message:

    1. Call LPC_Cmd() to disable the LPC.

    2. Call LPC_CounterCmd() to disable the LPC counter.

    3. Call Pad_Config() and Pinmux_Config() to initialize the pin to ADC function.

    static void board_adc_init(void)
    {
       Pad_Config(ADC_SAMPLE_PIN, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW);
       Pinmux_Config(ADC_SAMPLE_PIN, IDLE_MODE);
    }
    
    1. Call adc_mgr_enable_req() to enable the specific ADC manager channel for sampling.

ADC Manager Callback Handle

When ADC sampling is completed, ADC manager callback function adc_key_read_voltage_callback will be executed.

  1. Call adc_mgr_read_data_req() to read ADC sampling raw data of the specific ADC manager channel.

  2. Call ADC_GetRes() to get ADC conversion result, and get the key index key_index based on the conversion result.

  3. If the key index key_index is not equal to 0xff, it means a key is pressed, and the edge of LPC is adjusted to LPC_Vin_Over_Vth to detect key release.

    1. If adc_key_data.key_press[key_index] is equal to KEY_RELEASE, it means that the last state of this key was released.

      1. Set key_status_update_fg to 1.

      2. Set adc_key_data.key_press[key_index] to update the key state.

      3. Set adc_key_data.key_index to update the key index.

    2. Call Pad_Config() and Pinmux_Config() to initialize the pin to LPC function.

      static void board_lpc_init(void)
      {
         Pad_Config(ADC_SAMPLE_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                     PAD_OUT_HIGH);
         Pinmux_Config(ADC_SAMPLE_PIN, IDLE_MODE);
      }
      
    3. Call LPC_SetTriggerEdge() to set LPC trigger edge to LPC_Vin_Over_Vth.

    4. Call LPC_Cmd() to enable the LPC.

    5. Call LPC_CounterCmd() to enable the LPC counter.

  4. If the key index key_index is equal to 0xff, it means a key is released, and the edge of LPC is adjusted to LPC_Vin_Below_Vth to detect key press.

    1. If adc_key_data.key_index is not equal to 0xff and adc_key_data.key_press[adc_key_data.key_index] is equal to KEY_PRESS, it means that the last state of this key was pressed.

      1. Set key_status_update_fg to 1.

      2. Set adc_key_data.key_press[adc_key_data.key_index] to update the key state.

      3. Set adc_key_data.key_index to update the key index.

    2. Call Pad_Config() and Pinmux_Config() to initialize the pin to LPC function.

      static void board_lpc_init(void)
      {
         Pad_Config(ADC_SAMPLE_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                     PAD_OUT_HIGH);
         Pinmux_Config(ADC_SAMPLE_PIN, IDLE_MODE);
      }
      
    3. Call LPC_SetTriggerEdge() to set LPC trigger edge to LPC_Vin_Below_Vth.

    4. Call LPC_Cmd() to enable the LPC.

    5. Call LPC_CounterCmd() to enable the LPC counter.

  5. If key_status_update_fg is set to 1, send a message to the task, and after the task receives the message, print key information.