查看: 3942|回复: 2

[求助] adc_etc和DMA怎么关联

[复制链接]

该用户从未签到

5

主题

15

帖子

0

中级会员

Rank: 3Rank: 3

积分
221
最后登录
2021-6-26
发表于 2020-6-22 17:35:34 | 显示全部楼层 |阅读模式
hello,大家好
现在碰到一个比较棘手的问题,SDK中没有相关的实例。

使用平台:rt1021

问题:我想使用采集5路ADC的数据,并且5路采集完成后触发DMA传输数据到buffer中保存起来(连续触发)。现在我设置好了5路的ADC以及ADC_ETC,不清楚怎么与DMA进行关联,还有触发ADC_ETC进行采集(外部触发信号选什么)

望解答,谢谢


回复

使用道具 举报

该用户从未签到

712

主题

6371

帖子

0

超级版主

Rank: 8Rank: 8

积分
24866
最后登录
2025-7-18
发表于 2020-6-29 11:13:58 | 显示全部楼层
楼主你好!
目前还没有直接的代码供你参考,需要你结合RT的reference manual,自己去配置。
另外,我们有些DMA+ADC的应用笔记,kinetis的,你也可以参考:
http://community.nxp.com/message/1177594
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

7

帖子

0

新手上路

Rank: 1

积分
41
最后登录
2021-2-26
发表于 2020-7-23 11:13:53 | 显示全部楼层
#include "adc_dma.h"

/*******************************************************************************
* Variables
******************************************************************************/

/******************* DMA Definitions **********************/

edma_handle_t g_ADCEdmaHandle;
edma_transfer_config_t ADC_transferConfig;

AT_NONCACHEABLE_SECTION_INIT(uint16_t g_vusADCConvertedValue[5]) = {0x00};
void ADC_TransferCreateHandleEDMA(void);
/**********************************************************/

volatile uint32_t g_AdcInterruptCounter = 0;
const uint32_t g_Adc_12bitFullRange = 4096U;

/*******************************************************************************
* Code
******************************************************************************/
void ADC_EDMACallback(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
{
    PRINTF("****ADC_EDMACallback****\r\n");
    ADC_TransferCreateHandleEDMA();   
}
void EXAMPLE_ADC_ETC_DONE0_Handler(void)
{
    ADC_ETC_ClearInterruptStatusFlags(DEMO_ADC_ETC_BASE, kADC_ETC_Trg0TriggerSource, kADC_ETC_Done0StatusFlagMask);
#ifndef  USER_DMA_TRANSPORT_RESULT
    /* 触发链组0进入 */
    if (g_AdcInterruptCounter == 0)
    {
        g_vusADCConvertedValue[0] = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 0U); /* Get trigger0 chain0 result. */
//        g_AdcConversionValue0 = *((uint32_t*)0x400C4024);
        g_AdcInterruptCounter++;
    }
    /* 触发链组1进入 */
    else if (g_AdcInterruptCounter == 1)
    {
        g_vusADCConvertedValue[1] = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 1U); /* Get trigger0 chain1 result. */
//        g_AdcConversionValue1 = *((uint32_t*)0x400C4024);
        g_AdcInterruptCounter++;
    }
    /* 触发链组2进入 */
    else if (g_AdcInterruptCounter == 2)
    {
        g_vusADCConvertedValue[2] = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 2U); /* Get trigger0 chain2 result. */
//        g_AdcConversionValue2 = *((uint32_t*)0x400C4024);
        g_AdcInterruptCounter++;
    }
    /* 触发链组3进入 */
    else if (g_AdcInterruptCounter == 3)
    {
        g_vusADCConvertedValue[3] = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 3U); /* Get trigger0 chain3 result. */
//        g_AdcConversionValue3 = *((uint32_t*)0x400C4024);
        g_AdcInterruptCounter++;
    }
    /* 触发链组4进入 */
    else if (g_AdcInterruptCounter == 4)
    {
        g_vusADCConvertedValue[4] = ADC_ETC_GetADCConversionValue(DEMO_ADC_ETC_BASE, 0U, 4U); /* Get trigger0 chain4 result. */
//        g_AdcConversionValue4 = *((uint32_t*)0x400C4024);
        g_AdcInterruptCounter = 0;
//        ADC_TransferCreateHandleEDMA();
    }
