0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

LPC5516_SDK例程ADC_2Msps高速采集

恩智浦MCU加油站 ? 來源:恩智浦MCU加油站 ? 2023-01-06 09:34 ? 次閱讀

最近支持一個(gè)客戶,需要在LPC5516下實(shí)現(xiàn)ADC 2Msps高速采集,根據(jù)數(shù)據(jù)手冊描述:

23959160-8d56-11ed-bfe3-dac502259ad0.png

  • ADC在12-bit模式下最高可以達(dá)到2.3Msps

  • ADC在16-bit模式下最高可以達(dá)到2.0Msps.


那么實(shí)際情況是否真如數(shù)據(jù)手冊所述,能達(dá)到如此高的轉(zhuǎn)換速率呢?小編這次就編寫了測試代碼進(jìn)行了實(shí)測,結(jié)果為:


12-bit模式下ADC最快可達(dá)2.326Msps, 16-bit模式下2.083Msps, 結(jié)果還是和數(shù)據(jù)手冊很吻合的。

代碼設(shè)計(jì)

代碼基于SDK的例程:

SDK_2_12_0_LPCXpresso55S16oardslpcxpresso55s16driver_exampleslpadcdma

修改:

1. 為了實(shí)現(xiàn)最快速度ADC采集,我們需要將ADC配置為:

  • ADC輸入時(shí)鐘: ADCCLK = 48MHz

  • 無硬件平均: HWAVG=1

  • ADC采樣時(shí)長設(shè)置為最短3xCLK: STS=0

  • ADC功率最大: PWRSEL=3

除此之外,還需要將ADC設(shè)置為連續(xù)轉(zhuǎn)換模式:即將g_LpadcCommandConfigStruct.chainedNextCommandNumber指向自己,即完成當(dāng)前轉(zhuǎn)換后,自動開始下次轉(zhuǎn)換。

以上所有配置對應(yīng)SDK代碼如下:


		

/* Configure ADC. */

LPADC_GetDefaultConfig(&lpadcConfigStruct);

lpadcConfigStruct.enableAnalogPreliminary = true;

lpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage1;

lpadcConfigStruct.powerLevelMode=kLPADC_PowerLevelAlt4;

lpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE;

lpadcConfigStruct.FIFO0Watermark = 2;


		

LPADC_GetDefaultConvCommandConfig(&g_LpadcCommandConfigStruct);

g_LpadcCommandConfigStruct.channelNumber = DEMO_LPADC_USER_CHANNEL;

g_LpadcCommandConfigStruct.sampleTimeMode = kLPADC_SampleTimeADCK3;

g_LpadcCommandConfigStruct.loopCount = 1;

g_LpadcCommandConfigStruct.conversionResolutionMode = kLPADC_ConversionResolutionHigh;

//g_LpadcCommandConfigStruct.conversionResolutionMode =kLPADC_ConversionResolutionStandard;

g_LpadcCommandConfigStruct.chainedNextCommandNumber = DEMO_LPADC_USER_CMDID;

2. 配置DMA,使用DMA Ping-Pang buffer接收ADC數(shù)據(jù),即定義兩個(gè)DMA描述符,A和B:A傳輸完成后自動觸發(fā)B,B傳輸完成后自動觸發(fā)A。對應(yīng)SDK代碼為:


		

1.SDK_ALIGN(uint32_t s_dma_table[DMA_DESCRIPTOR_NUM * sizeof(dma_descriptor_t)], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE);

2.

3. const uint32_t g_XferConfig =

4. DMA_CHANNEL_XFER(true, /* Reload linkdescriptor after current exhaust, */

5. true, /* Clear trigger status.*/

6. true, /* Enable interruptA. */

7. false, /* Not enable interruptB. */

8. sizeof(uint32_t), /* Dma transfer width. */

9. kDMA_AddressInterleave0xWidth, /* Dma source address no interleave*/

10. kDMA_AddressInterleave1xWidth, /* Dma destination address nointerleave */

11. sizeof(uint32_t)*ADC_DMA_SIZE /* Dma transfer byte. */

12. );


		

static void DMA_Configuration(void)

