跳到主要内容

tkl_adc | ADC 驱动

TKL ADC 接口通过模数转换器对模拟电压进行采样以完成读取。你为一个 ADC 单元(TUYA_ADC_NUM_E)配置通道列表、分辨率和采样模式,然后读取原始计数值、将其转换为毫伏,或查询芯片温度。每个 ADC 单元通常通过位掩码暴露多个通道。

ADC 经过采样、保持、量化和编码,将连续的模拟信号转换为离散的数字采样。其关键指标包括分辨率(位宽,如 8、10、12、16 位)、精度、转换时间,以及决定可测范围的参考电压。

tkl_adc_init

OPERATE_RET tkl_adc_init(TUYA_ADC_NUM_E port_num, TUYA_ADC_BASE_CFG_T *cfg);

按给定的通道列表、分辨率和采样模式初始化一个 ADC 单元。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引(TUYA_ADC_NUM_0TUYA_ADC_NUM_6)。每个单元为一个物理 ADC,通常带多个通道。
cfgTUYA_ADC_BASE_CFG_T *ADC 配置。

配置结构体如下:

typedef struct {
TUYA_AD_DA_CH_LIST_U ch_list; // 通道列表
uint8_t ch_nums; // 要转换的通道数量
uint8_t width; // 采样分辨率(位宽)
uint32_t freq; // 采样频率
TUYA_ADC_TYPE_E type; // 采样类型
TUYA_ADC_MODE_E mode; // 采样模式
uint16_t conv_cnt; // 采样次数
uint32_t ref_vol; // 参考电压,单位 mV(不支持则忽略)
} TUYA_ADC_BASE_CFG_T;

ch_list 选择要转换的通道。你可以按位设置,也可以通过 data 整字赋值:

typedef union {
TUYA_AD_DA_CH_LIST_BIT_T bits;
uint32_t data;
} TUYA_AD_DA_CH_LIST_U;

typedef struct {
uint32_t ch_0 : 1;
uint32_t ch_1 : 1;
uint32_t ch_2 : 1;
uint32_t ch_3 : 1;
uint32_t ch_4 : 1;
uint32_t ch_5 : 1;
uint32_t ch_6 : 1;
uint32_t ch_7 : 1;
uint32_t ch_8 : 1;
uint32_t ch_9 : 1;
uint32_t ch_10 : 1;
uint32_t ch_11 : 1;
uint32_t ch_12 : 1;
uint32_t ch_13 : 1;
uint32_t ch_14 : 1;
uint32_t ch_15 : 1;
uint32_t rsv : 16;
} TUYA_AD_DA_CH_LIST_BIT_T;

ch_numsch_list 中要转换的通道数量。type 选择采样源:

取值说明
TUYA_ADC_INNER_SAMPLE_VOL采样内部电压,如供电电压
TUYA_ADC_EXTERNAL_SAMPLE_VOL采样外部电压,如引脚电压

mode 选择转换模式:

取值说明
TUYA_ADC_SINGLE单次转换 —— 每次转换一个通道
TUYA_ADC_CONTINUOUS连续转换 —— 对一个通道转换设定的次数
TUYA_ADC_SCAN扫描模式 —— 一次转换一组通道

conv_cnt 设置该模式下的采样次数。

返回值:成功返回 OPRT_OK。其他值请参考 tuya_error_code.hOS_ADAPTER_ADC 定义部分。

tkl_adc_deinit

OPERATE_RET tkl_adc_deinit(TUYA_ADC_NUM_E port_num);

反初始化一个 ADC 单元并释放其资源。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。

返回值:成功返回 OPRT_OK。其他值请参考 tuya_error_code.hOS_ADAPTER_ADC 定义部分。

tkl_adc_width_get

uint8_t tkl_adc_width_get(TUYA_ADC_NUM_E port_num);

读取 ADC 单元的分辨率(位宽)。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。

返回值:ADC 分辨率,单位为位。

tkl_adc_ref_voltage_get

uint32_t tkl_adc_ref_voltage_get(TUYA_ADC_NUM_E port_num);

