One Shot Interrupt
该示例通过使用 ADC 单次采样中断模式进行电压检测。
当 ADC 采样完成时,触发中断,在中断函数内读取 raw data 并进行电压转换计算。
用户可以通过不同的宏配置改变示例中 ADC 通道的采样模式,输入电压范围等信息,具体宏配置详见 配置选项。
环境需求
该示例的环境需求,可参考 环境需求。
硬件连线
使用杜邦线短接 P2_4 和外部输入电压。
配置选项
可配置如下宏修改 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. */
可配置如下宏修改 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. */
可配置如下宏修改引脚定义。
#define ADC_SAMPLE_PIN P2_4 #define ADC_SAMPLE_CHANNEL ADC_Channel_Index_4
编译和下载
该示例的编译和下载流程,可参考 编译和下载。
测试验证
EVB 启动后,在 Debug Analyzer 工具内观察 log:
Start ADC interrupt test!
ADC 初始化配置:
若
ADC_MODE_DIVIDE_OR_BYPASS
配置为ADC_DIVIDE_MODE
,则会打印如下 log:[ADC]ADC sample mode is divide mode !
若
ADC_MODE_DIVIDE_OR_BYPASS
配置为ADC_BYPASS_MODE
,则会打印如下 log:[ADC]ADC sample mode is bypass mode !
初始化完成后 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 中的 初始化流程 部分。
调用
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); }
调用
RCC_PeriphClockCmd()
,开启 ADC 时钟。对 ADC 外设进行初始化:
定义
ADC_InitTypeDef
类型ADC_InitStruct
,调用ADC_StructInit()
将ADC_InitStruct
预填默认值。根据需求修改
ADC_InitStruct
参数,当ADC_DATA_OUTPUT_TO_FIFO
配置为不同值时,初始化配置会有所不同。ADC 的初始化参数配置如下表。调用
ADC_Init()
,初始化 ADC 外设。
ADC Hardware Parameters |
Setting in the |
|
|
---|---|---|---|
Sample Time |
255 |
255 |
|
Schedule Index |
Index 0 is set to |
Index 0 is set to |
|
Bit Map |
0x01 |
0x01 |
|
Data Write to FIFO |
|||
FIFO Threshold Level |
- |
0x0A |
|
Power Always On |
若
ADC_MODE_DIVIDE_OR_BYPASS
配置为ADC_BYPASS_MODE
,需要调用函数ADC_BypassCmd()
开启对应引脚的 Bypass 模式。调用
ADC_INTConfig()
,配置 ADC 中断和 NVIC。NVIC 相关配置可参考 中断配置。若
ADC_DATA_OUTPUT_TO_FIFO
配置为0
,配置 ADC 单次采样完成中断ADC_INT_ONE_SHOT_DONE
。若
ADC_DATA_OUTPUT_TO_FIFO
配置为1
,配置 ADC FIFO 达到阈值中断ADC_INT_FIFO_THD
。
在 ADC 开始采样前,必须调用
ADC_CalibrationInit()
进行 ADC 电压校准。若返回值为 false,则代表该 IC 未经校验,无法正确转换电压值,但仍可读到 raw data。
功能实现
ADC 采样数据不存入 FIFO
当 ADC 采样数据不存入 FIFO 时,中断模式单次采样的流程如图所示:

ADC 中断模式单次采样流程图( ADC 采样数据不存入 FIFO )
循环调用
ADC_Cmd()
,开始 ADC 采样。当 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 中断模式单次采样流程图( ADC 采样数据存入 FIFO )
在 ADC 采样前调用
ADC_ClearFIFO()
清空 ADC FIFO 内数据。循环调用
ADC_Cmd()
,开始 ADC 采样。当 FIFO 中的采样数据达到设定的阈值时,触发 ADC
ADC_INT_FIFO_THD
中断,在中断函数内调用ADC_GetFIFODataLen()
读取 FIFO 中数据长度;调用ADC_ReadFIFOData()
函数读取 FIFO 内数据;调用ADC_GetVoltage()
函数,输入对应采样模式,将采样数据转换为电压值。数据处理完毕后,调用
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 }