{

dma_channel_config_t dmaChannelConfigStruct;

#if defined (DEMO_DMA_HARDWARE_TRIGGER) && DEMO_DMA_HARDWARE_TRIGGER

/* Configure INPUTMUX. */

INPUTMUX_Init(DEMO_INPUTMUX_BASE);

INPUTMUX_AttachSignal(DEMO_INPUTMUX_BASE, DEMO_DMA_ADC_CHANNEL, DEMO_DMA_ADC_CONNECTION);

#endif /* DEMO_DMA_HARDWARE_TRIGGER */

/* Configure DMA. */

DMA_Init(DEMO_DMA_BASE);

DMA_EnableChannel(DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL);

DMA_CreateHandle(&g_DmaHandleStruct, DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL);

DMA_SetCallback(&g_DmaHandleStruct, DEMO_DMA_Callback, NULL);

/* Prepare and submitthe transfer. */

DMA_PrepareChannelTransfer(&dmaChannelConfigStruct, /* DMA channel transfer configuration structure. */

(void *)DEMO_LPADC_RESFIFO_REG_ADDR, /* DMA transfer source address.*/

(void *)adc_result, /* DMA transfer destination address. */

g_XferConfig, /* Xfer configuration */

kDMA_PeripheralToMemory, /* DMAtransfer type. */

NULL, /*DMA channel trigger configurations. */

(dma_descriptor_t *)&(s_dma_table[0]) /* Address of next descriptor. */

);

DMA_SubmitChannelTransfer(&g_DmaHandleStruct, &dmaChannelConfigStruct);

/* Set two DMAdescripters to use ping-pong mode. */

DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[0]), g_XferConfig, (void *)DEMO_LPADC_RESFIFO_REG_ADDR, (void *)adc_result, (dma_descriptor_t *)&(s_dma_table[4]));

DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[4]), g_XferConfig, (void *)DEMO_LPADC_RESFIFO_REG_ADDR, (void *)adc_result, (dma_descriptor_t *)&(s_dma_table[0]));

}

3. 最后小編還使能了SysTick定時(shí)器用于記錄轉(zhuǎn)換時(shí)間,程序開始運(yùn)行后,ADC會啟動連續(xù)轉(zhuǎn)換,DMA設(shè)置為傳輸100次ADC轉(zhuǎn)換結(jié)果后觸發(fā)DMA完成中斷, DMA中斷觸發(fā)后(傳輸完成),程序會統(tǒng)計(jì)ADC轉(zhuǎn)換時(shí)間,計(jì)算ADC轉(zhuǎn)換結(jié)果的平均值和標(biāo)準(zhǔn)差,以及打印轉(zhuǎn)換結(jié)果。

代碼清單

最后為大家呈上完整代碼清單(可以直接復(fù)制到lpadc_dma.c里運(yùn)行):

