ADC hardware average with Timer trigger not counting all samples

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

ADC hardware average with Timer trigger not counting all samples

2,109 次查看
vinay_devarakon
Contributor II

Hello Community,

I have been working with Kinetis MK24FN1M0 microcontroller and performing ADC measurements. According to our requirement, the ADC has to perform measurements every 10µs. For this I have used the FTM timer 2 and configured it to trigger the ADC every 10µs. Then, we wanted to take an average every 32 measurements and generate an ADC Interrupt. To my surprise, the ADC with hardware averaging count of 32 is generating an interrupt every 175 µs . When I trigger and perform ADC measurements every 10µs and 32 ADC measurements should sum up to 320µs. But this is not working. Initially, I thought it was timer which was not working correctly, I disabled the hardware averaging and observed the interval betwen every ADC Interrupt. It is exactly 10µs. But as soon as I enable the Hardware Averaging, and check the interval between the Interrupts it is just 175µs.

I then changed the timer trigger interval to 1 ms, but the hardware averaging ADC interrupt shows up again after 175µs. I don't understand this behaviour.

I have even checked the ADC registers, if I have configured anything wrong but everything seems right with the configuration. I am very disappointed with the result and I would really appreciate if I could get the Hardware averaging working correctly.

Any suggestions in finding a solution to this problem would be of great help.

Thankyou!

标签 (1)
9 回复数

1,773 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Vinay Kumar,

    Thank you for your interest in NXP kinetis product, I would like to provide service for you.

    Actually, the ADC conversion time can be calculated, it is totally determined by your ADC module configuration.

   Please check the K24 reference manual, chapter: 35.4.4.5 Sample time and total conversion time

pastedImage_1.png

Please calculate the conversion time with your ADC configuration, then you can determine what the FTM trigger time you need to use.

You also can use the continuous mode to test the conversion time at first.

Please calculate it at first.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

1,773 次查看
vinay_devarakon
Contributor II

Hello Kerry Zhou,

Thanks for the timely reply. I have already calculated the ADC conversion time and it is 6,1041 µs. My Timer triggers every 10µs. I could reduce my ADC conversion time to 5,101 µs by removing the Long sample time of 10. At the Moment, both my ADCs ( I assume I have two ADCs as stated in K24 reference Manual ) run at 6 MHz with 16-bit Resolution and my System Clock Frequency is 48 MHz. All this works good. But, as soon as I enable the Hardware averaging with 32 conversions, I expect to get an ADC Interrupt or Setting of COCO flag after 32 * 10µs = 320 µs.

But when I measure the Interrupt Interval, I measure every time around 165-170µs.

After trying so many Things, I wanted to try out the Continuous mode. After I enabled the continuous mode with Software trigger, only one of my ADC seems to be running even though I have written into SC1A Registers of both ADC0 and ADC1. Only, the first seems to be running.

My Basic Question is do I really have physically two ADCs in K24 or is it only one ADC which uses a MUX ? If it uses a MUX, then in the Reference Manual at Section 3.7.1.1 it is stated that this device has two ADCs. Even in the Software I have seen two Instances of ADCs. If that is so what is right way of configuring the two ADCs so that both run simultaneuously with precision. I don't mind getting the Interrupt around 1-2µs delayed ( because of Interrupt prioirty or so) , but I want the measurements on both ADCs to run exactly at the same time instant. Is this really possible on this device ??

Looking Forward to your Suggestions!

Thankyou!

0 项奖励
回复

1,773 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Vinay,

    Thanks a lot for your detail information.

    MK24 really have two ADC modules.

    From your description, your problem is in the hardware averaging, no hardware averaging seems no problem.

   So, do you mind you shar your problem project with me, I would like to help you to check it. You can delete all the other important code, just give me the project which can reproduce the problem.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

1,773 次查看
vinay_devarakon
Contributor II

Hello Kerry,

I have recalculated my ADC conversion time for 32 Hardware averaging counts and it is Correct what I measure. It is 165.93 µs.

That works good. The Continuous mode seems to also work on both the ADCs parallely.

Thankyou!

0 项奖励
回复

1,773 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Vinay,

    Thanks a lot for your updated information.

   So, your previous problem still caused by the wrong calculated ADC conversion time, is it right?

   Any way, if you still have question about it, please kindly let me know.