读取 ADC 单元的参考电压。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。

返回值:参考电压,单位 mV。

tkl_adc_temperature_get

int32_t tkl_adc_temperature_get(void);

读取芯片温度。

返回值:温度,单位为摄氏度。

tkl_adc_read_data

OPERATE_RET tkl_adc_read_data(TUYA_ADC_NUM_E port_num, int32_t *buff, uint16_t len);

从 ADC 寄存器读取原始转换数据到缓冲区。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。
buffint32_t *输出:存放读取数据的缓冲区。
lenuint16_t缓冲区长度。

返回值:成功返回 OPRT_OK。其他值请参考 tuya_error_code.hOS_ADAPTER_ADC 定义部分。

tkl_adc_read_single_channel

OPERATE_RET tkl_adc_read_single_channel(TUYA_ADC_NUM_E port_num, uint8_t ch_id, int32_t *data);

读取单个通道的转换结果。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。
ch_iduint8_tADC 单元内的通道索引。
dataint32_t *输出:转换结果。

返回值:成功返回 OPRT_OK。其他值请参考 tuya_error_code.hOS_ADAPTER_ADC 定义部分。

tkl_adc_read_voltage

OPERATE_RET tkl_adc_read_voltage(TUYA_ADC_NUM_E port_num, int32_t *buff, uint16_t len);

读取转换数据并以计算后的电压返回。

参数类型说明
port_numTUYA_ADC_NUM_EADC 单元索引。
buffint32_t *输出:存放电压的缓冲区,单位 mV。
lenuint16_t缓冲区长度。

返回值:成功返回 OPRT_OK。其他值请参考 tuya_error_code.hOS_ADAPTER_ADC 定义部分。

示例

读取单个通道:

void tuya_adc_single_channel_test(void)
{
OPERATE_RET ret;
TUYA_ADC_BASE_CFG_T adc_cfg;
int32_t adc_value = 0;
uint8_t channel = 0;

adc_cfg.ch_list.data = 1; // 或 adc_cfg.ch_list.bits.ch_0 = 1;
adc_cfg.ch_nums = 1;
adc_cfg.type = TUYA_ADC_INNER_SAMPLE_VOL;
adc_cfg.mode = TUYA_ADC_SINGLE;
adc_cfg.width = 10;
adc_cfg.conv_cnt = 1;

ret = tkl_adc_init(TUYA_ADC_NUM_0, &adc_cfg);
if (ret != OPRT_OK) {
return;
}

ret = tkl_adc_read_single_channel(TUYA_ADC_NUM_0, channel, &adc_value);
if (ret != OPRT_OK) {
return;
}

// 使用 adc_value

tkl_adc_deinit(TUYA_ADC_NUM_0);
}

扫描模式一次读取多个通道:

#define ADC_CHANNEL_NUM 3

void tuya_adc_multi_channel_test(void)
{
OPERATE_RET ret;
TUYA_ADC_BASE_CFG_T adc_cfg;
int32_t adc_value[ADC_CHANNEL_NUM] = {0};

adc_cfg.ch_list.bits.ch_0 = 1;
adc_cfg.ch_list.bits.ch_1 = 1;
adc_cfg.ch_list.bits.ch_2 = 1;
adc_cfg.ch_nums = ADC_CHANNEL_NUM;
adc_cfg.type = TUYA_ADC_INNER_SAMPLE_VOL;
adc_cfg.mode = TUYA_ADC_SCAN;
adc_cfg.width = 10;
adc_cfg.conv_cnt = 1;

ret = tkl_adc_init(TUYA_ADC_NUM_0, &adc_cfg);
if (ret != OPRT_OK) {
return;
}

ret = tkl_adc_read_data(TUYA_ADC_NUM_0, adc_value, ADC_CHANNEL_NUM);
if (ret != OPRT_OK) {
return;
}

// 使用 adc_value[0..ADC_CHANNEL_NUM-1]

tkl_adc_deinit(TUYA_ADC_NUM_0);
}

相关文档