跳转至

SARADC采样检测使用指南

SARADC采样检测使用指南*

第一章 概述*

逐次逼近型 ADC(Successive Approximation register ADC)采用的是一种反馈比较型电路结构。它的构思是这样的:取一个数字量加到 DAC 上,于是得到一个对应的输出模拟电压。将这个模拟电压和输入的模拟电压信号相比较。如果两者不相等,则调整所取的数字量,直到两个模拟电压相等为止,最后所取的这个数字量就是所求的转换结果。

我们在做电子产品开发的时候,需要把各种外部传感器的数据,传输给cpu,然后进行计算或者输出显示。

其实这个传感器给到cpu的数据,就是一系列变化的电压。这一系列变化的电压,我们称为模拟量。而我们的cpu,需要通过ADC把它转换为数字量,这样cpu内部的程序才能识别何使用了。

1.1 功能特性*

  • 共有 16 个通道,外部 8 个通道,内部 8 个通道。内部通道用于:如电池电压测量,芯片温度传感器;外部通道用于:连接外部模拟 IO

  • 采样数据深度为 12bit

  • 支持单端和差分信号采样,单端采样将通道号配置在 p 通道上,差分分别配置 p 和 n 通道

  • 只使能 1 个通道的话,最高采样率可达到 4Mbps

  • 支持 DMA 传输采样数据

  • 轮询采样支持部分通道配置阈值,产生阈值中断

1.2 管脚选择*

硬件工程师可以查看芯片的datasheet,描述支持 SARADC 功能的管脚,就可以选用。

重要

SARADC 及相关 IO 的使用限制: 当使用 SARADC 时,P1_0 - P1_7 组 IO,不可以有来自外部的高于 VBAT3 的电压来源。在与外部供电环境交互的是有尤其需要注意。可以规避的做法包括:1)硬件设计时:统一供电来源,外部 IO 与 APUS IO 的供电都统一为 VBAT3。2)硬件设计时:不能让外部比VBAT3更高的电压从P1组灌进来。

第二章 使用示例*

2.1 API 接口描述*

/*
 *      NationalChip Hardware Abstract Layer
 * Copyright (C) 2001-2022 NationalChip Co., Ltd
 *              ALL RIGHTS RESERVED
 *
 * gx_saradc.h: gx_saradc.c header file
 */
#ifndef __GX_SARADC_H__
#define __GX_SARADC_H__

#include <gx_hal_saradc.h>

typedef struct {
    GX_HAL_SARADC_ONCE_INT_CALLBACK_FUNC once_int_cb;
    GX_HAL_SARADC_POLL_INT_CALLBACK_FUNC stop_int_cb;
    GX_HAL_SARADC_THRESHOLD_INT_CALLBACK_FUNC threshold_int_cb;
    unsigned int buff_trim;    /*!< 输入buffer偏置电流 */
    unsigned char clk_gate_en;
    unsigned char ldo_vsel;    /*!< 参考电压配置,可配值范围0~31,0:1.608v,1:1.614v,2:1.62v...1.986v;6mV递进 */
}GX_SARADC_INIT_CFG;

int gx_saradc_init(GX_SARADC_INIT_CFG *cfg);
int gx_saradc_self_cal(GX_HAL_SARADC_SELF_CAL_CFG_T *cfg);
int gx_saradc_get_once_data(GX_HAL_SARADC_ONCE_CFG_T *cfg);
int gx_saradc_get_once_data_it(GX_HAL_SARADC_ONCE_CFG_T *cfg);
void gx_saradc_stop(void);
int gx_saradc_reset(void);
void gx_saradc_lowpower(unsigned char en);
unsigned int gx_saradc_get_polled_cycle(void);
int gx_saradc_get_poll_data(GX_HAL_SARADC_SEQU_CFG_T *cfg, unsigned short *data);
unsigned int gx_saradc_set_channel_threshold(GX_HAL_SARADC_THRESHOLD_CFG_T *thr_cfg);
int gx_saradc_get_poll_data_dma_async(GX_HAL_SARADC_SEQU_CFG_T *sequ_cfg, unsigned short *data,
                                            void (*done_cb)(void *));
void gx_saradc_temperature_en(GX_HAL_SARADC_TEMP_SENSOR_CFG_T *cfg);
void gx_saradc_vbat_measure_en(uint32_t vbat_sel);


#endif /* __GX_SARADC_H__ */
芯片管脚 Channel Select
P1_0 0
P1_1 1
P1_2 2
P1_3 3
P1_4 4
P1_5 5
P1_6 6
P1_7 7
内部电池电压检测 8
内部温度检测 9
内部参考电压检测,VREF 800mV 10

2.2 电量检测*

测量内部电池电压,芯片自带该传感器。

只能单端检测。