Have a great day,
kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

1,773 次查看
vinay_devarakon
Contributor II

Hi Kerry,

Thanks to you too for your Support. Actually, the Problem is not completely cleared. My Goal was to sample both the ADCs with a single Hardware Timer as Trigger Input and compute 32 consecutive such measurements ( which with the corrected ADC conversion time of 5.77µs for one measurement should be at 32 * 5.77µs = 184,64µs ) and take an average for the 32 measurements. So, instead of me doing all the measurements and taking an average, I found the Hardware Averaging Feature quite apt for my requirement. But, as I stated before I always get my Interrupt only after170µs which makes me understand that Hardware Trigger and Hardware averaging are not to be used together?? 

This makes me understand that the Hardware averaging Feature is meant only for Continuous conversions and it does not depend on the Timer Trigger Input.

I am really interested to know what exactly is actually meant with Hardware Averaging Count ?? and whether it is Independent of Hardware Trigger?

Thankyou once again!

0 项奖励
回复

1,773 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Vinay Kumar,

    Thanks  for your updated information.

    Hardware conversion is not only in continuous mode, please check these information:

pastedImage_1.png

pastedImage_2.png

So, actually, you totally can use the hardware trigger, if you trigger one time, and you enable the hardware average function, then one set of conversion will be converted.

But please note, you must make sure your hardware trigger intervals larger than the hardware average conversion time.

Wish it helps you!

If you still have question about it, please kindly let me know.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,773 次查看
lukas_osmancik
NXP Employee
NXP Employee

Use of average function may lead user into assumption that it works with HW triggers differently than in continuous mode. It works as Kerry explained and this block diagram describes that.

pastedImage_2.png

1,773 次查看
vinay_devarakon
Contributor II

Hi Kerry,

Here is my Code.

#define WITH_DMA (0) /*with DMA */

#if WITH_DMA
#define DMA_INTERRUPT (1)           /*with DMA Interrupt*/
#define AUTONOM (0)                       /*automatic triggering of ADC conversions*/
#define CYCLIC_CONTINUOUS (0) /*continuous triggering of ADC conversions*/
#endif

#define HZ_TO_MHZ(x) (x / 1000000)

#define TEST_TOGGLE_PIN (0)
#define WITH_FTM_INTERRUPT (0)
#define HARDWARE_TRIGGER (1)
#define AVERAGING_HARDWARE (0)

