ADC
简要说明
ADC(Analog-to-Digital Converter)模拟/数字转换驱动,可以将外部模拟量转换为数字量,并且信号比较和触发中断的功能。
接口描述
drv_adc_initialize
adc_handle_t drv_adc_initialize(int32_t idx, adc_event_cb_t cb_event);
功能描述:
- 通过设备号初始化对应的adc实例,返回adc实例的句柄。
参数:
idx
: 设备号。cb_event
: adc实例的事件回调函数。应用可根据回调函数做相应的睡前睡后行为。回调函数原型定义见adc_event_cb_t。回调函数类型adc_event_cb_t定义如下:
typedef void (*adc_event_cb_t)(int32_t idx, adc_event_e event);
其中idx为设备号,event 为传给回调函数的事件类型。
ADC回调事件枚举类型见 adc_event_e 定义。
返回值:
- NULL: 初始化失败。
- 其它: 实例句柄。
adc_event_e:
名称 | 定义 | 备注 |
---|---|---|
ADC_EVENT_CONVERSION_COMPLETE | 所有数据转换完毕 | |
ADC_EVENT_DATA_LOST | 数据丢失 | |
ADC_EVENT_DATA_OVERWRITE | 将新转换结果加载到数据寄存器前,尚未读取转换到后数据。 | |
ADC_EVENT_DATA_COMPARE_VALID | 数据比较匹配 |
drv_adc_uninitialize
int32_t drv_adc_uninitialize(adc_handle_t handle);
- 功能描述:
- 反初始化adc实例。
- 参数:
handle
: adc实例句柄。
- 返回值:
- 0: 成功。
- 其它: 错误码。
drv_adc_power_control
int32_t drv_adc_power_control(adc_handle_t handle, csi_power_stat_e state)
- 功能描述:
- adc功耗控制。
- 参数:
handle
: adc实例句柄。state
: 设置功耗状态,见csi_power_stat_e定义。
- 返回值:
- 0: 成功。
- 其它: 错误码。
csi_power_stat_e
名称 | 定义 | 备注 |
---|---|---|
DRV_POWER_OFF | 关闭电源 | |
DRV_POWER_LOW | 保持状态,检测并发出唤醒事件的信号 | |
DRV_POWER_FULL | 全功率模式 | |
DRV_POWER_SUSPEND | 省电模式 |
drv_adc_get_capabilities
adc_capabilities_t drv_adc_get_capabilities(int32_t idx);
- 功能描述:
- 获取adc 功能列表。
- 参数:
idx
: adc设备号。
- 返回值:
- adc功能表,见adc_capabilities_t定义。
名称 | 定义 | 备注 |
---|---|---|
single | 单次采集模式:1支持,0不支持 | |
continuous | 连续采集模式:1支持,0不支持 | |
scan | 扫描模式:1支持,0不支持 | |
calibration | 校准模式:1支持,0不支持 | |
comparator | 比较模式:1支持,0不支持 |
drv_adc_config
int32_t drv_adc_config(adc_handle_t handle, adc_conf_t *config);
- 功能描述:
- 配置adc。
- 参数:
handle
: adc实例句柄。config
: adc配置参数,见adc_conf_t定义。
- 返回值:
- 0: 成功。
- 其它: 错误码。
adc_conf_t
名称 | 定义 | 备注 |
---|---|---|
clk_prescaler | 时钟源 | |
mode | adc运行模式,见adc_mode_e定义 | |
trigger | adc启动触发,0软件启动,1外部中断触发启动。 | |
intrp_mode | 1:ADC中断模式;0:ADC轮询模式 | |
channel_array | 指向adc通道数组,将要启用的通道写在该数组内 | |
channel_nbr | adc通道数组的大小 | |
conv_cnt | adc数据采集次数 | |
sampling_time | 采样时间值。单位:ADC时钟周期。 | |
offset | 预留 |
adc_mode_e
名称 | 定义 | 备注 |
---|---|---|
ADC_SINGLE | 单次采集模式 | |
ADC_CONTINUOUS | 连续采集模式 | |
ADC_SCAN | 连续多通道采集模式 |
drv_adc_comparator_config
int32_t drv_adc_comparator_config(adc_handle_t handle, adc_cmp_conf_t *config);
- 功能描述:
- adc 比较器配置。
- 参数:
handle
: adc实例句柄。config
: adc比较器参数,见adc_cmp_conf_t定义。
- 返回值:
- 0: 成功。
- 其它: 错误码。
adc_cmp_conf_t
名称 | 定义 | 备注 |
---|---|---|
cmp_data | 与转换结果进行比较的值 | |
cmp_channel | 指定比较的通道 | |
cmp_condition | 0:转换结果 < cmp_data时匹配;1:转换结果>=cmp_data时匹配 | |
cmp_match_cnt | 设置匹配计数器的阈值;匹配次数达到cmp_match_cnt时,触发标志位转换 |
drv_adc_start
int32_t drv_adc_start(adc_handle_t handle);
- 功能描述:
- adc 启动转换。
- 参数:
handle
: adc实例句柄。
- 返回值:
- 0: 成功。
- 其它: 错误码。
drv_adc_stop
int32_t drv_adc_stop(adc_handle_t handle);
- 功能描述:
- adc 停止转换。
- 参数:
handle
: adc实例句柄。
- 返回值:
- 0: 成功。
- 其它: 错误码。
drv_adc_read
int32_t drv_adc_read(adc_handle_t handle, uint32_t *data, uint32_t num);
- 功能描述:
- adc 读取转换结果。
- 参数:
handle
: adc实例句柄。data
: 存贮转换结果。num
: 读取结果的个数。
- 返回值:
- 0: 成功。
- 其它: 错误码。
drv_adc_get_status
adc_status_t drv_adc_get_status(adc_handle_t handle);
- 功能描述:
- 获取adc状态。
- 参数:
handle
: adc实例句柄。
- 返回值:
- adc状态,见adc_status_t定义。
adc_status_t
名称 | 定义 | 备注 |
---|---|---|
busy | 忙碌状态,adc转换中 | |
data_lost | adc buffer溢出,数据丢失 | |
complete | 转换完毕 | |
compare_valid | 数据比较匹配 |
使用例程
ADC可采用单次采样模式或者连续采样模式
本示例,分别使用了单次采样模式和连续采样模式,具体如下:
#include <soc.h>
#include <drv_adc.h>
#include <stdio.h>
#include <pin_name.h>
#include <pin.h>
#include <csi_config.h>
#define TEST_ADC_SINGLE_CHANNEL EXAMPLE_ADC_CHANNEL_USR_DEF0
#define TEST_ADC_CONTINOUS_CHANNEL EXAMPLE_ADC_CHANNEL_USR_DEF0
#define TEST_SINGLE_CONV_TIMES 1
#define TEST_CONTINOUS_CONV_TIMES 4
#define SINGE_DATA_NUM 1
#define CONTINOUS_DATA_NUM (1*TEST_CONTINOUS_CONV_TIMES)
#define SCAN_DATA_NUM 128
#define ADC_TEST_SUCCESS 0
#define ADC_TEST_FAIL -1
#define ADC_DELAY 1000
static volatile uint32_t scan_complete_flag;
extern void mdelay(uint32_t ms);
static int test_adc_single(void)
{
adc_conf_t sconfig;
adc_handle_t hd;
uint32_t data[SINGE_DATA_NUM] = {0x314};
uint32_t ch_array[1] = {TEST_ADC_SINGLE_CHANNEL};
int ret = 0;
printf("example single mode:\n");
sconfig.mode = ADC_SINGLE;
sconfig.trigger = 0;
sconfig.intrp_mode = 0;
sconfig.sampling_time = 2;
sconfig.channel_array = ch_array;
sconfig.channel_nbr = TEST_SINGLE_CONV_TIMES;
#ifdef EXAMPLE_ADC_CH_PIN_USR_DEF0_FUNC
drv_pinmux_config(EXAMPLE_ADC_CH_PIN_USR_DEF0, EXAMPLE_ADC_CH_PIN_USR_DEF0_FUNC);
#endif
hd = drv_adc_initialize(0, NULL);
if (!hd) {
printf("adc initial failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_config(hd, &sconfig);
if (ret != 0 && ret != (CSI_DRV_ERRNO_ADC_BASE | DRV_ERROR_UNSUPPORTED)) {
printf("adc config failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_start(hd) != 0) {
printf("adc start failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_read(hd, &data[SINGE_DATA_NUM - 1], SINGE_DATA_NUM);
if (ret) {
printf("read ad ret = %d\n", ret);
}
printf("read single data from adc: 0x%x\n\n", data[SINGE_DATA_NUM - 1]);
if (drv_adc_stop(hd) != 0) {
printf("adc stop failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_uninitialize(hd) != 0) {
printf("adc uninitial failed\n");
return ADC_TEST_FAIL;
}
return ADC_TEST_SUCCESS;
}
static int test_adc_continous(void)
{
adc_conf_t sconfig;
adc_handle_t hd;
uint32_t data[CONTINOUS_DATA_NUM];
uint32_t ch_array[16] = {TEST_ADC_SINGLE_CHANNEL, TEST_ADC_SINGLE_CHANNEL,
TEST_ADC_SINGLE_CHANNEL, TEST_ADC_SINGLE_CHANNEL};
int i = 0;
int ret = 0;
printf("example continous mode:\n");
sconfig.mode = ADC_CONTINUOUS;
sconfig.trigger = 0;
sconfig.intrp_mode = 0;
sconfig.sampling_time = 2;
sconfig.channel_array = ch_array;
sconfig.channel_nbr = TEST_CONTINOUS_CONV_TIMES;
#ifdef EXAMPLE_ADC_CH_PIN_USR_DEF0_FUNC
drv_pinmux_config(EXAMPLE_ADC_CH_PIN_USR_DEF0, EXAMPLE_ADC_CH_PIN_USR_DEF0_FUNC);
#endif
for (i = 0; i < CONTINOUS_DATA_NUM; i++) {
data[i] = 0x31415;
}
hd = drv_adc_initialize(0, NULL);
if (!hd) {
printf("adc initial failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_config(hd, &sconfig);
if (ret == (CSI_DRV_ERRNO_ADC_BASE | DRV_ERROR_UNSUPPORTED)) {
printf("continous mode unsupported\n");
return ADC_TEST_SUCCESS;
}
if (ret != 0) {
printf("adc config failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_start(hd) != 0) {
printf("adc start failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_read(hd, &data[0], CONTINOUS_DATA_NUM);
if (ret) {
printf("read ad ret = %d\n", ret);
}
printf("read a data from adc:\n");
for (i = 0; i < TEST_CONTINOUS_CONV_TIMES; i++) {
printf("0x%x ", data[i]);
if (i % 4 == 3) {
printf("\n");
}
}
printf("\n");
if (drv_adc_stop(hd) != 0) {
printf("adc stop failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_uninitialize(hd) != 0) {
printf("adc uninitial failed\n");
return ADC_TEST_FAIL;
}
return ADC_TEST_SUCCESS;
}
void example_adc_cb(int32_t idx, adc_event_e event)
{
if (event == ADC_EVENT_CONVERSION_HALF_COMPLETE) {
printf("event: ADC_EVENT_CONVERSION_HALF_COMPLETE\n");
} else if (event == ADC_EVENT_CONVERSION_COMPLETE){
scan_complete_flag = 1;
printf("event: ADC_EVENT_CONVERSION_COMPLETE\n");
}
}
int test_adc_scan(void)
{
adc_conf_t sconfig;
adc_handle_t hd;
uint32_t data[SCAN_DATA_NUM + 16];
uint32_t ch_array[16] = {EXAMPLE_ADC_CHANNEL_DEF1, EXAMPLE_ADC_CHANNEL_DEF1, EXAMPLE_ADC_CHANNEL_DEF2, EXAMPLE_ADC_CHANNEL_DEF2};
int i = 0;
int ret = 0;
printf("example scan mode:\n");
sconfig.mode = ADC_SCAN;
sconfig.trigger = 0;
sconfig.intrp_mode = 0;
sconfig.sampling_time = 2;
sconfig.channel_array = &ch_array[0];
sconfig.channel_nbr = 4;
#ifdef EXAMPLE_ADC_CH_PIN_USR_DEF1_FUNC
drv_pinmux_config(EXAMPLE_ADC_CH_PIN_USR_DEF1, EXAMPLE_ADC_CH_PIN_USR_DEF1_FUNC);
drv_pinmux_config(EXAMPLE_ADC_CH_PIN_USR_DEF2, EXAMPLE_ADC_CH_PIN_USR_DEF2_FUNC);
#endif
for (i = 0; i < SCAN_DATA_NUM; i++) {
data[i] = 0x31415;
}
hd = drv_adc_initialize(0, example_adc_cb);
if (!hd) {
printf("adc initial failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_config(hd, &sconfig);
if (ret == (CSI_DRV_ERRNO_ADC_BASE | DRV_ERROR_UNSUPPORTED)) {
printf("continous mode unsupported\n");
return ADC_TEST_SUCCESS;
}
if (ret != 0) {
printf("adc config failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_start(hd) != 0) {
printf("adc start failed\n");
return ADC_TEST_FAIL;
}
ret = drv_adc_read(hd, &data[0], SCAN_DATA_NUM);
if (ret) {
printf("read ad ret = %d\n", ret);
}
printf("read data from adc:\n");
while (!scan_complete_flag);
for (i = 0; i < SCAN_DATA_NUM; i++) {
printf("0x%x ", data[i]);
if (i % 4 == 3) {
printf("\n");
}
}
printf("\n");
scan_complete_flag = 0;
for (i = 0; i < SCAN_DATA_NUM; i++) {
data[i] = 0x31415;
}
drv_adc_read(hd, &data[0], SCAN_DATA_NUM);
while (!scan_complete_flag);
for (i = 0; i < SCAN_DATA_NUM; i++) {
printf("0x%x ", data[i]);
if (i % 4 == 3) {
printf("\n");
}
}
printf("\n");
if (drv_adc_stop(hd) != 0) {
printf("adc stop failed\n");
return ADC_TEST_FAIL;
}
if (drv_adc_uninitialize(hd) != 0) {
printf("adc uninitial failed\n");
return ADC_TEST_FAIL;
}
return ADC_TEST_SUCCESS;
}
int example_adc(void)
{
int ret;
ret = test_adc_single();
if (ret < 0) {
printf("test adc single mode failed\n");
return ADC_TEST_FAIL;
}
ret = test_adc_continous();
if (ret < 0) {
printf("test adc continous mode failed\n");
return ADC_TEST_FAIL;
}
ret = test_adc_scan();
if (ret < 0) {
printf("test adc scan mode failed\n");
return ADC_TEST_FAIL;
}
printf("test adc successfully\n");
return ADC_TEST_SUCCESS;
}
int main(void)
{
return example_adc();
}