RISCV_ADCMP使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 09/06/2024
    1.1
  • 完善功能说明和FAQ描述
  • 04/10/2025
    1.2
  • 增加直接读取ADC数据及序列采样后的线性映射接口
  • 05/15/2025

    1. 概述

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

    2. 关键字说明

    • ADCLP

      Analog-to-digital converter Low Precision,低精度(10bit)模数转换器

    • ADCMP

      Analog-to-digital converter Medium Precision,中精度(12bit)模数转换器

    • regular/inject

      不同的adc通道可以选择按不同的采样顺序加入regular序列或者inject序列,inject序列采样优先级高于regular序列

    • 基准电压

      用于模数转换计算时使用的参考电压,也是最大量程,若基准电压设定为1.8v,当外部输入电压>=1.8v时,数字量达到最大值4095

    3. 功能描述

    SAR ADCMP采样精度为12bit,硬件设计为2组,下文使用group0和group1区分,其中group0属于pm domain,group1属于nonpm domain

    3.1. group0功能描述

    • 支持22个adc通道采样,可同时使用regular序列及inject序列

    • regular序列最多配置23个adc通道(group0共计22个通道,富余的1个通道可以选择不配置,也可以选择配置为重复的通道),inject序列最多配置12个adc通道(采样优先级大于regular序列,但非dma模式下不建议与regular序列的通道重合)

    • regular序列支持15种采样触发方式,inject序列支持14种采样触发方式

    • 采样频率 = 时钟源 / 16,可选时钟源为24M和12M(采样频率的倒数为硬件上采集一个数据点的时间)

    • 支持1.5V、1.8V共计2个档位基准电压

    3.2. group1功能描述

    • 支持2个adc通道采样,且不可同时使用regular序列及inject序列,只能二选一

    • regular序列最多配置23个adc通道(group1共计2个通道,富余的21个通道可以选择不配置,也可以选择配置为重复的通道),inject序列最多配置12个adc通道(富余的10个通道可以选择不配置,也可以选择配置为重复的通道,但不支持与regular序列同时使用)

    • regular序列支持3种采样触发方式,inject序列支持2种采样触发方式

    • 采样频率 = 时钟源 / N,可选时钟源为80M、24M、12M、6M;当采样模式为conversion时, N=15;当采样模式为sequence时, N=16(采样频率的倒数为硬件上采集一个数据点的时间)

    • 支持1.8V的基准电压

    3.3. 触发方式说明

    adcmp支持的触发方式汇总

    NO. 触发方式 group0-regular group0-inject group1-regular group1-inject
    0 pwm12_out_p
    ×
    ×
    1 pwm12_out_n
    ×
    ×
    2 pwm13_out_p
    ×
    ×
    3 pwm13_out_n
    ×
    ×
    4 pwm14_out_p
    ×
    ×
    5 pwm14_out_n
    ×
    ×
    6 pwm15_out_p
    ×
    ×
    7 pwm15_out_n
    ×
    ×
    8 pwm16_out_p
    ×
    ×
    9 pwm16_out_n
    ×
    ×
    10 pwm17_out_p
    ×
    ×
    11 pwm17_out_n
    ×
    ×
    12 sw trigger
    13 external trigger
    14 freerun
    ×
    ×

    pwm_out_p:基于dead time设定后生成的正向PWM波,regular序列的采样时机是pwm_out_p波形的上升沿,inject序列的采样时机是pwm周期的起点,如图所示:

    pwm_out_n:基于dead time设定后生成的反向PWM波,regular序列的采样时机是pwm_out_n波形的上升沿,inject序列的采样时机是pwm周期的起点,如图所示:

    sw trigger:通知指令下达至寄存器,一次指令trigger后硬件执行一次采样

    external trigger:指定PIN脚,拉低拉高后触发上升沿脉冲后硬件执行一次采样

    freerun:不间断采样,采样方法如果是conversion,那么支持采样多个数据并输出平均值,同时可设定采样间隔

    3.4. 采样方法说明

    adcmp采样可选择conversion和sequence两种不同的方法

    conversion:每次触发源会触发硬件采样一个通道

    • conversion + pwm_out_p触发源:每个pwm周期的上升沿触发一次采样并采集一个通道的数据
    • conversion + sw trigger触发源:每执行一次sw trigger,触发一次采样并采集一个通道的数据
    • conversion + external trigger触发源:每执行一次external trigger,触发一次采样并采集一个通道的数据
    • conversion + freerun触发源:触发一次后进行不间断采样,支持平均采样和设定每个通道的硬件采样间隔

    sequence:每次触发源会触发硬件采样一整个序列的所有通道

    • sequence + pwm_out_p触发源:每个pwm周期的上升沿触发一次采样并采集一整个序列所有通道的数据
    • sequence + sw trigger触发源:每执行一次sw trigger,触发一次采样并采集一整个序列所有通道的数据
    • sequence + external trigger触发源:每执行一次external trigger,触发一次采样并采集一整个序列所有通道的数据
    • sequence + freerun触发源:触发一次后进行不间断采样,不支持平均采样,也不支持设定每个通道的硬件采样间隔

    3.5. 计算说明

    SAR ADCMP的主要功能是将模拟信号转换为相应的数字信号,即可以将输入电压转换为数字量存储于寄存器中,通过公式计算出输入电压,

    计算公式:电压 = ( 寄存器数值 / 采样精度12bit )* 基准电压

    即如果读到的数值是0x4B0,可得电压为0x4B0/0xFFF *1.8=0.53v左右

    4. 硬件连接介绍

    SAR ADCMP不同group下的不同通道与PAD的对应关系:

    Group0 Channel Index Pad Name
    0 PAD_SAR_ADC0_00
    1 PAD_SAR_ADC0_01
    2 PAD_SAR_ADC0_02
    3 PAD_SAR_ADC0_03
    4 PAD_SAR_ADC0_04
    5 PAD_SAR_ADC0_05
    6 PAD_SAR_ADC0_06
    7 PAD_SAR_ADC0_07
    8 PAD_SAR_ADC0_08
    9 PAD_SAR_ADC0_09
    10 PAD_SAR_ADC0_10
    11 PAD_SAR_ADC0_11
    12 PAD_SAR_ADC0_12
    13 PAD_SAR_ADC0_13
    14 PAD_SAR_ADC0_14
    15 PAD_SAR_ADC0_11
    16 PAD_PM_GPIO0
    17 PAD_PM_GPIO1
    18 PAD_PM_GPIO3
    19 PAD_PM_GPIO6
    20 PAD_PM_ADC00_IN
    21 PAD_PM_GPIO7
    Group1 Channel Index Pad Name
    0 PAD_PWM_OUT00
    1 PAD_PWM_OUT01

    以PAD_SAR_ADC0_00为例,硬件连接时,查看原理图定位引脚位置,将外部电压接入引脚PAD_SAR_ADC0_00,如下图所示:

    5. RISCV用法介绍

    5.1. DRIVER PATH

    sc/driver/sysdriver/saradc/os/adcmp_os.h
    sc/driver/sysdriver/saradc/drv/pub/drv_adcmp.h
    sc/driver/sysdriver/saradc/drv/src/drv_adcmp.c
    sc/driver/sysdriver/saradc/drv/src/drv_adcmp_test.c
    sc/driver/sysdriver/saradc/hal/chipname/src/hal_adcmp.c
    sc/driver/sysdriver/saradc/hal/chipname/inc/hal_adcmp.h
    sc/driver/sysdriver/saradc/hal/chipname/inc/hal_adcmp_cfg.h
    

    5.2. CONFIG配置

    config文件位于mak/options_chipname_riscv_isw.mak,使能CONFIG_SARADC_SUPPORT

    # Feature_Name = [DRV] SARADC driver support
    # Description = SARADC driver support
    # Option_Selection = TRUE, FALSE
    CONFIG_SARADC_SUPPORT = TRUE
    

    5.3. SYSDESC配置

    chipname_xxx.sys文件是用于描述外设硬件属性的文件,外设节点中包含的属性值可用于外设的配置,类似Linux的设备树,该文件位于sc/driver/sysdriver/sysdesc/hal/chipname/pub

    <adcmp0>
        [reg_u32] 0x200AC00, 0x200AE00, 0x2003C00, 0x2204600, 0x2203E00;
        [interrupts_u32] INT_PM_FIQ_ADCMP;
        [camclk_u16] CAMCLK_pm_pwm_adc;
        [interrupts_en_u8] 0;
        [dma_en_u8] 0;
        [dma_count_u32] 50;
        [clk_level_u8] 0;
        [ref_vol_u32] 1800;
        [regular_method_u8] 0;
        [inject_method_u8] 0;
        [regular_ch_u8] 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11;
        [inject_ch_u8] 12, 13, 14, 15, 16, 17, 18, 19, 20, 21;
        [upper_bound_u16] 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,0xFFFF, 0xFFFF;
        [lower_bound_u16] 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
        [status_u8] 0;
    
    <adcmp1>
        [reg_u32] 0x2203600, 0x2203A00, 0x2200E00, 0x2204600, 0x2203E00;
        [interrupts_u32] INT_FIQ_ADCMP;
        [camclk_u16] CAMCLK_pwm_adc;
        [interrupts_en_u8] 0;
        [dma_en_u8] 0;
        [dma_count_u32] 50;
        [clk_level_u8] 3;
        [ref_vol_u32] 1800;
        [regular_method_u8] 0;
        [inject_method_u8] 0;
        [regular_ch_u8] 0, 1;
        [upper_bound_u16] 0xFFFF, 0xFFFF;
        [lower_bound_u16] 0, 0;
        [status_u8] 0;
    
    属性 描述 设定值 备注
    reg_u32 设定寄存器bank地址 禁止修改
    interrupts_u32 绑定中断号 INT_PM_FIQ_ADCMP & INT_FIQ_ADCMP 禁止修改
    camclk_u16 设定时钟源 CAMCLK_pm_pwm_adc & CAMCLK_pwm_adc 禁止修改
    interrupts_en_u8 使能中断 1:enable,0:disable 可根据需要修改
    dma_en_u8 使能dma 1:enable,0:disable, 使用dma需要先使能中断 可根据需要修改
    dma_count_u32 dma采样数量 必须是偶数 可根据需要修改
    ref_vol_u32 设定基准电压挡位 以mv为单位,group0可选1500、1800,group1只能设定1800 可根据需要修改
    clk_level_u8 设定时钟源 可切换时钟源变更采样时间,group0可选0->24M、1->12M,group1可选0->24M、1->12M、2->6M、3->80M 可根据需要修改
    regular_method_u8 设定regular序列的采样模式 0:conversion, 1:sequence 可根据需要修改
    inject_method_u8 设定inject序列的采样模式 0:conversion, 1:sequence 可根据需要修改
    regular_ch_u8 设定regular序列的adc采样通道 最多设定23个adc通道,按照采样顺序从左至右排列 可根据需要修改
    inject_ch_u8 设定inject序列的adc采样通道 最多设定12个adc通道,按照采样顺序从左至右排列 可根据需要修改
    upper_bound_u16 设定阈值上限电压 0~0xFFFF 可根据需要修改
    lower_bound_u16 设定阈值下限电压 0~0xFFFF 可根据需要修改
    status 是否使能驱动 1:enable,0:disable 可根据需要修改

    以DMA采样功能举例,若按照如下DTS配置:

    <adcmp0>
        ......
        [interrupts_u32] INT_PM_FIQ_ADCMP;
        [camclk_u16] CAMCLK_pm_pwm_adc;
        [interrupts_en_u8] 1; //DMA功能必须使能中断
        [dma_en_u8] 1;        //使能DMA
        [dma_count_u32] 200;  //每次触发采样,会连续采集200个ADC数据
        [clk_level_u8] 0;
        [ref_vol_u32] 1800;
        [regular_method_u8] 0;
        [inject_method_u8] 0;
        [regular_ch_u8] 0, 1, 2, 3, 4, 5;
        [inject_ch_u8] 12, 13, 14, 15;
        ......
    

    影响DMA采样结果的配置如下:

    [clk_level_u8] 0:采样频率 = 24M / 16 = 1.5M hz,因此每个ADC数据的采样间隔 = 1000000000 / 1.5M = 667ns

    [dma_count_u32] 200:每次DMA触发后采集200个ADC数据,因此每次DMA触发后硬件采样的总时间为667ns * 200 = 133400ns

    [regular_ch_u8] 0, 1, 2, 3, 4, 5; [inject_ch_u8] 12, 13, 14, 15;:采集的200个数据中包含了channel0、1、2、3、4、5、12、13、14、15的ADC数据, 由于inject序列优先级更高,因此采样结果按照channel 12 -> channel 13 -> channel 14 -> channel 15 -> channel 0 -> channel 1 -> channel 2 -> channel 3 -> channel 4 -> channel 5....顺序排列

    <adcmp1>
        ......
        [interrupts_u32] INT_FIQ_ADCMP;
        [camclk_u16] CAMCLK_pwm_adc;
        [interrupts_en_u8] 1; //DMA功能必须使能中断
        [dma_en_u8] 1;        //使能DMA
        [dma_count_u32] 400;  //每次触发采样,会连续采集400个ADC数据
        [clk_level_u8] 3;
        [ref_vol_u32] 1800;
        [regular_method_u8] 1;
        [regular_ch_u8] 0, 1;
        ......
    

    影响DMA采样结果的配置如下:

    [clk_level_u8] 3; [regular_method_u8] 1;:采样频率 = 80M / 16 = 5M hz (如果regular-method = <0>, 那么采样频率 = 80M / 15 = 5.33M hz) ,因此每个ADC数据的采样间隔 = 1000000000 / 5M = 200ns

    [dma_count_u32] 400:每次DMA触发后采集400个ADC数据,因此每次DMA触发后硬件采样的总时间为200ns * 400 = 80000ns

    [regular_ch_u8] 0, 1:采集的400个数据中包含了channel0和channle1的ADC数值,按照channel 0 -> channel 1 -> channel 0 -> channel 1 -> ....顺序排列

    5.4. PADMUX配置

    CONFIG配置:CONFIG_PADMUX_SUPPORT=TRUE

    如果chipname_xxx.sys文件配置了属性<padmux>,那么PADMUX的设定直接在此配置:

    <padmux>
        [schematic_u32_u32_u32]
                //pm adc 22ch
                PAD_SAR_ADC0_00  PINMUX_FOR_PMADC0_MODE_1 MDRV_PUSE_PWMADC0,
                PAD_SAR_ADC0_01 PINMUX_FOR_PMADC1_MODE_1 MDRV_PUSE_PWMADC1,
                PAD_SAR_ADC0_02 PINMUX_FOR_PMADC2_MODE_1 MDRV_PUSE_PWMADC2,
                PAD_SAR_ADC0_03  PINMUX_FOR_PMADC3_MODE_1 MDRV_PUSE_PWMADC3,
                PAD_SAR_ADC0_04 PINMUX_FOR_PMADC4_MODE_1 MDRV_PUSE_PWMADC4,
                PAD_SAR_ADC0_05  PINMUX_FOR_PMADC5_MODE_1 MDRV_PUSE_PWMADC5,
                PAD_SAR_ADC0_06  PINMUX_FOR_PMADC6_MODE_1 MDRV_PUSE_PWMADC6,
                PAD_SAR_ADC0_07  PINMUX_FOR_PMADC7_MODE_1 MDRV_PUSE_PWMADC7,
                PAD_SAR_ADC0_08 PINMUX_FOR_PMADC8_MODE_1 MDRV_PUSE_PWMADC8,
                PAD_SAR_ADC0_09  PINMUX_FOR_PMADC9_MODE_1 MDRV_PUSE_PWMADC9,
                PAD_SAR_ADC0_10 PINMUX_FOR_PMADC10_MODE_1 MDRV_PUSE_PWMADC10,
                PAD_SAR_ADC0_11  PINMUX_FOR_PMADC11_MODE_1 MDRV_PUSE_PWMADC11,
                PAD_SAR_ADC0_12 PINMUX_FOR_PMADC12_MODE_1 MDRV_PUSE_PWMADC12,
                PAD_SAR_ADC0_13  PINMUX_FOR_PMADC13_MODE_1 MDRV_PUSE_PWMADC13,
                PAD_SAR_ADC0_14  PINMUX_FOR_PMADC14_MODE_1 MDRV_PUSE_PWMADC14,
                PAD_PM_GPIO0   PINMUX_FOR_PMADC15_MODE_1 MDRV_PUSE_PWMADC15,
                PAD_PM_GPIO1     PINMUX_FOR_PMADC16_MODE_1 MDRV_PUSE_PWMADC16,
                PAD_PM_GPIO2     PINMUX_FOR_PMADC17_MODE_1 MDRV_PUSE_PWMADC17,
                PAD_PM_GPIO3     PINMUX_FOR_PMADC18_MODE_1 MDRV_PUSE_PWMADC18,
                PAD_PM_GPIO6      PINMUX_FOR_PMADC19_MODE_1 MDRV_PUSE_PWMADC19,
                PAD_PM_ADC00_IN PINMUX_FOR_PMADC20_MODE_1 MDRV_PUSE_PWMADC20,
                PAD_PM_GPIO7     PINMUX_FOR_PMADC21_MODE_1 MDRV_PUSE_PWMADC21,
                PAD_PM_PWM0_OUT    PINMUX_FOR_PM_ADC_INT_MODE_2 MDRV_PUSE_PMPWMADC_INT,
    
                //non pm adc 2ch
                PAD_PWM_OUT00     PINMUX_FOR_ADC0_MODE_1 MDRV_PUSE_PWMADC22,
                PAD_PWM_OUT01     PINMUX_FOR_ADC1_MODE_1 MDRV_PUSE_PWMADC23,
                PAD_GPIOA_12 PINMUX_FOR_PWM_INT_MODE_1 MDRV_PUSE_PWMADC_INT,
                PAD_GPIOA_13 PINMUX_FOR_PWM_INT_MODE_1 MDRV_PUSE_PWMOUT_INT;
        [status_u8] 1;
    

    否则通过使能PADMUX驱动,在chipname-xxx-padmux.c文件配置引脚复用功能,该文件位于sc/driver/sysdriver/padmux/hal/chipname/src,只需要在对应的schematic属性添加如下内容中设定:

    pad_info_t schematic[] =
    {
        //pm adc 22ch
        {PAD_SAR_ADC0_00  PINMUX_FOR_PMADC0_MODE_1 MDRV_PUSE_PWMADC0},
        {PAD_SAR_ADC0_01 PINMUX_FOR_PMADC1_MODE_1 MDRV_PUSE_PWMADC1},
        {PAD_SAR_ADC0_02 PINMUX_FOR_PMADC2_MODE_1 MDRV_PUSE_PWMADC2},
        {PAD_SAR_ADC0_03  PINMUX_FOR_PMADC3_MODE_1 MDRV_PUSE_PWMADC3},
        {PAD_SAR_ADC0_04 PINMUX_FOR_PMADC4_MODE_1 MDRV_PUSE_PWMADC4},
        {PAD_SAR_ADC0_05  PINMUX_FOR_PMADC5_MODE_1 MDRV_PUSE_PWMADC5},
        {PAD_SAR_ADC0_06  PINMUX_FOR_PMADC6_MODE_1 MDRV_PUSE_PWMADC6},
        {PAD_SAR_ADC0_07  PINMUX_FOR_PMADC7_MODE_1 MDRV_PUSE_PWMADC7},
        {PAD_SAR_ADC0_08 PINMUX_FOR_PMADC8_MODE_1 MDRV_PUSE_PWMADC8},
        {PAD_SAR_ADC0_09  PINMUX_FOR_PMADC9_MODE_1 MDRV_PUSE_PWMADC9},
        {PAD_SAR_ADC0_10 PINMUX_FOR_PMADC10_MODE_1 MDRV_PUSE_PWMADC10},
        {PAD_SAR_ADC0_11  PINMUX_FOR_PMADC11_MODE_1 MDRV_PUSE_PWMADC11},
        {PAD_SAR_ADC0_12 PINMUX_FOR_PMADC12_MODE_1 MDRV_PUSE_PWMADC12},
        {PAD_SAR_ADC0_13  PINMUX_FOR_PMADC13_MODE_1 MDRV_PUSE_PWMADC13},
        {PAD_SAR_ADC0_14  PINMUX_FOR_PMADC14_MODE_1 MDRV_PUSE_PWMADC14},
        {PAD_PM_GPIO0   PINMUX_FOR_PMADC15_MODE_1 MDRV_PUSE_PWMADC15},
        {PAD_PM_GPIO1     PINMUX_FOR_PMADC16_MODE_1 MDRV_PUSE_PWMADC16},
        {PAD_PM_GPIO2     PINMUX_FOR_PMADC17_MODE_1 MDRV_PUSE_PWMADC17},
        {PAD_PM_GPIO3     PINMUX_FOR_PMADC18_MODE_1 MDRV_PUSE_PWMADC18},
        {PAD_PM_GPIO6      PINMUX_FOR_PMADC19_MODE_1 MDRV_PUSE_PWMADC19},
        {PAD_PM_ADC00_IN PINMUX_FOR_PMADC20_MODE_1 MDRV_PUSE_PWMADC20},
        {PAD_PM_GPIO7     PINMUX_FOR_PMADC21_MODE_1 MDRV_PUSE_PWMADC21},
        {PAD_PM_PWM0_OUT    PINMUX_FOR_PM_ADC_INT_MODE_2 MDRV_PUSE_PMPWMADC_INT},
    
        //non pm adc 2ch
        {PAD_PWM_OUT00     PINMUX_FOR_ADC0_MODE_1 MDRV_PUSE_PWMADC22},
        {PAD_PWM_OUT01     PINMUX_FOR_ADC1_MODE_1 MDRV_PUSE_PWMADC23},
        {PAD_GPIOA_12 PINMUX_FOR_PWM_INT_MODE_1 MDRV_PUSE_PWMADC_INT},
        {PAD_GPIOA_13 PINMUX_FOR_PWM_INT_MODE_1 MDRV_PUSE_PWMOUT_INT},
    };
    

    第一列为引脚索引号,可以在sc/drivers/sysdriver/gpio/hal/chipname/pub/gpio.h中查询;

    第二列为模式定义,可以在sc/drivers/sysdriver/gpio/hal/chipname/pub/padmux.h中查询;

    第三列为引脚及搭配模式的索引名称,可以在sc/drivers/sysdriver/padmux/drv/pub/drv_puse.h中查询;

    5.5. Sample Code

    demo源码位于sc/driver/sysdriver/saradc/drv/src/drv_adcmp_test.c

    其中需要注意dma采样时的调用顺序:drv_adcmp_set_config()->drv_adcmp_register_callback()->drv_adcmp_dma_sample_trigger()->回调函数中调用drv_adcmp_dma_sample_data()

    6. API参考

    头文件位于sc/driver/sysdriver/saradc/drv/pub/drv_adcmp.h

    struct adcmp_bound
    {
        u8  channel;     //指定adc通道
        u8  bound_en;    //使能阈值监测功能
        u16 lower_bd;    //阈值下限
        u16 upper_bd;    //阈值上限
    };
    
    struct adcmp_config
    {
        u8  inje_en;     //使能inject序列采样功能
        u8  inje_mod;    //inject序列采样触发方式
        u8  regu_en;     //使能regular序列采样功能
        u8  regu_mod;    //regular序列采样触发方式
        u8  avg_cnt;     //freerun时获取平均值的采样数量
        u32 p_delay;     //inject采样时pwm out p trigger的delay时间
        u32 n_delay;     //inject采样时pwm out n trigger的delay时间
        u16 sample_time; //freerun延长的采样间隔(仅支持coversion下使用),若sample time = N,最终的采样间隔时间 =  基础采样时间 + 延长采样时间 = (1 / (时钟源 / 16)) + ( N / (时钟源 / 4))
    };
    
    typedef s32 (*adcmp_cb_t)(u8 group);
    
    int drv_adcmp_get_ref_vol(u8 group, u32 *voltage);
    int drv_adcmp_set_bound(struct adcmp_bound *adcmp_bd, u8 group);
    int drv_adcmp_set_config(struct adcmp_config *adcmp_cfg, u8 group);
    int drv_adcmp_get_config(struct adcmp_config *adcmp_cfg, u8 group);
    int int drv_adcmp_direct_read_ch(u8 group, u8 channel, u16 *value)(u8 group, u8 channel, u16 *value);
    int drv_adcmp_direct_read_seq(u8 group, u8 linear_map, u16 *value);
    int drv_adcmp_sample_channel(u8 group, u8 channel, u16 *value);
    int drv_adcmp_sample_sequence(u8 group, u16 *value);
    int drv_adcmp_sample_seq_linear_map(u8 group, u16 *value);
    int drv_adcmp_dma_sample_trigger(u8 group);
    int drv_adcmp_dma_sample_stop(u8 group);
    int drv_adcmp_dma_sample_data(u8 group, u16 *value);
    int drv_adcmp_register_callback(u8 group, adcmp_cb_t cb_t);
    int drv_adcmp_unregister_callback(u8 group, adcmp_cb_t cb_t);
    
    API名称 功能
    drv_adcmp_get_ref_vol 获取当前使用的基准电压
    drv_adcmp_set_bound 设定指定通道的阈值
    drv_adcmp_set_config 设定采样属性
    drv_adcmp_get_config 获取采样属性
    drv_adcmp_direct_read_ch 直接获取指定单个通道的外部输入电压数字量,不保证实时性
    drv_adcmp_direct_read_seq 在不使能dma时,直接获取regular序列所有通道的外部输入电压数字量,不保证实时性
    drv_adcmp_sample_channel 实时获取指定单个通道的外部输入电压数字量
    drv_adcmp_sample_sequence 在不使能dma时,实时获取sysdesc指定所有通道的外部输入电压数字量
    drv_adcmp_sample_seq_linear_map 在不使能dma时,实时获取sysdesc指定所有通道的外部输入电压数字量,并将通道和数据做线性映射
    drv_adcmp_dma_sample_trigger 触发dma模式下的采样功能
    drv_adcmp_dma_sample_stop 停止dma模式下的采样功能
    drv_adcmp_dma_sample_data 获取dma模式下的采样结果
    drv_adcmp_register_callback 注册指定group的回调函数
    drv_adcmp_unregister_callback 释放指定group的回调函数和注册时申请的内存

    6.1. drv_adcmp_set_bound

    • 目的

      设定adcmp指定通道的阈值范围

    • 语法

      int drv_adcmp_set_bound(struct adcmp_bound *adcmp_bd, u8 group)
      
    • 参数

      参数名称 描述
      adcmp_bd 用于使能及配置adcmp指定通道的阈值上下限
      group 指定adcmp group
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.2. drv_adcmp_set_config

    • 目的

      设定adcmp的采样属性

    • 语法

      int drv_adcmp_set_config(struct adcmp_config *adcmp_cfg, u8 group)
      
    • 参数

      参数名称 描述
      adcmp_cfg 配置adcmp的采样属性
      group 指定adcmp group
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.3. drv_adcmp_get_config

    • 目的

      获取adcmp的采样属性,防止更新参数时其他属性被改变

    • 语法

      drv_adcmp_get_config(struct adcmp_config *adcmp_cfg, u8 group)
      
    • 参数

      参数名称 描述
      adcmp_cfg 获取当前adcmp的采样属性
      group 指定adcmp group
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.4. drv_adcmp_sample_channel

    • 目的

      获取指定单个通道的外部输入电压数字量

    • 语法

      int drv_adcmp_sample_channel(u8 group, u8 channel, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      channel 指定通道,注意需要是sysdesc中属性regular_ch_u8inject_ch_u8的成员
      value 获取采样结果的指针
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.5. drv_adcmp_sample_sequence

    • 目的

      在不使能dma时,获取sysdesc指定所有通道的外部输入电压数字量

    • 语法

      int drv_adcmp_sample_sequence(u8 group, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      value 获取采样结果的指针, 先获取inject_ch_u8指定通道的采样值,后获取regular_ch_u8指定通道的采样值
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.6. drv_adcmp_dma_sample_trigger

    • 目的

      触发dma模式下的采样功能

    • 语法

      int drv_adcmp_dma_sample_trigger(u8 group)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.7. drv_adcmp_dma_sample_stop

    • 目的

      停止dma模式下的采样功能

    • 语法

      int drv_adcmp_dma_sample_stop(u8 group)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.8. drv_adcmp_dma_sample_data

    • 目的

      获取dma模式下的采样结果,注意每次刷新采样结果都需要先调用drv_adcmp_dma_sample_trigger

    • 语法

      int drv_adcmp_dma_sample_data(u8 group, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      value 获取dma采样结果的指针,先获取inject-ch指定通道的采样值,后获取regular-ch指定通道的采样值
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.9. drv_adcmp_register_callback

    • 目的

      注册指定group的回调函数,当dma采样完成后可在回调函数里调用drv_adcmp_dma_sample_data获取采样结果

    • 语法

      int drv_adcmp_register_callback(u8 group, adcmp_cb_t cb_t)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      cb_t 函数指针
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.10. drv_adcmp_unregister_callback

    • 目的

      释放指定group的回调函数和注册时申请的内存

    • 语法

      int drv_adcmp_unregister_callback(u8 group, adcmp_cb_t cb_t)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      cb_t 函数指针
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.11. drv_adcmp_get_ref_vol

    • 目的

      获取当前使用的基准电压

    • 语法

      int drv_adcmp_get_ref_vol(u8 group, u32 *voltage)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      voltage 基准电压,以mv为单位
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.12. drv_adcmp_direct_read_ch

    • 目的

      直接获取指定单个通道的外部输入电压数字量,与drv_adcmp_sample_channel区别在于direct read获取的结果不保证实时性,仅支持对regular序列的通道使用,且触发源不支持sw trigger和external trigger;

      硬件方面,regular序列的通道会按照既定顺序轮询采样,使用drv_adcmp_sample_channel会确保是当前周期的采样结果,drv_adcmp_direct_read_ch可能是上一个周期,当前周期,或者下一周期的采样结果(一个采样周期=regular序列通道数量*(1 / 采样频率),不包括inject序列抢占所需的采样时间)

      常用场景一般为使用DMA采集大量数据时,可在DMA采样结束前先获取某个通道的数据

    • 语法

      int drv_adcmp_direct_read_ch(u8 group, u8 channel, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      channel 指定通道,必须是sysdesc中属性regular_ch_u8的成员
      value 获取采样结果的指针
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数
    • 注意事项

      第一次使用之前或者每次调用drv_adcmp_set_config之后,都需要先调用一次drv_adcmp_sample_channel or drv_adcmp_dma_sample_trigger触发采样;

      如果使用了drv_adcmp_dma_sample_triggerdrv_adcmp_direct_read_ch只能获取DMA采样过程中的通道数据,当DMA采样结束后,drv_adcmp_direct_read_ch拿到的数据不会更新,此时再调用drv_adcmp_sample_channel即可恢复

    6.13. drv_adcmp_direct_read_seq

    • 目的

      在不使能dma时,直接获取regular序列所有通道的外部输入电压数字量,与drv_adcmp_sample_sequence区别在于direct read获取的结果不保证实时性,仅支持对regular序列的通道使用,且触发源不支持sw trigger和external trigger;

      硬件方面,regular序列的通道会按照既定顺序轮询采样,使用drv_adcmp_sample_sequence会确保是当前周期的采样结果,drv_adcmp_direct_read_seq可能是上一个周期,当前周期,或者下一周期的采样结果(一个采样周期=regular序列通道数量*(1 / 采样频率),不包括inject序列抢占所需的采样时间)

      常用场景一般为使用DMA采集大量数据时,可在DMA采样结束前先获取整个序列所有通道的数据

    • 语法

      int drv_adcmp_direct_read_seq(u8 group, u8 linear_map, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      linear_map 0:value的数据排序根据sysdesc中regular_ch_u8定义的顺序,1:value的数据按照通道index从小到大排序,比如value[0]=channel 0 adc data
      value 获取采样结果的指针, 获取regular_ch_u8中所有通道的采样值
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数
    • 注意事项

      第一次使用之前或者每次调用drv_adcmp_set_config之后,都需要先调用一次drv_adcmp_sample_sequence or drv_adcmp_dma_sample_trigger触发采样;

      如果使用了drv_adcmp_dma_sample_triggerdrv_adcmp_direct_read_seq只能获取DMA采样过程中的通道数据,当DMA采样结束后,drv_adcmp_direct_read_seq拿到的数据不会更新,此时再调用drv_adcmp_sample_sequence即可恢复

    6.14. drv_adcmp_sample_seq_linear_map

    • 目的

      在不使能dma时,实时获取sysdesc指定所有通道的外部输入电压数字量,并将通道和数据做线性映射

    • 语法

      int drv_adcmp_sample_seq_linear_map(u8 group, u16 *value)
      
    • 参数

      参数名称 描述
      group 指定adcmp group
      value 获取采样结果的指针, value的数据按照通道index从小到大排序,比如value[0] = channel 0 adc data, value[1] = channel 1 adc data
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    7. FAQ

    Q1:SAR ADCMP接口不存在

    1. 检查sysdes adcmp节点的status_u8是否为1

    2. 检查config是否配置,详见[5.2. Config配置]

    Q2:SAR ADCMP采样结果没有与外部电压同步变化

    1. 引脚设为GPIO mode进行output high/low的试验,如果无法拉高拉低则有可能是硬件问题

    2. 检查采样触发方式是否ready,比如pwm out p需要配置pwm dead time并使能,external trigger需要电平产生变化触发上升沿,尤其是inject序列的触发方式未启动,那么regular序列也无法采样

    Q3:SAR ADCMP采样结果以256的倍数变化

    当某一ADC通道对应的PIN脚输入电压大于参考电压时,前一个通道的采样会受到干扰,采样结果只能是256的倍数

    <adcmp0>
        [reg_u32] 0x200AC00, 0x200AE00, 0x2003C00, 0x2204600, 0x2203E00;
        [interrupts_u32] INT_PM_FIQ_ADCMP;
        [camclk_u16] CAMCLK_pm_pwm_adc;
        [interrupts_en_u8] 0;
        [dma_en_u8] 0;
        [dma_count_u32] 50;
        [clk_level_u8] 0;
        [ref_vol_u32] 1800;
        [regular_method_u8] 0;
        [inject_method_u8] 0;
        [regular_ch_u8] 0 1 2 8 3 9 4 5 6 7 10 11 12 13 14 15 16 17 18 19 20 21;
        [upper_bound_u16] 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,0xFFFF, 0xFFFF;
        [lower_bound_u16] 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
        [status_u8] 1;
    

    例如上述配置中,[ref_vol_u32]为1.8V,若通道8、通道9的输入电压大于1.8V,则通道2、通道3的采样结果会受到干扰,且只能是256的倍数。

    Q4:SAR ADCMP 在超声波场景下DMA采样时获取不到有效数据"

    此场景需求输出PWM波形(蓝色)后,电压(黄色)才产生变化;

    如果没有报错,仅是采样数据不符合预期,需要查看DMA采样时机与电压变化时机是否匹配;

    如果此时使用adcmp0,可以选择pwm_out的触发方式(0~11),采样起点在第一个PWM波形的上升沿,可以保证同步采完所有ADC数据;

    如果此时使用adcmp1,由于没有pwm_out的触发方式,可以选择先trigger采样,然后在控制输出PWM波形,根据采样count控制采样总时长,也可采完所有ADC数据