/*------------------------------------------------------------------------*/ /**
* \brief        Initializes the two instances of the ADC and configures the DMA
*               such that the ADC conversions are started by a DMA channel and
*               the other DMA channel reads the result from the ADC Data register
*               and saves them in a RAM buffer.
* \param[in]    none
* \return       none
*/  //---------------------------------------------------------------------------
void CADC_MK24FN1M0::init()
{
    adc16_chn_config_t adcChnConfig;

    ADC_Type * bases[NUMBER_OF_INSTANCES]               = {m_stADC[0]->base, m_stADC[1]->base};
    uint32 Instances[NUMBER_OF_INSTANCES]               = {m_stADC[0]->instances, m_stADC[1]->instances};
    adc16_chn_t channelIndex[NUMBER_OF_INSTANCES]       = {m_stADC[0]->chnIdx, m_stADC[1]->chnIdx};
    adc16_chn_mux_mode_t muxConfig[NUMBER_OF_INSTANCES] = {m_stADC[0]->adcMuxChannel, m_stADC[1]->adcMuxChannel};

 /* Config ADC module */
    const adc16_converter_config_t convConfig =
    {
        false,                   /*!< Enables low power. @internal gui name="Low power mode" id="LowPowerMode" */
        kAdc16ClkDividerOf8,     /*!< Selects the divider of input clock source. @internal gui name="Clock divider" id="ClockDivider" */
        true,                    /*!< Enables the long sample time. @internal gui name="Long sample time" id="LongSampleTime" */
        kAdc16ResolutionBitOf16, /*!< Selects the sample resolution mode. @internal gui name="Resolution" id="Resolution" */
  kAdc16ClkSrcOfBusClk,    /*!< Selects the input clock source to converter. @internal gui name="Clock source" id="ClockSource" */
        false, /*!< Enables the asynchronous clock inside the ADC. @internal gui name="Internal async. clock" id="InternalAsyncClock" */
        false, /*!< Enables the high-speed mode. @internal gui name="High speed mode" id="HighSpeed" */
        kAdc16LongSampleCycleOf10, /*!< Selects the long sample mode. @internal gui name="Long sample mode" id="LongSampleMode" */
#if HARDWARE_TRIGGER   
  true,                      /*!< Enables the hardware trigger function. @internal gui name="Hardware trigger" id="HwTrigger" */
#else
  false,
#endif
  kAdc16RefVoltSrcOfVref, /*!< Selects the reference voltage source. @internal gui name="Voltage reference" id="ReferenceVoltage" */
        false,                  /*!< Enables continuous conversion mode. @internal gui name="Continuous mode" id="ContinuousMode" */

#if FSL_FEATURE_ADC16_HAS_DMA
#if WITH_DMA
        true
#else
        false /*!< Enables the DMA for ADC converter. @internal gui name="DMA mode" id="DMASupport" */
#endif /*WITH_DMA*/
#endif /*FSL_FEATURE_ADC16_HAS_DMA*/
    };

    /* Config hardware average function */
    const adc16_hw_average_config_t averageConfig =
 {
#if AVERAGING_HARDWARE
  true,
#else
        false,                     /*!< Enable the hardware average function. */
#endif
  kAdc16HwAverageCountOf32  /*!< Select the count of conversion result for accumulator. */
    };

    for (uint32 i = 0; i < m_numberOfUsedInstances; ++i)
    {
        /* Disable ADC interrupt */
        NVIC_DisableIRQ(m_stADC[i]->ADC_IRQn);

#if WITH_DMA

        /* De-Init DMAMUX */
        DMAMUX_HAL_SetChannelCmd(m_stADC[i]->DMAMUX_Peripheral, static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel1), false);

        /* De-Init EDMA */
        EDMA_HAL_HTCDClearReg(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1);
        EDMA_HAL_ClearIntStatusFlag(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1);
        EDMA_HAL_ClearErrorIntStatusFlag(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1);

        /* Disable DMA ADC interrupt */
        NVIC_DisableIRQ(m_stADC[i]->EDMA_ADCIRQn);
#endif /*WITH_DMA*/

        /* Un-gate ADC clock */
        CLOCK_SYS_EnableAdcClock(Instances[i]);

        /* Enable ADC module clock*/
        ADC16_HAL_Init(bases[i]);

        /* Calibrate ADC module */
        ADC16_HAL_SetAutoCalibrationCmd(bases[i], true);
        while (ADC16_HAL_GetAutoCalibrationActiveFlag(bases[i]))
            ;
        ASSERT_ALWAYS(!ADC16_HAL_GetAutoCalibrationFailedFlag(bases[i]));

#if FSL_FEATURE_ADC16_HAS_DIFF_MODE
        uint16 minusGain = ADC16_HAL_GetAutoMinusSideGainValue(bases[i]);
        ADC16_HAL_SetMinusSideGainValue(bases[i], minusGain);
        uint16 plusGain = ADC16_HAL_GetAutoPlusSideGainValue(bases[i]);
        ADC16_HAL_SetPlusSideGainValue(bases[i], plusGain);
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */

        ADC16_HAL_ConfigConverter(bases[i], &convConfig);
        ADC16_HAL_ConfigHwAverage(bases[i], &averageConfig);

        /* Configure ADC channel, Interrupt and differential enable */
        adcChnConfig.chnIdx = channelIndex[i];

#if WITH_DMA
        adcChnConfig.convCompletedIntEnable = false;  // Disables the ADC interrupt
#else
        adcChnConfig.convCompletedIntEnable = true;  // Enables the ADC interrupt
#endif /*WITH_DMA*/

#if FSL_FEATURE_ADC16_HAS_DIFF_MODE
        adcChnConfig.diffConvEnable = false; /*!< Enable/ Disable the differential conversion. */
#endif                                       /*FSL_FEATURE_ADC16_HAS_DIFF_MODE*/

        ADC16_HAL_ConfigChn(bases[i], muxConfig[i], &adcChnConfig);
        ADC16_HAL_SetChnMuxMode(bases[i], muxConfig[i]);

        /* Initialise and reset TCD Buffers for the two DMA Channels */
        edma_software_tcd_t stcd[TCD_COUNT];
        memset(stcd, 0, sizeof(stcd));
        memset(m_configDMA, 0, sizeof(m_configDMA));

#if WITH_DMA

        /* Configure ADC DMA */
        m_configDMA[0].srcAddr            = reinterpret_cast<uint32_t>(&ADC_R_REG(m_stADC[i]->base, 0));
        m_configDMA[0].destAddr           = reinterpret_cast<uint32_t>(&m_stDMA_Collect[ (3*i) + 2]);
        m_configDMA[0].srcTransferSize    = kEDMATransferSize_2Bytes;
        m_configDMA[0].destTransferSize   = kEDMATransferSize_2Bytes;
        m_configDMA[0].srcOffset          = 0x00;
        m_configDMA[0].destOffset         = 0x00;  // 2 Bytes
        m_configDMA[0].srcLastAddrAdjust  = 0x00;
  m_configDMA[0].destLastAddrAdjust = 0x00; //static_cast<uint32_t>(-6);
        m_configDMA[0].srcModulo          = kEDMAModuloDisable;
        m_configDMA[0].destModulo         = kEDMAModuloDisable;
        m_configDMA[0].minorLoopCount     = 2U;
        m_configDMA[0].majorLoopCount     = 1U;

        /* DMAMUX init */
        DMAMUX_HAL_SetTriggerSource(m_stADC[i]->DMAMUX_Peripheral, static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel1),
                                    static_cast<uint8>(m_stADC[i]->DMAMUX_ADC_Source));
        DMAMUX_HAL_SetChannelCmd(m_stADC[i]->DMAMUX_Peripheral, static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel1), true);