static int _saradc_bat_measure_once(void)
{
    GX_HAL_SARADC_ONCE_CFG_T once_cfg;
    uint32_t val = 0;
    memset(&once_cfg, 0, sizeof(GX_HAL_SARADC_ONCE_CFG_T));
    once_cfg.chnl_cfg.diff_en = 0;
    once_cfg.chnl_cfg.p_ch_sel = 8;
    once_cfg.setup_time = 40;
    once_cfg.samp_hlevel_time = 2;
    once_cfg.conversion_time = 1;
    gx_saradc_vbat_measure_en(1); // 1:vat5 0:vat3

    val = gx_saradc_get_once_data(&once_cfg);
    // vat3 : 2*1.8*adcval/4096
    printf("val=%d vbat= %.2f\n", val, 4*1.8*val/4096);
    return 0;
}

2.3 温度检测*

测量内部芯片温度,芯片自带该传感器。

只能单端检测。

static int _saradc_temperature_measure_once(void)
{
    GX_HAL_SARADC_ONCE_CFG_T once_cfg;
    uint32_t val = 0;
    memset(&once_cfg, 0, sizeof(GX_HAL_SARADC_ONCE_CFG_T));
    once_cfg.chnl_cfg.diff_en = 0;
    once_cfg.chnl_cfg.p_ch_sel = 9;
    once_cfg.setup_time = 40;
    once_cfg.samp_hlevel_time = 2;
    once_cfg.conversion_time = 1;
    gx_saradc_temperature_en(0); // 0:VBE, 1:VPTAT

    val = gx_saradc_get_once_data(&once_cfg);
    printf("val = %d\n", val);
    return 0;
}

温度计算公式为: 温度(VBE)=398−采样值×0.239 温度(VPTAT)=采样值×0.198−308

2.4 使用异步DMA方式同时采样电压和温度*

可以使用异步DMA的方式,并同时对多个通道采样多次。

static int _saradc_bat_temperature_poll(void)
{
    memset(&_sequ_cfg, 0, sizeof(GX_HAL_SARADC_SEQU_CFG_T));
    memset(_saradc_data_buf, 0xffffffff, sizeof(_saradc_data_buf));

    _sequ_cfg.poll_cycle = 120;
    _sequ_cfg.setup_time[0] = 40;
    _sequ_cfg.setup_time[1] = 40;
    _sequ_cfg.samp_hlevel_time = 2;
    _sequ_cfg.conversion_time = 1;
    _sequ_cfg.complemented_time = 0;
    _sequ_cfg.sequ[0].channel_valid = 1;
    _sequ_cfg.sequ[0].p_ch_sel = 8;
    _sequ_cfg.sequ[0].n_ch_sel = 0;
    _sequ_cfg.sequ[0].diff_en = 0;

    _sequ_cfg.sequ[1].channel_valid = 1;
    _sequ_cfg.sequ[1].p_ch_sel = 9;
    _sequ_cfg.sequ[1].n_ch_sel = 0;
    _sequ_cfg.sequ[1].diff_en = 0;


    gx_saradc_get_poll_data_dma_async(&_sequ_cfg, _saradc_data_buf, saradc_poll_done_cb);
    chip_os_sem_take(&_sradc_poll_sem, CHIP_OS_TIME_FOREVER);

    for(int i = 0; i<120; i+=2) {
        printf("seq =%x val=%d vbat =%.2f\n",_saradc_data_buf[i] >>12,  _saradc_data_buf[i] & 0xfff, 4*1.8*( _saradc_data_buf[i] & 0xfff)/4096); //vat5
        // vat3 : 2*1.8*adcval/4096
    }
    for(int i = 1; i<120; i+=2) {
        printf("seq =%x val=%d ",_saradc_data_buf[i] >>12,  _saradc_data_buf[i] & 0xfff);
        float temperature;
        if(_teme_cfg.vtemp_sel == 0) {
            temperature = 398 - 0.239f* (_saradc_data_buf[i] & 0xfff);
        } else {
            temperature = 0.198f* ((_saradc_data_buf[i] & 0xfff) - 308);
        }
        printf("temperature=%.2f\n", temperature);
    }

    return 0;
}

2.5 采样率设置*

进行最大2^32轮次采样。通过配置轮询间隔参数,可改变采样率。

static GX_HAL_SARADC_SEQU_CFG_T _sequ_cfg = {0};
sequ_cfg.poll_cycle = 100; // 采样100次
sequ_cfg.setup_time[0] = 40// 每次采样的间隔时间,单位毫秒

2.6 校准*

通过测量标准电压获得偏差数据,开启校准后,获得采样值将是校准后的值。

GX_HAL_SARADC_SELF_CAL_CFG_T cal_cfg;

memset(&cal_cfg, 0, sizeof(GX_HAL_SARADC_SELF_CAL_CFG_T));
cal_cfg.gain = 2041;
cal_cfg.change_offset_en = 1;
cal_cfg.change_offset = 10;
if(gx_hal_saradc_self_cal(&saradc_dev_private, cal_cfg);)
    printf("gx_saradc_self_cal error\r\n");
else
    printf("self_cal done.\r\n");