RTOS_ADCLP使用参考
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 08/23/2024 |
1. 概述¶
逐次逼近型模数转换器(Successive Approximation ADC)采用的是一种反馈比较型电路结构。实现方式简要概述为:取一个数字量加到DAC上,可得到一个对应的输出模拟电压,将这个模拟电压和输入的模拟电压信号相比较,如果两者不相等,则调整所取的数字量,直到两个模拟电压相等为止,最后所取的这个数字量就是所求的转换结果。
2. 关键字说明¶
-
ADCLP
Analog-to-digital converter Low Precision,低精度(10bit)模数转换器
-
ADCMP
Analog-to-digital converter Medium Precision,中精度(12bit)模数转换器
-
upper/lower bound
ADCLP可设置外部输入电压数字量的上下限,超出范围则触发中断
-
基准电压
用于模数转换计算时使用的参考电压,也是最大量程
-
sysdesc
RTOS用于描述外设硬件属性的文件,外设节点中包含的属性值可用于外设的配置,类似Linux的设备树文件
3. 功能描述¶
-
SAR ADCLP共计4个Channel可支持外部输入电压的模数转换
-
采样精度为10bit,因此获取到的寄存器数值范围在0~0x3ff之间
-
支持两个档位的基准电压(即满量程)切换,分别为3.3V和2.0V
-
支持外部输入电压的阈值设定
-
采样时间为8667ns
4. 硬件连接介绍¶
如下图,可将外部电压接入引脚PAD_SAR_GPIO0~PAD_SAR_GPIO3