#ifdef AUTONOM /*automatic triggering of ADC conversions*/
        EDMA_HAL_STCDSetChannelMinorLink(&stcd[0], static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel2), true);
#else
        EDMA_HAL_STCDSetChannelMinorLink(&stcd[0], static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel1), false);
#endif /*AUTONOM*/

#ifdef DMA_INTERRUPT
        EDMA_HAL_STCDSetBasicTransfer(m_stADC[i]->EDMA_Peripheral, &stcd[0], &m_configDMA[0], true, false);
#else
        EDMA_HAL_STCDSetBasicTransfer(m_stADC[i]->EDMA_Peripheral, &stcd[0], &m_configDMA[0], false, false);
#endif /*DMA_INTERRUPT*/

        EDMA_HAL_PushSTCDToHTCD(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1, &stcd[0]);
        EDMA_HAL_SetDmaRequestCmd(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1, true);

// ------------------------------------------------
// For transferring from SRAM to ADC_SC1A
// ------------------------------------------------

#ifdef AUTONOM /*automatic triggering of ADC conversions*/

        EDMA_HAL_ClearIntStatusFlag(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2);
        EDMA_HAL_ClearErrorIntStatusFlag(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2);

        /* DMAMUX init */
        DMAMUX_HAL_SetChannelCmd(m_stADC[i]->DMAMUX_Peripheral, static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel2), false);
        DMAMUX_HAL_SetChannelCmd(m_stADC[i]->DMAMUX_Peripheral, static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel2), true);

        uint8 channel2Scan = ADC_Channel_NTC_IN;
        if (1 == i)
        {
            channel2Scan = SECOND_ADC_FIRST_CHANNEL;
        }

        /* Configure ADC DMA */
        m_configDMA[1].srcAddr            = reinterpret_cast<uint32_t>(&m_stChannels->channels[channel2Scan]);
        m_configDMA[1].destAddr           = reinterpret_cast<uint32_t>(&m_stADC[i]->base->SC1[0]);
        m_configDMA[1].srcTransferSize    = kEDMATransferSize_1Bytes;
        m_configDMA[1].destTransferSize   = kEDMATransferSize_1Bytes;
        m_configDMA[1].srcOffset          = 0x01;
        m_configDMA[1].destOffset         = 0x00;
        m_configDMA[1].srcLastAddrAdjust  = static_cast<uint32_t>(-3);
        m_configDMA[1].destLastAddrAdjust = 0x00;
        m_configDMA[1].srcModulo          = kEDMAModuloDisable;
        m_configDMA[1].destModulo         = kEDMAModuloDisable;
        m_configDMA[1].minorLoopCount     = 1U;
        m_configDMA[1].majorLoopCount     = 3U;

        /* Links the second DMA Channel to the TCD of the first DMA Channel */
        EDMA_HAL_STCDSetChannelMinorLink(&stcd[1], static_cast<uint32>(m_stADC[i]->EDMA_ADC_Channel2), false);
        EDMA_HAL_STCDSetBasicTransfer(m_stADC[i]->EDMA_Peripheral, &stcd[1], &m_configDMA[1], true, false);
        EDMA_HAL_PushSTCDToHTCD(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2, &stcd[1]);
        EDMA_HAL_SetDmaRequestCmd(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2, true);
        EDMA_HAL_TriggerChannelStart(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2);