#endif   
    __DSB();
}

void ADC_TransferCreateHandleEDMA(void)
{
    EDMA_PrepareTransfer(&ADC_transferConfig,                    // EDMA传输的句柄
                         (void *)0x400C4024,                     // 源地址
                         sizeof(g_vusADCConvertedValue[0]),      // 源地址字宽
                         g_vusADCConvertedValue,                 // 目标地址
                         sizeof(g_vusADCConvertedValue[0]),      // 目标地址字宽
                         sizeof(g_vusADCConvertedValue[0]),      // 每次搬运字宽
                         10,                                     // 搬运次数
                         kEDMA_PeripheralToMemory);              // 搬运类型(外设到内存)
    EDMA_SubmitTransfer(&g_ADCEdmaHandle, &ADC_transferConfig);
    EDMA_StartTransfer(&g_ADCEdmaHandle);   
}

/*!
* @brief Configure ADC to working with ADC_ETC.
*/
void ADC_Configuration(ADC_Type *base)
{
    adc_config_t k_adcConfig;
    adc_channel_config_t adcChannelConfigStruct;
    edma_config_t config;

    /* 初始化引脚 */
    BOARD_ADC_InitPins();
   
    /* Initialize the ADC module. */
    ADC_GetDefaultConfig(&k_adcConfig);
    ADC_Init(base, &k_adcConfig);
    ADC_EnableHardwareTrigger(base, true);

    adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL16; /* External channel selection from ADC_ETC. */
    adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;
    ADC_SetChannelConfig(base, DEMO_ADC_CHANNEL_GROUP0, &adcChannelConfigStruct);

    /* Do auto hardware calibration. */
    if (kStatus_Success == ADC_DoAutoCalibration(base))
    {
        PRINTF("ADC_DoAutoCalibration() Done.\r\n");
    }
    else
    {
        PRINTF("ADC_DoAutoCalibration() Failed.\r\n");
    }
#ifdef USER_DMA_TRANSPORT_RESULT   
    ADC_EnableDMA(DEMO_ADC_BASE, true);
   
    /* Init DMAMUX */
    DMAMUX_Init(EXAMPLE_ADC1_DMAMUX_BASEADDR);
   
    /* Set channel for ADC1 */
    DMAMUX_SetSource(EXAMPLE_ADC1_DMAMUX_BASEADDR, ADC1_CHANNEL0_DMA_CHANNEL, kDmaRequestMuxADC1);
    DMAMUX_EnableChannel(EXAMPLE_ADC1_DMAMUX_BASEADDR, ADC1_CHANNEL0_DMA_CHANNEL);
   
    /* Init the EDMA module */
    EDMA_GetDefaultConfig(&config);
    EDMA_Init(EXAMPLE_ADC1_DMA_BASEADDR, &config);
    EDMA_CreateHandle(&g_ADCEdmaHandle, EXAMPLE_ADC1_DMA_BASEADDR, ADC1_CHANNEL0_DMA_CHANNEL);
    EDMA_SetCallback(&g_ADCEdmaHandle, ADC_EDMACallback, NULL);

    ADC_TransferCreateHandleEDMA();
#endif
}

/*!
* @brief Configure XBARA to work with ADC_ETC.
*/
void XBARA_Configuration(void)
{
    /* Init xbara module. */
    XBARA_Init(DEMO_XBARA_BASE);

    /* Configure the XBARA signal connections. */
    XBARA_SetSignalsConnection(DEMO_XBARA_BASE, DEMO_XBARA_INPUT_PITCH0, DEMO_XBARA_OUTPUT_ADC_ETC);
}

