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");