// EDMA_HAL_SetChannelPriority(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel1, m_stADC[i]->EDMA_CH1_Priortity);
// EDMA_HAL_SetChannelPriority(m_stADC[i]->EDMA_Peripheral, m_stADC[i]->EDMA_ADC_Channel2, m_stADC[i]->EDMA_CH2_Priortity);

#endif /*AUTONOM*/

#ifdef DMA_INTERRUPT
        /* Initialize EDMA interrupts */
        NVIC_ClearPendingIRQ(m_stADC[i]->EDMA_ADCIRQn);
        NVIC_SetPriority(m_stADC[i]->EDMA_ADCIRQn, m_stADC[i]->EDMA_IRQPriority);
        NVIC_EnableIRQ(m_stADC[i]->EDMA_ADCIRQn);
#endif /*DMA_INTERRUPT*/

#else
        /* Initialize ADC interrupts */
        NVIC_ClearPendingIRQ(m_stADC[i]->ADC_IRQn);
        NVIC_SetPriority(m_stADC[i]->ADC_IRQn, m_stADC[i]->ADC_IRQPriority);
        NVIC_EnableIRQ(m_stADC[i]->ADC_IRQn);
#endif /*WITH_DMA*/

        // ###########################################################################

#if HARDWARE_TRIGGER

        // Timer Configuration to generate trigger for ADC
        CLOCK_SYS_EnableFtmClock(m_stADC[0]->FTM_Instance);

  /* Use FTM mode */
  FTM_HAL_Enable(m_stADC[0]->FTM_base, true);

  // Set prescaler to 1
  FTM_HAL_SetClockPs(m_stADC[0]->FTM_base, kFtmDividedBy1);

        // Configure outputs
        FTM_HAL_SetWriteProtectionCmd(m_stADC[0]->FTM_base, false);
        FTM_HAL_SetClockSource(m_stADC[0]->FTM_base, kClock_source_FTM_None);

        //Set FTM external trigger
  FTM_HAL_SetInitTriggerCmd(m_stADC[0]->FTM_base, true);

#if WITH_FTM_INTERRUPT
        // Configure and enable FTM overflow interrupt
        NVIC_EnableIRQ(m_stADC[0]->FTM_OverflowIrq);
        // Enable interrupt on counter overflow
        FTM_HAL_EnableTimerOverflowInt(m_stADC[0]->FTM_base);
#else
       
  SIM_HAL_SetAdcTriggerModeOneStep(SIM, i, true, kSimAdcPretrgselA, kSimAdcTrgSelFtm2);

  EN_ADC_CHANNELS channel;
        if (1 == i)
        {
            channel = ADC_Channel_PHOTO2;
        }
        else
        {
            channel = ADC_Channel_PHOTO1;
        }
        setADCTriggerInput(channel, true);

#endif
#endif
        // ###########################################################################
    }
}

/*------------------------------------------------------------------------*/ /**
    Configures Timer to the new on Time
    If on_time_us is 0 then no timer will be started
*/  //---------------------------------------------------------------------------
void CADC_MK24FN1M0::setTriggerInterval(const uint16 triggerInterval_us)
{
#if HARDWARE_TRIGGER
    m_trigTime_us = triggerInterval_us;

 const uint64 fmtClockFrequency = SystemCoreClock; 
    const uint8 prescaler = 1;

 m_clocksforTImer = static_cast<uint16>( HZ_TO_MHZ( (fmtClockFrequency / prescaler) * m_trigTime_us) ); 
 
    FTM_HAL_SetMod(m_stADC[0]->FTM_base, m_clocksforTImer);
#endif
}

