One Shot Interrupt

该示例通过使用 ADC 单次采样中断模式进行电压检测。

当 ADC 采样完成时,触发中断,在中断函数内读取 raw data 并进行电压转换计算。

用户可以通过不同的宏配置改变示例中 ADC 通道的采样模式,输入电压范围等信息,具体宏配置详见 配置选项

环境需求

该示例的环境需求,可参考 环境需求

硬件连线

使用杜邦线短接 P2_4 和外部输入电压。

配置选项

  1. 可配置如下宏修改 ADC 的采样值是否存入 FIFO 中, 1 表示 ADC 采样数据存入 FIFO 中, 0 表示 ADC 数据存入对应的 Schedule Table 中。

    #define ADC_DATA_OUTPUT_TO_FIFO             0                   /*< Set this macro to configure whether ADC data is stored in the FIFO. */
    
  2. 可配置如下宏修改 ADC 输入电压范围。

    #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. 可配置如下宏修改引脚定义。

    #define ADC_SAMPLE_PIN                      P2_4
    #define ADC_SAMPLE_CHANNEL                  ADC_Channel_Index_4
    

编译和下载

该示例的编译和下载流程,可参考 编译和下载

测试验证

  1. EVB 启动后,在 Debug Analyzer 工具内观察 log:

    Start ADC interrupt test!
    
  2. ADC 初始化配置:

    1. ADC_MODE_DIVIDE_OR_BYPASS 配置为 ADC_DIVIDE_MODE ,则会打印如下 log:

      [ADC]ADC sample mode is divide mode !
      
    2. ADC_MODE_DIVIDE_OR_BYPASS 配置为 ADC_BYPASS_MODE ,则会打印如下 log:

      [ADC]ADC sample mode is bypass mode !
      
  3. 初始化完成后 ADC 开始采样。ADC 单次采样结束后会触发中断,在中断函数内打印采样得到的 raw data 和转换后的电压值。

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

代码介绍

该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。

源码路径

工程文件和源码路径如下:

  • 工程路径: sdk\samples\peripheral\adc\oneshot_interrupt\proj

  • 源码路径: sdk\samples\peripheral\adc\oneshot_interrupt\src

初始化

外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。

  1. 调用 Pad_Config()Pinmux_Config(),配置对应引脚的 PAD 和 PINMUX。注意需要配置 PAD 为 Shutdown 模式,防止漏电。

    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. 调用 RCC_PeriphClockCmd() ,开启 ADC 时钟。

  3. 对 ADC 外设进行初始化:

    1. 定义 ADC_InitTypeDef 类型 ADC_InitStruct ,调用 ADC_StructInit()ADC_InitStruct 预填默认值。

    2. 根据需求修改 ADC_InitStruct 参数,当 ADC_DATA_OUTPUT_TO_FIFO 配置为不同值时,初始化配置会有所不同。ADC 的初始化参数配置如下表。

    3. 调用 ADC_Init(),初始化 ADC 外设。

ADC 初始化参数

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. ADC_MODE_DIVIDE_OR_BYPASS 配置为 ADC_BYPASS_MODE,需要调用函数 ADC_BypassCmd() 开启对应引脚的 Bypass 模式。

  2. 调用 ADC_INTConfig() ,配置 ADC 中断和 NVIC。NVIC 相关配置可参考 中断配置

    1. ADC_DATA_OUTPUT_TO_FIFO 配置为 0,配置 ADC 单次采样完成中断 ADC_INT_ONE_SHOT_DONE

    2. ADC_DATA_OUTPUT_TO_FIFO 配置为 1,配置 ADC FIFO 达到阈值中断 ADC_INT_FIFO_THD

  3. 在 ADC 开始采样前,必须调用 ADC_CalibrationInit() 进行 ADC 电压校准。若返回值为 false,则代表该 IC 未经校验,无法正确转换电压值,但仍可读到 raw data。

功能实现

ADC 采样数据不存入 FIFO

当 ADC 采样数据不存入 FIFO 时,中断模式单次采样的流程如图所示:

这里应该是 ADC one shot interrupt not FIFO flow

ADC 中断模式单次采样流程图( ADC 采样数据不存入 FIFO )

  1. 循环调用 ADC_Cmd() ,开始 ADC 采样。

  2. 当 ADC 采样完成时,触发 ADC 单次采样完成中断 ADC_INT_ONE_SHOT_DONE。在中断函数内,调用 ADC_ReadRawData() 函数,读取对应通道的采样数据。调用 ADC_GetVoltage() 函数,输入对应采样模式,将采样数据转换为电压值。

    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 采样数据存入 FIFO

当 ADC 采样数据存入 FIFO 时,中断模式单次采样的流程如图所示:

这里应该是 ADC one shot interrupt FIFO flow

ADC 中断模式单次采样流程图( ADC 采样数据存入 FIFO )

  1. 在 ADC 采样前调用 ADC_ClearFIFO() 清空 ADC FIFO 内数据。

  2. 循环调用 ADC_Cmd() ,开始 ADC 采样。

  3. 当 FIFO 中的采样数据达到设定的阈值时,触发 ADC ADC_INT_FIFO_THD 中断,在中断函数内调用 ADC_GetFIFODataLen() 读取 FIFO 中数据长度;调用 ADC_ReadFIFOData() 函数读取 FIFO 内数据;调用 ADC_GetVoltage() 函数,输入对应采样模式,将采样数据转换为电压值。

  4. 数据处理完毕后,调用 ADC_ClearFIFO() 清空 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
    }