SemiDrive E3 SSDK ADC 采样频率说明

一、    概述

ADC 转换就是输入模拟的信号量转换成数字量,读取数字量必须等 ADC 转换完成后,完成一个通道的读取叫做采样周期;采样周期 = 转换时间 + 读取时间,而转换时间 = 采样时间 + 转化时间;采样时间通过寄存器进行设置,设置越长越精确,E3 ADC 固定转化时间为 13.5 个时钟周期;在某些领域对 ADC 采样频率要求极高,通常需要精确计算 ADC 的采样频率;本文通过 ADC 同步采样模式,RC 定时器触发 ADC 采样,采用中断读取的方式实时读取 ADC 转化时间,做到 ADC 采样频率的精准计算。

硬件平台:E3640 官方开发板 (SD103_E3_GATEWAY_ePOWERTRAIN_A03_019),如下图所示;
软件平台:e3_gateway_E3640_mcu_demo_E3_SSDK_PTG3.0 中 driver_demo adc_sync_poll、adc_Async_int 例程。



图1 E3640 官方开发板


二、    ADC 配置详解

1.  ADC 引脚设置

配置管脚相应 scr,使得片外管脚信号与片内 ADC 电路导通。

const scr_signal_t adc_scr[] = {

        SCR_SF_ANA_SF_CFG_APD_A_A12_CTRL_3_0,

        SCR_SF_ANA_SF_CFG_APD_A_A13_CTRL_3_0,

        SCR_SF_ANA_SF_CFG_APD_A_A14_CTRL_3_0,

        SCR_SF_ANA_SF_CFG_APD_A_A15_CTRL_3_0

    };

  

       for (i = 0; i < sizeof(adc_scr) / sizeof(adc_scr[0]); i++) {

        /* set APD_A ctrl to 1 */

        scr_set(&scr_ctrl, &adc_scr[i], 1);

      }

 

      用 ADC_CH_SEL_TAISHAN 构建单端通道号,通过设置 ADC_CH_SEL_TAISHAN 的变量设置 ADC 模块与外部引脚的对应,从 E3 DataSheet 截取 ADC 引脚对应部分如下表1,参数设置主要包含:采集通道,采集极性,引脚复用 MUX 配置,详细对应关系如下图所示。

   enum adc1_ch5n_mux {

    ADC1_CH5N_MUX_A0 = 0u,

    ADC1_CH5N_MUX_A2,

    ADC1_CH5N_MUX_A4,

    ADC1_CH5N_MUX_A6,

    ADC1_CH5N_MUX_A8,

    ADC1_CH5N_MUX_A10,

    ADC1_CH5N_MUX_A12,      // CH5_N.MUX_6

    ADC1_CH5N_MUX_A14

    };



2.  采样模拟量设置

sdrv_adc_ana_param_cfg_t 这个结构体主要设置 ADC 模拟量采集相关的参数,主要设置模拟量的采样时间、参考电压、采样模式(单端采样、差分采样)。

typedef struct sdrv_adc_ana_param_cfg {

        uint32_t    sample_time : 3;        /* ADC采样时间设置 */

        uint32_t                : 1;

        uint32_t    ref_sel     : 1;        /* ADC参考电压设置 */

        uint32_t    input_mode  : 1;        /* ADC 采样模式:单端采样,差分采样 */

        } sdrv_adc_ana_param_cfg_t;

        sdrv_adc_ana_param_cfg_t ana_param[] = {

        {SDRV_ADC_SAMPLE_TIME_10D5, SDRV_ADC_REF_VREFP1, SDRV_ADC_INPUT_SINGLE},

        {SDRV_ADC_SAMPLE_TIME_34D5, SDRV_ADC_REF_VREFP1, SDRV_ADC_INPUT_SINGLE},

        {SDRV_ADC_SAMPLE_TIME_18D5, SDRV_ADC_REF_VREFP1, SDRV_ADC_INPUT_DIFF},

        };

        /* 将ana_param依次配置到 0~2 位置上 */

        for (i = 0; i < sizeof(ana_param) / sizeof(ana_param[0]); i++) {

        sdrv_adc_ana_param_cfg(ADC_DEV_TEST, i, ana_param[i]);

         }