/*!
* @brief Configuration PIT to trigger ADC_ETC.
*/
void PIT_Configuration(void)
{
    /* Structure of initialize PIT */
    pit_config_t pitConfig;

    /* Set PERCLK_CLK source to OSC_CLK*/
    CLOCK_SetMux(kCLOCK_PerclkMux, 1U);
    /* Set PERCLK_CLK divider to 1 */
    CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U);
   
    /* Init pit module */
    PIT_GetDefaultConfig(&pitConfig);
    PIT_Init(PIT, &pitConfig);

    /* Set timer period for channel 0 */
    PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(100000U, ADC_PIT_SOURCE_CLOCK));
}
/*
* @brief ADC_ETC初始化,在RT1011中只有ADC1,所以入口参数只能是'ADC1'.
*
*/
uint32_t ADC_ETC_init (ADC_Type *base)
{
   
    adc_etc_config_t adcEtcConfig;
    adc_etc_trigger_config_t adcEtcTriggerConfig;
    adc_etc_trigger_chain_config_t adcEtcTriggerChainConfig;
   
    /* Set PERCLK_CLK source to OSC_CLK*/
    CLOCK_SetMux(kCLOCK_PerclkMux, 1U);
    /* Set PERCLK_CLK divider to 1 */
    CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U);
   
    ADC_Configuration(base);
    XBARA_Configuration();
    PIT_Configuration();
   
    /* Initialize the ADC_ETC. */
    ADC_ETC_GetDefaultConfig(&adcEtcConfig);
    adcEtcConfig.XBARtriggerMask = 1U; /* Enable the external XBAR trigger0. */
    ADC_ETC_Init(DEMO_ADC_ETC_BASE, &adcEtcConfig);
   
    /* Set the external XBAR trigger0 configuration. */
    adcEtcTriggerConfig.enableSyncMode      = false;
    adcEtcTriggerConfig.enableSWTriggerMode = false;
    adcEtcTriggerConfig.triggerChainLength  = DEMO_ADC_ETC_CHAIN_LENGTH; /* Chain length is 5. */
    adcEtcTriggerConfig.triggerPriority     = 0U;
    adcEtcTriggerConfig.sampleIntervalDelay = 0U;
    adcEtcTriggerConfig.initialDelay        = 0U;
    ADC_ETC_SetTriggerConfig(DEMO_ADC_ETC_BASE, 0U, &adcEtcTriggerConfig);
   
    /* Set the external XBAR trigger0 chain configuration. */
    adcEtcTriggerChainConfig.enableB2BMode       = true;
   
    /* 配置触发组0、链组0 */
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP0; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_USER_CHANNEL0; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    adcEtcTriggerChainConfig.enableIrq = true; /* Enable the IRQ. */   
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 0U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain0. */
                                 
    /* 配置触发组0、链组1 */
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP0; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_USER_CHANNEL7; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    adcEtcTriggerChainConfig.enableIrq = true; /* Enable the IRQ. */   
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 1U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain1. */
   
    /* 配置触发组0、链组2 */
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP0; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_USER_CHANNEL8; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    adcEtcTriggerChainConfig.enableIrq = true; /* Enable the IRQ. */   
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 2U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain2. */
   
    /* 配置触发组0、链组3 */
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP0; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_USER_CHANNEL9; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    adcEtcTriggerChainConfig.enableIrq = true; /* Enable the IRQ. */   
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 3U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain3. */
   
    /* 配置触发组0、链组4 */
    adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U
                                                   << DEMO_ADC_CHANNEL_GROUP0; /* Select ADC_HC0 register to trigger. */
    adcEtcTriggerChainConfig.ADCChannelSelect =
        DEMO_ADC_ETC_USER_CHANNEL10; /* ADC_HC0 will be triggered to sample Corresponding channel. */
    adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
    adcEtcTriggerChainConfig.enableIrq = true; /* Enable the IRQ. */   
    ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 4U,
                                  &adcEtcTriggerChainConfig); /* Configure the trigger0 chain4. */
   
    /* Enable the NVIC. */
    EnableIRQ(ADC_ETC_IRQ0_IRQn);
   
    /* Start PIT channel0. */
    PIT_StartTimer(PIT, kPIT_Chnl_0);
   
    PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
   
    return 0;
   
}

void show_adc_result (void)
{
   PRINTF("ADC conversion value is %d\t%d\t%d\t%d\t%d\r\n",
    g_vusADCConvertedValue[0], g_vusADCConvertedValue[1], g_vusADCConvertedValue[2], g_vusADCConvertedValue[3], g_vusADCConvertedValue[4]);
   
   PRINTF("\r\nadc test end!\r\n");
}

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-19 08:18 , Processed in 0.083435 second(s), 21 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表