/* * Copyright 2018-2021 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_debug_console.h" #include "fsl_dma.h" #include "fsl_inputmux.h" #include "fsl_lpadc.h" #include "stdio.h" #include "math.h" #include "fsl_power.h" #include "fsl_anactrl.h" /******************************************************************************* * Definitions ******************************************************************************/ #define PF(a) ((a) * (a)) #define DEMO_LPADC_BASE ADC0 #define DEMO_LPADC_USER_CHANNEL 0U #define DEMO_LPADC_USER_CMDID 1U /* CMD1 */ #define DEMO_LPADC_VREF_SOURCE kLPADC_ReferenceVoltageAlt2 #define DEMO_LPADC_DO_OFFSET_CALIBRATION true #define DEMO_LPADC_RESFIFO_REG_ADDR (uint32_t)(&(ADC0->RESFIFO[0])) #define DEMO_RESULT_FIFO_READY_FLAG kLPADC_ResultFIFO0ReadyFlag #define DEMO_DMA_BASE DMA0 #define DEMO_DMA_ADC_CHANNEL 21U #define DMA_DESCRIPTOR_NUM 2U #define ADC_DMA_SIZE (100) static void ADC_Configuration(void); static void DMA_Configuration(void); lpadc_conv_command_config_t g_LpadcCommandConfigStruct; /* Structure to configure conversion command. */ dma_handle_t g_DmaHandleStruct; /* Handler structure for using DMA. */ uint32_t adc_result[ADC_DMA_SIZE]; /* Keep the ADC conversion resulut moved from ADC data register by DMA. */ static double adc_sum; static double adc_mean, adc_std; static double adc_sum_sqrt; volatile bool g_DmaTransferDoneFlag = false; /* Flag of DMA transfer done trigger by ADC conversion. */ /* DMA descripter table used for ping-pong mode. */ SDK_ALIGN(uint32_t s_dma_table[DMA_DESCRIPTOR_NUM * sizeof(dma_descriptor_t)], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); const uint32_t g_XferConfig = DMA_CHANNEL_XFER(true, /* Reload link descriptor after current exhaust, */ true, /* Clear trigger status. */ true, /* Enable interruptA. */ false, /* Not enable interruptB. */ sizeof(uint32_t), /* Dma transfer width. */ kDMA_AddressInterleave0xWidth, /* Dma source address no interleave */ kDMA_AddressInterleave1xWidth, /* Dma destination address no interleave */ sizeof(uint32_t)*ADC_DMA_SIZE /* Dma transfer byte. */ ); const uint32_t g_LpadcFullRange = 65536U; const uint32_t g_LpadcResultShift = 0U; void DEMO_DMA_Callback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { //printf("DEMO_DMA_Callback "); if (true == transferDone) { g_DmaTransferDoneFlag = true; } } int main(void) { /* Initialize board hardware. */ /* set BOD VBAT level to 1.65V */ POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false); /* attach main clock divide to FLEXCOMM0 (debug console) */ CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); /* Set clock source for ADC0 */ CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk, 2U, true); CLOCK_AttachClk(kFRO_HF_to_ADC_CLK); /* Disable LDOGPADC power down */ POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC); ANACTRL_Init(ANACTRL); ANACTRL_EnableVref1V(ANACTRL, true); PRINTF("LPADC DMA Example "); PRINTF("ADC CLK:%d ", CLOCK_GetAdcClkFreq()); PRINTF("CORE CLK:%d ", CLOCK_GetCoreSysClkFreq()); /* Configure peripherals. */ DMA_Configuration(); ADC_Configuration(); PRINTF("ADC Full Range: %d ", g_LpadcFullRange); PRINTF("ADCResolution: %dbit ", (g_LpadcCommandConfigStruct.conversionResolutionMode == kLPADC_ConversionResolutionStandard)?(12):(16)); SysTick_Config(0xFFFFFF); int tick; PRINTF("Please press any key to trigger the conversion. "); while (1) { /* Get the input from terminal and trigger the converter by software. */ GETCHAR(); g_DmaTransferDoneFlag = false; LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1UL); /* Trigger the ADC and start the conversion. */ DMA_StartTransfer(&g_DmaHandleStruct); /* Enable the DMA every time for each transfer. */ tick = SysTick->VAL; /* Wait for the converter & transfer to be done. */ while (false == g_DmaTransferDoneFlag) {}; tick = tick - SysTick->VAL; tick = tick / (CLOCK_GetCoreSysClkFreq() / (1000*1000)); printf("%-16s%dus(%.3fMS/s) ", "TIME:", tick, (1 / (float)tick)*ADC_DMA_SIZE); int i; adc_sum = 0; adc_sum_sqrt = 0; for(i=0; i> g_LpadcResultShift); adc_sum += (float)adc_result[i]; adc_sum_sqrt += (adc_result[i]*adc_result[i]); // PRINTF("ADC[%d]:%d ", i, adc_result[i]); } // printf("SUM:%.2f ", adc_sum); // printf("SSUM:%.2f ", adc_sum_sqrt); adc_mean = adc_sum / ADC_DMA_SIZE; adc_std = (adc_sum_sqrt - PF(adc_sum)/ADC_DMA_SIZE) / (ADC_DMA_SIZE-1); adc_std = sqrt(adc_std); printf("%-16s%f ", "AVG :", adc_mean); printf("%-16s%f ", "STD :", adc_std); }}static void ADC_Configuration(void){ lpadc_config_t lpadcConfigStruct; lpadc_conv_trigger_config_t lpadcTriggerConfigStruct; /* Configure ADC. */ LPADC_GetDefaultConfig(&lpadcConfigStruct); lpadcConfigStruct.enableAnalogPreliminary = true; lpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage1; lpadcConfigStruct.powerLevelMode=kLPADC_PowerLevelAlt4; lpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE; lpadcConfigStruct.FIFO0Watermark = 2; LPADC_Init(DEMO_LPADC_BASE, &lpadcConfigStruct); LPADC_DoOffsetCalibration(DEMO_LPADC_BASE); LPADC_DoAutoCalibration(DEMO_LPADC_BASE); /* Set conversion CMD configuration. */ LPADC_GetDefaultConvCommandConfig(&g_LpadcCommandConfigStruct); g_LpadcCommandConfigStruct.channelNumber = DEMO_LPADC_USER_CHANNEL; g_LpadcCommandConfigStruct.sampleTimeMode = kLPADC_SampleTimeADCK3; g_LpadcCommandConfigStruct.loopCount = 1; g_LpadcCommandConfigStruct.conversionResolutionMode = kLPADC_ConversionResolutionHigh; // g_LpadcCommandConfigStruct.conversionResolutionMode = kLPADC_ConversionResolutionStandard; g_LpadcCommandConfigStruct.chainedNextCommandNumber = DEMO_LPADC_USER_CMDID; LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID, &g_LpadcCommandConfigStruct); /* Set trigger configuration. */ LPADC_GetDefaultConvTriggerConfig(&lpadcTriggerConfigStruct); lpadcTriggerConfigStruct.targetCommandId = DEMO_LPADC_USER_CMDID; lpadcTriggerConfigStruct.enableHardwareTrigger = true; LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &lpadcTriggerConfigStruct); /* Configurate the trigger0. */ /* DMA request enabled. */ LPADC_EnableFIFO0WatermarkDMA(DEMO_LPADC_BASE, true);}static void DMA_Configuration(void){ dma_channel_config_t dmaChannelConfigStruct;#if defined(DEMO_DMA_HARDWARE_TRIGGER) && DEMO_DMA_HARDWARE_TRIGGER /* Configure INPUTMUX. */ INPUTMUX_Init(DEMO_INPUTMUX_BASE); INPUTMUX_AttachSignal(DEMO_INPUTMUX_BASE, DEMO_DMA_ADC_CHANNEL, DEMO_DMA_ADC_CONNECTION);#endif /* DEMO_DMA_HARDWARE_TRIGGER */ /* Configure DMA. */ DMA_Init(DEMO_DMA_BASE); DMA_EnableChannel(DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL); DMA_CreateHandle(&g_DmaHandleStruct, DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL); DMA_SetCallback(&g_DmaHandleStruct, DEMO_DMA_Callback, NULL); /* Prepare and submit the transfer. */ DMA_PrepareChannelTransfer(&dmaChannelConfigStruct, /* DMA channel transfer configuration structure. */ (void *)DEMO_LPADC_RESFIFO_REG_ADDR, /* DMA transfer source address. */ (void *)adc_result, /* DMA transfer destination address. */ g_XferConfig, /* Xfer configuration */ kDMA_PeripheralToMemory, /* DMA transfer type. */ NULL, /* DMA channel trigger configurations. */ (dma_descriptor_t *)&(s_dma_table[0]) /* Address of next descriptor. */ ); DMA_SubmitChannelTransfer(&g_DmaHandleStruct, &dmaChannelConfigStruct); /* Set two DMA descripters to use ping-pong mode. */ DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[0]), g_XferConfig, (void *)DEMO_LPADC_RESFIFO_REG_ADDR, (void *)adc_result, (dma_descriptor_t *)&(s_dma_table[4])); DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[4]), g_XferConfig, (void *)DEMO_LPADC_RESFIFO_REG_ADDR, (void *)adc_result, (dma_descriptor_t *)&(s_dma_table[0]));}void SysTick_Handler(void){}

