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次,發文人進小黑屋喔~

評論