3.  RC寄存器设置

       ADC有两种触发方式,包含:HTC、RC0、RC1、RC2、RC3,HTC 为硬件通道触发,RC 可以通过定时器方式定时触发 ADC 采样,HTC 和 RC 将触发信息发送给 SCHEDULER,SCHEDULER 通过仲裁方式优先处理优先级高的触发信号,RC0、RC1、RC2、RC3 均可单独配置使用,也可以将 RC0 设置为主模式,将 RC1、RC2、RC3 设置成从模式组合使用; RC 对于 RC0 中的计时器 r0,它将向RC1/2/3 中的计时器 r1/2/3 生成计数器清除信号;对于 RC1/2/3 中的时间 1/2/3,它可以选择独立工作或通过计数器获取清除两者来自时间 r0 的阈值或清除信号。

sdrv_adc_rc_entry_cfg_t 主要是设置 ADC 采样通道、模拟量采集设置、ADC RC 触发模式、ADC RC 重复采样次数;

typedef struct sdrv_adc_rc_entry_cfg {

        uint32_t    channel     : 9;        /**ADC 采样通道设置 */

        uint32_t                : 3;

        uint32_t    cfg_sel     : 4;        /**选择模拟量设置通道 */

        uint32_t    repeat_mode : 1;        /**RC 硬件触发模式或软件触发模式 */

        uint32_t                : 7;

        uint32_t    repeat_cnt  : 5;        /**ADC 重复采集次数 */

        } sdrv_adc_rc_entry_cfg_t;

        在上述 sdrv_adc_ana_param_cfg_t 结构体中 sample time 参量主要设置 ADC 采样时间,而sdrv_adc_rc_cfg_t 结构体中 terminal compare 是采样触发的时间点,通过修改 Terminal 的数据更改 ADC 采样频率,RC entry 采样序列,RC 是否使能等设置。

typedef struct sdrv_adc_rc_cfg {

        uint16_t    terminal;               /**< rc timer terminal value */

        uint16_t    compare;                /**< rc timer compare value */

        uint32_t    q_cur       : 4;        /**rc_entry 当前位置*/

        uint32_t    q_start     : 4;        /**rc_entry 起始位置 */

        uint32_t    q_end       : 4;        /**rc_entry 终止位置 */

        uint32_t                : 1;

        uint32_t    tmr_mode    : 1;        /**RC模式:主模式、从模式 */

        uint32_t    trg_mode    : 1;        /**RC触发模式:软件触发、硬件触发 */

        uint32_t                : 2;

        uint32_t    trg_en      : 1;        /**< RC使能 */

         } sdrv_adc_rc_cfg_t;



4.  ADC模式设置

        配置同步模式 slot 间隔最大值为 50clock ,其中根据 ADC 最大采样时间 34.5clock,ADC固定转化时间 13.5clock,再预留 2clock 时间间隔,将 RC entry 变量依次添加至 cid_buf 数组中,ADC 同步开启后将按照 cid_buf 数组的顺序存放 ADC 转化结果。

sdrv_adc_sync_cfg_t sync_cfg = {50, 0}; //max samctrl 5 (48 + 2);

uint8_t cid_buf[8];   

        /* RC0 repeat_cnt 总数为 2,需要占用 2 个 slot。 */

        cid_buf[0] = SDRV_ADC_SYNC_CID_RC0;

        cid_buf[1] = SDRV_ADC_SYNC_CID_RC0;

         /* RC1 repeat_cnt 总数为 3,需要占用 3 个 slot。 */

        cid_buf[2] = SDRV_ADC_SYNC_CID_RC1;

        cid_buf[3] = SDRV_ADC_SYNC_CID_RC1;

        cid_buf[4] = SDRV_ADC_SYNC_CID_RC1;

        sdrv_adc_sync_cfg(ADC_DEV_TEST, sync_cfg, cid_buf, 5);