下期,將重點(diǎn)聊聊影響ADC轉(zhuǎn)換誤差的各種因素。

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • adc
    adc
    +關(guān)注

    關(guān)注

    98

    文章

    6498

    瀏覽量

    544681
  • SDK
    SDK
    +關(guān)注

    關(guān)注

    3

    文章

    1036

    瀏覽量

    45955
  • 高速采集
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    6161

原文標(biāo)題:LPC5516_SDK例程ADC_2Msps高速采集

文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    LPC 1768 ADC

    最近在做lpc 1765的ADC 參考lpc 1768 的來做 ADC 采用硬件循環(huán)采集模式 ,在中斷例處理單進(jìn)入中斷后就出不來了 網(wǎng)上看的
    發(fā)表于 04-16 12:04

    學(xué)習(xí)高速ADC必備資料(ADI)

    ADI的高速模數(shù)轉(zhuǎn)換器(高速ADC)提供市場上最佳的性能和最高的ADC采樣速度。該系列產(chǎn)品包括高中頻ADC (10
    發(fā)表于 04-12 17:24

    請問關(guān)于高速ADC時(shí)間交替采樣時(shí)鐘同步問題

    想請問大家: 我擬采用500Msps以上采樣率,JESD204B接口的ADC芯片構(gòu)建2通道以上的一個(gè)多通道高速數(shù)據(jù)采集系統(tǒng)。為使討論問題具體
    發(fā)表于 07-24 10:45

    用STM32F407如何采集200M高速ADC信號?

    各位學(xué)術(shù)大佬,小弟想問問如何用工作頻率為168M的STM32F407來檢測100MHz的高速信號。小弟的方案是:根據(jù)香農(nóng)定理,ADC的采樣頻率需要為200MHz,所以用一個(gè)200MspsAD
    發(fā)表于 12-06 22:26

    LPC5516 SRAM程序未從Flash中執(zhí)行如何解決?

    ]: *** [makefile:59: LPC5516_Project.axf] 錯誤 1make: *** [makefile:50: all] 錯誤 2 “make -r -j4 all”以退出代碼 2 終止。構(gòu)建可能不完
    發(fā)表于 04-11 06:04

    LPC2148驅(qū)動例程

    LPC2148開發(fā)板所有設(shè)備驅(qū)動例程 有需要的下來看看
    發(fā)表于 12-30 15:58 ?6次下載

    LPC1300_KEIL_PT_DEMO配套例程和工程模板

    lpc1300的例程包括gpio、uart、adc等等
    發(fā)表于 02-18 15:13 ?7次下載

    LPC1114_例程和教程

    LPC1114_例程和教程介紹,又需要的下來看看
    發(fā)表于 05-18 11:44 ?302次下載

    AD7641:18位,2 MSPS SAR ADC數(shù)據(jù)Sheet

    AD7641:18位,2 MSPS SAR ADC數(shù)據(jù)Sheet
    發(fā)表于 04-16 20:32 ?2次下載
    AD7641:18位,<b class='flag-5'>2</b> <b class='flag-5'>MSPS</b> SAR <b class='flag-5'>ADC</b>數(shù)據(jù)Sheet

    24位2Msps SAR ADC

    24位2Msps SAR ADC
    發(fā)表于 05-20 18:43 ?9次下載
    24位<b class='flag-5'>2Msps</b> SAR <b class='flag-5'>ADC</b>

    國產(chǎn)ADC高速采集芯片資料分享

    國產(chǎn)ADC高速采集芯片資料免費(fèi)下載。
    發(fā)表于 05-28 09:16 ?38次下載

    AT84AD001型ADC2GHz高速信號采集系統(tǒng)中的應(yīng)用

    AT84AD001型ADC2GHz高速信號采集系統(tǒng)中的應(yīng)用(無線電源技術(shù)商業(yè)計(jì)劃書)-該文檔為AT84AD001型ADC
    發(fā)表于 09-24 16:39 ?5次下載
    AT84AD001型<b class='flag-5'>ADC</b>在<b class='flag-5'>2</b>GHz<b class='flag-5'>高速</b>信號<b class='flag-5'>采集</b>系統(tǒng)中的應(yīng)用

    串口DMA發(fā)送+中斷接收的例程

    LPC5500的SDK中提供了非常豐富的串口例程(如下圖所示)。
    的頭像 發(fā)表于 07-21 09:14 ?2749次閱讀

    LPC5500_SDK例程:串口DMA發(fā)送+中斷接收

    LPC5500_SDK例程:串口DMA發(fā)送+中斷接收
    的頭像 發(fā)表于 10-30 16:59 ?1119次閱讀
    <b class='flag-5'>LPC5500_SDK</b><b class='flag-5'>例程</b>:串口DMA發(fā)送+中斷接收

    替換AD9208,國產(chǎn)ADC可用于高速采集電路

    替換AD9208,國產(chǎn)ADC可用于高速采集電路
    的頭像 發(fā)表于 07-08 09:57 ?1080次閱讀
    替換AD9208,國產(chǎn)<b class='flag-5'>ADC</b>可用于<b class='flag-5'>高速</b><b class='flag-5'>采集</b>電路