/*------------------------------------------------------------------------*/ /**
    Sets the trigger for m_trigTime_us to high to start the ADC conversion
*/  //---------------------------------------------------------------------------
void CADC_MK24FN1M0::startTrigger()
{
#if HARDWARE_TRIGGER
    if (m_trigTime_us != 0)
    { 
#if TEST_TOGGLE_PIN
  g_testToggleFlag = false;
#endif
        FTM_HAL_SetCounterInitVal(m_stADC[0]->FTM_base, 0);
        FTM_HAL_SetWriteProtectionCmd(m_stADC[0]->FTM_base, false);
        FTM_HAL_ClearTimerOverflow(m_stADC[0]->FTM_base);
        FTM_HAL_SetClockSource(m_stADC[0]->FTM_base, kClock_source_FTM_SystemClk);
    }
#else
 setADCTriggerInput(IADC::ADC_Channel_PHOTO1, true);
 setADCTriggerInput(IADC::ADC_Channel_PHOTO2, true );
#endif
}

void CADC_MK24FN1M0::stopTrigger()

#if HARDWARE_TRIGGER
    FTM_HAL_ClearTimerOverflow(m_stADC[0]->FTM_base);
    FTM_HAL_SetWriteProtectionCmd(m_stADC[0]->FTM_base, false);
    FTM_HAL_SetClockSource(m_stADC[0]->FTM_base, kClock_source_FTM_None);
#else
 setADCTriggerInput(IADC::ADC_Channel_PHOTO1, false);
 setADCTriggerInput(IADC::ADC_Channel_PHOTO2, false);
#endif
}

/*------------------------------------------------------------------------*/ /**
* \brief        irq Handler routine for the ADC IRQ
* \param[in]    any one of the "EN_ADC_CHANNELS"
* \return       none
*/  //---------------------------------------------------------------------------
void CADC_MK24FN1M0::irqADC(uint32 adcInstance)
{
 static uint16 measureCount[NUMBER_OF_INSTANCES] = { 0 , 0 };
 uint8 channelNumber = ( static_cast<uint8>(m_stADC[adcInstance]->base->SC1[0]) & 0x1F );

 GPIO_HAL_WritePinOutput(PTA, 14, 1);

 EN_ADC_CHANNELS channel2Scan = getADCChannel2Scan(adcInstance, channelNumber);

 m_stDMA_Collect[channel2Scan] = ADC16_HAL_GetChnConvValue(m_stADC[adcInstance]->base, 0);

#if AVERAGING_HARDWARE
 m_ADCConversionFinish[channel2Scan] = true;
#else 
 m_ADC_Measurements[adcInstance] += m_stDMA_Collect[channel2Scan];

 if (MAX_ADC_MEASUREMENTS <= ++measureCount[adcInstance])
 {
  GPIO_HAL_WritePinOutput(PTB, 16, 1);
  m_AverageADC[adcInstance] = static_cast<uint16>(m_ADC_Measurements[adcInstance] / MAX_ADC_MEASUREMENTS);
  measureCount[adcInstance] = 0;
  m_ADCConversionFinish[channel2Scan] = true;
  GPIO_HAL_WritePinOutput(PTB, 16, 0);
 }
#endif

 GPIO_HAL_WritePinOutput(PTA, 14, 0);

#if 0
 if (adcInstance)
 {
  setADCTriggerInput(IADC::ADC_Channel_PHOTO1, true);
 }
 else
 {
  setADCTriggerInput(IADC::ADC_Channel_PHOTO2, true);
 }
#endif 
}

// ##############################################################################################

in ADC.h file the following Struct is declared.

// ##############################################################################################