5. 计算说明¶
SAR ADCLP的主要功能是将模拟信号转换为相应的数字信号,即可以将输入电压转换为数字量存储于寄存器中,通过公式计算出输入电压,
计算公式:电压 = ( 寄存器数值 / 满量程 )* 基准电压
即如果读到的数值是0x1D2,可得电压为0x1D2/0x3FF *3.3=1.50v左右
6. RTOS用法介绍¶
6.1. DRIVER PATH¶
sc/driver/sysdriver/adclp/os/adclp_os.h sc/driver/sysdriver/adclp/drv/pub/drv_adclp.h sc/driver/sysdriver/adclp/drv/src/drv_adclp.c sc/driver/sysdriver/adclp/drv/src/drv_adclp_test.c sc/driver/sysdriver/adclp/hal/ifado/src/hal_adclp.c sc/driver/sysdriver/adclp/hal/ifado/inc/hal_adclp.h sc/driver/sysdriver/adclp/hal/ifado/inc/hal_adclp_cfg.h
6.2. CONFIG配置¶
#make menuconfig
BSP Driver Options --->
<*> Support SARADC driver
6.3. SYSDESC配置¶
ifado.sysi文件位于sc/driver/sysdriver/sysdesc/hal/ifado/pub
<adclp0>
[reg_u32] 0x1F002800;
[interrupts_u32] INT_IRQ_KEYPAD;
[camclk_u16] CAMCLK_sar;
[interrupts_en_u8] 0;
[ref_vol_u32] 3300;
[upper_bound_u16] 0x3FF;
[lower_bound_u16] 0;
[status_u8] 1;
| 属性 | 描述 | 设定值 | 备注 |
|---|---|---|---|
| reg_u32 | 设定adclp bank地址 | 0x1F002800 | 禁止修改 |
| interrupts_u32 | 设定中断号 | INT_IRQ_KEYPAD | 禁止修改 |
| camclk_u16 | 设定时钟源 | CAMCLK_sar | 禁止修改 |
| interrupts_en_u8 | 使能中断 | 1:enable, 2:disable | 可根据需要修改 |
| ref_vol_u32 | 设定基准电压挡位 | 以mv为单位,支持3300mv和2000mv | 可根据需要修改 |
| upper_bound_u16 | 设定阈值上限电压 | 0~0x3FF,使能中断有效 | 可根据需要修改 |
| lower_bound_u16 | 设定阈值下限电压 | 0~0x3FF,使能中断有效 | 可根据需要修改 |
| status_u8 | 是否使能驱动 | 1:enable, 2:disable | 可根据需要修改 |
6.4. PADMUX设定¶
SAR-ADCLP无需进行padmux的配置,PAD_SAR_GPIO0~PAD_SAR_GPIO3默认配置为ADC采样功能
6.5. API说明¶
头文件位于sc/driver/sysdriver/adclp/drv/pub/drv_adclp.h
typedef int (*adclp_cb_t)(void *);
struct adclp_cb
{
adclp_cb_t cb_t; //采样结果超出阈值后的处理函数
u32 channel;
struct CamOsListHead_t cb_node;
};
int drv_adclp_set_bound(u8 channel, u16 upper_bound, u16 lower_bound);
int drv_adclp_get_data(u8 channel, u16 *data);
int drv_adclp_register_callback(struct adclp_cb *para);
int drv_adclp_unregister_callback(struct adclp_cb *para);
...
drv_adclp_get_data
-
目的
获取指定通道的外部输入电压数字量
-
语法
int drv_adclp_get_data(u8 channel, u16 *data)
-
参数
参数名称 描述 channel 采样通道 data 电压数字量 -
返回值
返回值 描述 0 成功 -3 通道不支持
drv_adclp_set_bound
-
目的
设定指定通道的阈值
-
语法
int drv_adclp_set_bound(u8 channel, u16 upper_bound, u16 lower_bound)
-
参数
参数名称 描述 channel 采样通道 upper_bound 阈值上限 lower_bound 阈值下限 -
返回值
返回值 描述 0 成功 -3 通道不支持
drv_adclp_register_callback
-
目的
注册指定通道的回调函数,可用于超出阈值后的中断处理
-
语法
int drv_adclp_register_callback(u8 channel, const adclp_cb_t cb)
-
参数
参数名称 描述 channel 采样通道 cb 函数指针 -
返回值
返回值 描述 0 成功 -4 通道不支持
drv_adclp_unregister_callback
-
目的
释放指定通道的回调函数
-
语法
int drv_adclp_unregister_callback(u8 channel, const adclp_cb_t cb)
-
参数
参数名称 描述 channel 采样通道 cb 函数指针 -
返回值
返回值 描述 0 成功 -4 通道不支持
6.6. DEMO¶
demo源码位于sc/driver/sysdriver/adclp/drv/src/drv_adclp_test.c
#define ADC_CHANNEL_NUM 8
static u8 adclp_cb_init[ADC_CHANNEL_NUM] = {0};
/* 回调函数,当电压超出阈值范围后该函数会被调用 */
int adclp_get_data(void *para)
{
u16 data;
u8 channel;
channel = *((u8 *)para);
drv_adclp_get_data(channel, &data);
cliPrintf("adclp%hhu data[%hu] exceeding bound\n",channel, data);
return 0;
}
static int adclp_test(CLI_t *cli, char *p)
{
u8 i;
int ret;
char *cmd;
u16 data;
u8 argc;
u32 channel;
argc = CliTokenCount(cli);
if (argc < 1)
goto adclp_help_exit;
cmd = CliTokenPop(cli);
if (strcmp(cmd, "init") == 0)
{
argc = CliTokenCount(cli);
if (argc != 1)
goto adclp_help_exit;
if (CliTokenPopNum(cli, &channel, 0) != eCLI_PARSE_OK)
goto adclp_help_exit;
if (adclp_cb_init[channel])
{
cliPrintf("channel[%hhu] already init\n", (u8)channel);
return eCLI_PARSE_OK;
}
ret = drv_adclp_register_callback((u8)channel, adclp_get_data); //注册回调函数
if (ret)
return -eCLI_PARSE_INVALID_PARAMETER;
ret = drv_adclp_set_bound((u8)channel, 600, 400); //设定阈值范围
if (ret)
return -eCLI_PARSE_INVALID_PARAMETER;
adclp_cb_init[channel] = 1;
}
else if (strcmp(cmd, "single") == 0)
{
argc = CliTokenCount(cli);
if (argc != 1)
goto adclp_help_exit;
if (CliTokenPopNum(cli, &channel, 0) != eCLI_PARSE_OK)
goto adclp_help_exit;
if (!adclp_cb_init[channel])
{
cliPrintf("channel[%hhu] must init first\n", (u8)channel);
return eCLI_PARSE_OK;
}
ret = drv_adclp_get_data((u8)channel, &data); //获取单个通道的电压数字量
if (ret)
return -eCLI_PARSE_INVALID_PARAMETER;
cliPrintf("channel[%hhu] data is[%hu]\n", (u8)channel, data);
}
else if (strcmp(cmd, "scan") == 0)
{
for (i = 0; i < ADC_CHANNEL_NUM; i++)
{
ret = drv_adclp_get_data((u8)channel, &data);
if (ret)
return -eCLI_PARSE_INVALID_PARAMETER;
cliPrintf("channel[%hhu] data is[%hu]\n", (u8)channel, data);
}
}
else
{
adclp_help_exit:
cliPrintf("command format : adclp init [channel]\n");
cliPrintf("command format : adclp single [channel]\n");
cliPrintf("command format : adclp scan\n");
return -eCLI_PARSE_INVALID_PARAMETER;
}
return eCLI_PARSE_OK;
}
7. Debug方法¶
7.1. SAR ADCLP接口不存在¶
-
检查sysdesc adclp节点的
status是否为1 -
检查config是否配置,详见6.2 CONFIG配置
7.2. SAR ADCLP采样结果为0¶
引脚设为GPIO mode进行output high/low的试验,如果无法拉高拉低则有可能是硬件问题