5.  中断设置

irq_initialize(VIC1_BASE, IRQ_MAX_INTR_NUM);

        sdrv_adc_clear_int_status(ADC_DEV_TEST, 0xFFFFFFFFu);

        /* 使能所有中断状态的记录 */

        sdrv_adc_int_status_en_cfg(ADC_DEV_TEST, 0xFFFFFFFFu, 1);

        /* 使能 FIFO 阈值中断的触发功能 */

       sdrv_adc_int_status_sig_en_cfg(ADC_DEV_TEST, SADC_INT_STAT_SUB_FIFO3, 1);

       /* 捕获 ADC2 中断,并设置中断回调函数 */

       irq_attach(ADC_DEV_IRQ, adc_demo_int, (void *)ADC_DEV_TEST);

        /* 中断使能 */

        irq_enable(ADC_DEV_IRQ);

       /* 中断禁止 */

      irq_detach(ADC_DEV_IRQ);



6.  ADC 频率计算

        计算 ADC 采样频率需要精准的系统计数,需要初始化 ARM 性能监视器周期计数器,用于得到系统计数,通过 pmu_get_cycle_cntr() 得到系统计数周期,通过 sdrv_ckgen_bus_get_rate() 读取系统时钟频率, ADC 频率 = CNT(sample) * F(系统时钟) * (CYCLE_CNT(ADC采样后)- CYCLE_CNT(ADC采样前)) ;

//初始化 ARM 性能监视器周期计数器

sdrv_pmu_counter_init();    /* 用于 udelay 及获取时间*/

udelay(1);

cnt_per_us = sdrv_ckgen_bus_get_rate(CLK_NODE(g_ckgen_bus_cr5_sf),

                                          CKGEN_BUS_CLK_OUT_M) / (1000 * 1000);

//读取 ADC 转化之前系统计数值

pmu_cnt_stamp[0] = pmu_get_cycle_cntr();

/* 开启 ADC 转化模式 */

//在 ADC 中断回调函数中读取最后一次 ADC 转化的系统计数值

static int adc_demo_int(uint32_t irq, void *arg)

{

        uint32_t temp;

        if (sdrv_adc_read_int_status(arg) & SADC_INT_STAT_SUB_FIFO3) {

        while (!(sdrv_adc_fifo_status(arg) & SADC_SUB_FIFO_EMPTY)) {

            temp = sdrv_adc_read_fifo(ADC_DEV_TEST);  //读取 ADC 数值

            adc_data_cnt++;

            if (adc_data_cnt == ADC_DATA_CNT_FOR_SAMPLE_RATE)

            {

                pmu_cnt_stamp[1] = pmu_get_cycle_cntr();  //获取循环计数器的值

                adc_data_sample_Finish_flag = 1;

            }

         }

        sdrv_adc_clear_int_status(arg, SADC_INT_STAT_SUB_FIFO3);

         }

        return 0;

        }

//ADC采样频率计算公式

printf("Sample rate %f Msps\n", ADC_DATA_CNT_FOR_SAMPLE_RATE * (float)cnt_per_us /

(pmu_cnt_stamp[1] - pmu_cnt_stamp[0]));

 

7.  结果验证

结果验证如下图:



                                             图2 ADC 频率输出结果

 
三、    参考文档

《AppNote_E3_Boot_and_OTA_Rev01.05》

《AppNote_E3_烧录流程_Rev2.0》

《E3110_MCU_TRM_Rev00.13》

《E3110_MCU_Datasheet_Rev00.17》


欢迎在博文下方留言评论,我们会及时回复您的问题如有更多需求,欢迎联系大联大世平集团 ATU 部门:atu.sh@wpi-group.com
作者:Linna Wang /王丽娜

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论