struct STADCHardware
    {
        FTM_Type * FTM_base;
        uint32 FTM_Instance;
        IRQn_Type FTM_OverflowIrq;
        ADC_Type * base;
        uint32 instances;
        adc16_chn_t chnIdx;
        adc16_chn_mux_mode_t adcMuxChannel;
        IRQn_Type ADC_IRQn;                          // IRQ channel ADC
        uint8 ADC_IRQPriority;                       // IRQ preemption priority
        DMAMUX_Type * DMAMUX_Peripheral;             // DMAMUX peripheral
        uint32 DMAMUX_Instance;                      // DMAMUX instance
        dma_request_source_t DMAMUX_ADC_Source;      // Source configuration for ADC
        DMA_Type * EDMA_Peripheral;                  // DMA peripheral
        uint32 EDMA_Instance;                        // instance in library(eg. 0 = DMA0)
        edma_channel_indicator_t EDMA_ADC_Channel1;  // DMA ADC channel
        edma_channel_indicator_t EDMA_ADC_Channel2;  // DMA ADC channel
        IRQn_Type EDMA_ADCIRQn;                      // IRQ channel DMA ADC
        uint8 EDMA_IRQPriority;                      // IRQ preemption priority
        edma_channel_priority_t EDMA_CH1_Priortity;
        edma_channel_priority_t EDMA_CH2_Priortity;
    };

// ##############################################################################################

// ##############################################################################################

in my Config.h file the following ADC configurations are used

// ##############################################################################################

#if 1
static const CADC_MK24FN1M0::STADCHardware stADC1 = {
    FTM3,                 // FTM_Type         *base;
    3,                    // uint32           FTM_Instance;
    FTM3_IRQn,            // IRQn_Type         FTM_OverflowIrq;
    ADC1,                 // ADC_Type         *base;
    1,                    // instances        ADC_Instance
    kAdc16Chn1d,          // adc16_chn_t
    kAdc16ChnMuxOfA,      // All Channels use multiplexer setting b
    ADC1_IRQn,            // IRQ channel ADC
    0,                    // IRQ preemption priority
    DMAMUX,               // DMAMUX_Type              *DMAMUX_Peripheral;// DMAMUX peripheral
    0,                    // uint32                   DMAMUX_Instance;   // DMAMUX instance
    kDmaRequestMux0ADC1,  // dma_request_source_t     DMAMUX_ADC_Source; // Source configuration for ADC
    DMA0,                 // DMA_Type                 *EDMA_Peripheral;  // DMA peripheral
    0,                    // uint32                   EDMA_Instance;     // instance in library(eg. 0 = DMA0)
    kEDMAChannel10,       // edma_channel_indicator_t EDMA_ADC_Channel;  // DMA  channel
    kEDMAChannel11,
    DMA10_IRQn,  // IRQn_Type                EDMA_ADCIRQn;      // IRQ DMA ADC
    0,           // IRQ preemption Priority
    kEDMAChnPriority11,
    kEDMAChnPriority10};
#endif

#if 1
static const CADC_MK24FN1M0::STADCHardware stADC0 = {
    FTM2,                 // FTM_Type         *base;
    2,                    // uint32           FTM_Instance;
    FTM2_IRQn,            // IRQn_Type         FTM_OverflowIrq;
    ADC0,                 // ADC_Type         *base;
    0,                    // instances        ADC_Instance
    kAdc16Chn1d,          // adc16_chn_t
    kAdc16ChnMuxOfA,      // All Channels use multiplexer setting b
    ADC0_IRQn,            // IRQ channel ADC
    0,                    // IRQ preemption Priority
    DMAMUX,               // DMAMUX_Type              *DMAMUX_Peripheral;// DMAMUX peripheral
    0,                    // uint32                   DMAMUX_Instance;   // DMAMUX instance
    kDmaRequestMux0ADC0,  // dma_request_source_t     DMAMUX_ADC_Source; // Source configuration for ADC
    DMA0,                 // DMA_Type                 *EDMA_Peripheral;  // DMA peripheral
    0,                    // uint32                   EDMA_Instance;     // instance in library(eg. 0 = DMA0)
    kEDMAChannel12,       // edma_channel_indicator_t EDMA_ADC_Channel;  // DMA channel
    kEDMAChannel13,
    DMA12_IRQn,  // IRQn_Type                EDMA_ADCIRQn;      // IRQ DMA ADC
    0,           // IRQ preemption Priority
    kEDMAChnPriority13,
    kEDMAChnPriority12};
#endif

// ##############################################################################################

Hoping to get some help in the right direction!

Thanks and have a nice day!

0 项奖励
回复