One Shot Interrupt

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

示例中可以用宏 ADC_DATA_OUTPUT_TO_FIFO 去配置是否将ADC采样值存入FIFO中。

示例中可用宏去配置ADC的采样电压范围,包含了Divide Mode和Bypass Mode。

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

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考快速入门

硬件连线

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

配置选项

该示例可配置的宏如下:

  1. ADC_DATA_OUTPUT_TO_FIFO :配置该宏可选择ADC的采样值是否存入FIFO中, 1 表示ADC采样数据存入FIFO中, 0 表示ADC数据存入Schedule Table中。

  2. ADC_MODE_DIVIDE_OR_BYPASS :配置该宏可选择ADC的电压采样范围,可选择的值如下:

    • ADC_DIVIDE_MODE :在Divide Mode下,ADC的采样电压值范围为0~3.3V

    • ADC_BYPASS_MODE :在Bypass Mode下,ADC的采样电压值范围为0~0.9V

编译和下载

该示例的工程路径如下:

Project file: samples\peripheral\adc\oneshot_interrupt\proj\rtl87x2g\mdk

Project file: samples\peripheral\adc\oneshot_interrupt\proj\rtl87x2g\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MP Tool 给出的步骤将app bin烧录至EVB内。

  5. 按下复位按键,开始运行。

测试验证

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

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

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

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

      [ADC]ADC sample mode is bypass mode !
      
  3. ADC采样后,在中断函数内打印采样得到的rawdata和转换后的电压值。

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

代码介绍

该章节分为以下几个部分:

  1. 源码路径

  2. 初始化函数将在 初始化 章节介绍。

  3. 初始化后的功能实现将在 功能实现 章节介绍。

源码路径

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

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

该工程的工程文件代码结构如下:

└── Project: oneshot_interrupt
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── Lib                      includes all binary symbol files that user application is built on
            └── rtl87x2g_io.lib
        ├── Peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_rcc.c
            ├── rtl_pinmux.c
            ├── rtl_nvic.c
            └── rtl_adc.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            └── io_adc.c

初始化

初始化流程包括了 board_adc_initdriver_adc_init


board_adc_init 中包含了PAD设置。

  1. 配置PAD:设置引脚、SW模式、PowerOn、无内部上拉、输出失能、输出低。


driver_adc_init 包含了对ADC外设的初始化。

  1. 使能PCC时钟。

  2. 配置ADC的采样通道,配置通道0为P2_4单端模式,设置Bitmap为0x01。

  3. 若开启宏 ADC_DATA_OUTPUT_TO_FIFO ,设置 ADC_DataWriteToFifo 为ENABLE,设置FIFO Threshold Level。

  4. 若开启Bypass Mode,执行函数 ADC_BypassCmd() 开启对应引脚的Bypass模式。

  5. 配置ADC中断

  RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE);
  ...
  /* Configure the ADC sampling schedule0 */
  ADC_InitStruct.ADC_SchIndex[0]      = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL);
  /* Set the bitmap corresponding to schedule0*/
  ADC_InitStruct.ADC_Bitmap           = 0x01;

#if (ADC_DATA_OUTPUT_TO_FIFO)
  ADC_InitStruct.ADC_DataWriteToFifo  = ENABLE;
  ADC_InitStruct.ADC_FifoThdLevel     = 0x0A;
#endif
  ...
#if (!ADC_DATA_OUTPUT_TO_FIFO)
  ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE);
#else
  ADC_INTConfig(ADC, ADC_INT_FIFO_THD, ENABLE);
#endif

功能实现

  1. 若开启宏 ADC_DATA_OUTPUT_TO_FIFO ,在ADC采样前执行 ADC_ClearFIFO() 清空ADC FIFO内数据。

  2. 循环执行 ADC_Cmd() ,开始ADC采样。

  3. ADC采样完成后,触发ADC中断,在ADC中断函数内对采样数据进行处理。

  4. 若开启宏 ADC_DATA_OUTPUT_TO_FIFO ,则触发的ADC中断为 ADC_INT_FIFO_THD ,执行 ADC_GetFIFODataLen() 读取FIFO中数据长度,执行 ADC_ReadFIFOData() 函数读取FIFO内数据。

  5. 若未开启宏 ADC_DATA_OUTPUT_TO_FIFO ,执行 ADC_ReadRawData() 函数,读取ADC采样数据。

  6. 执行 ADC_GetVoltage() 函数,将采样数据转换为电压值。

  7. 若开启宏 ADC_DATA_OUTPUT_TO_FIFO ,在数据处理后执行 ADC_ClearFIFO() 清空ADC FIFO内数据。

#if (!ADC_DATA_OUTPUT_TO_FIFO)
  while (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == RESET) {}
  ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE);
  ...
  sample_data[i] = ADC_ReadRawData(ADC, ADC_Schedule_Index_0 + i);
  sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status);

#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++)
    {
        sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status);
    }
    ...
    ADC_ClearFIFO(ADC);
  }
#endif

常见问题

  1. 若拿到的IC未经过FT校验,ADC则无法转换为正确的电压值。在log工具内会打印如下信息。

    [ADC]ADC_CalibrationInit fail!
    
  2. 若ADC采样值不正确,则会打印错误状态信息。

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