LPC54018 Reading Multiple ADCs

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC54018 Reading Multiple ADCs

Jump to solution
2,975 Views
ahmed_mostafa
Contributor II
I'm looking to collect multiple ADC readings at the same time with ADC0_4, ADC0_5, ADC0_6. I'm using the ADC basic example for the SDK. I configured all 3 inputs with the same configuration settings. Both are set to sequence A. I was able to receive accurate readings for ADC0_4 and ADC0_5, but for some reason ADC0_6 is not reporting any readings at all. Do I need to configure ADC0_6 differently? On the datasheet it says that ADC[0:5] are the fast channels and ADC[6:11] are the slow channels, does that mean that ADC0_6 can't be read alongside the other ones? If that is the case, how do I read an ADC from input channels 6:11? Should I set them up with sequence B?
0 Kudos
1 Solution
2,940 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I have checked that ADC0->FLAGS[SEQA_INT] can not be set,  I do not know why either, maybe it is only used in interrupt or DMA mode.

 

Any, pls use the code as you have done, I just modify it based on your architecture. Now it works fine. Note that the DATA VALID bit for DAT[0:11] register can only be read once. Reading the register will clear the bit.

 

DATA
VALID
This bit is set to 1 at the end of each conversion when a new result is loaded into the RESULT
field. It is cleared whenever this register is read.
This bit will cause a conversion-complete interrupt for the corresponding sequence if the MODE
bit (in SEQB_CTRL) for that sequence is set to 0 (and if the interrupt is enabled).

Hope it can help you

BR

XiangJun Rong

int main(void)
{
/* Initialize board hardware. */
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */

CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

BOARD_InitPins();
BOARD_BootClockPLL180M();
BOARD_InitDebugConsole();
/* Reset DMA since core reset in IDE will not reset DMA */
RESET_SetPeripheralReset(kDMA_RST_SHIFT_RSTn);
/* Enable the power and clock for ADC. */
ADC_ClockPower_Configuration();
PRINTF("ADC basic example.\r\n");

#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
uint32_t frequency = 0U;
/* Calibration after power up. */
#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
DEMO_ADC_BASE->CTRL |= ADC_CTRL_BYPASSCAL_MASK;
frequency = CLOCK_GetFreq(kCLOCK_BusClk);
if (true == ADC_DoOffsetCalibration(DEMO_ADC_BASE, frequency))
#else
#if defined(SYSCON_ADCCLKDIV_DIV_MASK)
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) / CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
#else
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
#endif /* SYSCON_ADCCLKDIV_DIV_MASK */
if (true == ADC_DoSelfCalibration(DEMO_ADC_BASE, frequency))
#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */
{
PRINTF("ADC Calibration Done.\r\n");
}
else
{
PRINTF("ADC Calibration Failed.\r\n");
}
#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */

/* Configure the converter and work mode. */
ADC_Configuration();
PRINTF("Configuration Done.\r\n");

#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
while (1)
{
/* Get the input from terminal and trigger the converter by software. */
GETCHAR();
ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
//ADC_DoSoftwareTriggerConvSeqB(DEMO_ADC_BASE);
#if 1 //Rong wrote: it appears the lines is incorrect
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct);

while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5);

while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6);
#endif

#if 0
/* Wait for the converter to be done. */
while(!(ADC0->FLAGS& 0x10000000)) //test the ADC0->FLAGS[SEQA_INT], bit 28
{
//PRINTF("In loop.\r\n");
}
ADC0->FLAGS|=0x10000000;
#endif
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct);
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5);
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6);


PRINTF("adcResultInfoStruct.result = %d\r\n", adcResultInfoStruct.result);
PRINTF("adcResultInfoStruct.channelNumber = %d\r\n", adcResultInfoStruct.channelNumber);
PRINTF("adcResultInfoStruct.overrunFlag = %d\r\n", adcResultInfoStruct.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct5.result = %d\r\n", adcResultInfoStruct5.result);
PRINTF("adcResultInfoStruct5.channelNumber = %d\r\n", adcResultInfoStruct5.channelNumber);
PRINTF("adcResultInfoStruct5.overrunFlag = %d\r\n", adcResultInfoStruct5.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct6.result = %d\r\n", adcResultInfoStruct6.result);
PRINTF("adcResultInfoStruct6.channelNumber = %d\r\n", adcResultInfoStruct6.channelNumber);
PRINTF("adcResultInfoStruct6.overrunFlag = %d\r\n", adcResultInfoStruct6.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
}

}

View solution in original post

0 Kudos
7 Replies
2,967 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Ahmed,

Regarding your question, I do not think there is big difference for the ADC[0:5]  fast channels and ADC[6:11] slow channel except for the ADC fast/slow channel pin input impedance.

Regarding your issue, I think your ADC code has issue, pls post your ADC code so that we can have a review.

BR

Xiangjun Rong

 

0 Kudos
2,961 Views
ahmed_mostafa
Contributor II

I have attached my code. These 2 files are the only ones I made changes to.

In the pin_mux.c I initialized all 3 ADCs using the same parameters.

Again, ADC0_4 and ADC0_5 seem to work well, but ADC_6 is not working.

Thanks for the help.

0 Kudos
2,879 Views
ahmed_mostafa
Contributor II

Thanks for your help. I believe I know the reason. On my evaluation board, the ADC input for channel 6 is shorted to ground.

 

Thanks for your help.

0 Kudos
2,957 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Pls try to test the code.

Hope it can help you

BR

XiangJun Rong

int main(void)
{
/* Initialize board hardware. */
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */

CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

BOARD_InitPins();
BOARD_BootClockPLL180M();
BOARD_InitDebugConsole();
/* Reset DMA since core reset in IDE will not reset DMA */
RESET_SetPeripheralReset(kDMA_RST_SHIFT_RSTn);
/* Enable the power and clock for ADC. */
ADC_ClockPower_Configuration();
PRINTF("ADC basic example.\r\n");

#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
uint32_t frequency = 0U;
/* Calibration after power up. */
#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
DEMO_ADC_BASE->CTRL |= ADC_CTRL_BYPASSCAL_MASK;
frequency = CLOCK_GetFreq(kCLOCK_BusClk);
if (true == ADC_DoOffsetCalibration(DEMO_ADC_BASE, frequency))
#else
#if defined(SYSCON_ADCCLKDIV_DIV_MASK)
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) / CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
#else
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
#endif /* SYSCON_ADCCLKDIV_DIV_MASK */
if (true == ADC_DoSelfCalibration(DEMO_ADC_BASE, frequency))
#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */
{
PRINTF("ADC Calibration Done.\r\n");
}
else
{
PRINTF("ADC Calibration Failed.\r\n");
}
#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */

/* Configure the converter and work mode. */
ADC_Configuration();
PRINTF("Configuration Done.\r\n");

#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
while (1)
{
/* Get the input from terminal and trigger the converter by software. */
GETCHAR();
ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
//ADC_DoSoftwareTriggerConvSeqB(DEMO_ADC_BASE);

/////////////////////////////////////////////////////////////////////////////////////////////////////////

///////Rong modified code beginning

/* Wait for the converter to be done. */
#if 0 //Rong wrote: it appears the lines is incorrect
while ((!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct))
&& (!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5))
&& (!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6)))
#endif

while(!(ADC0->FLAGS&0x10000000)) //test the ADC0->FLAGS[SEQA_INT], bit 28
{
}

ADC0->FLAGS|=0x10000000;

ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct);

ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5);

ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6);

///////Rong modified code end

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PRINTF("adcResultInfoStruct.result = %d\r\n", adcResultInfoStruct.result);
PRINTF("adcResultInfoStruct.channelNumber = %d\r\n", adcResultInfoStruct.channelNumber);
PRINTF("adcResultInfoStruct.overrunFlag = %d\r\n", adcResultInfoStruct.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct5.result = %d\r\n", adcResultInfoStruct5.result);
PRINTF("adcResultInfoStruct5.channelNumber = %d\r\n", adcResultInfoStruct5.channelNumber);
PRINTF("adcResultInfoStruct5.overrunFlag = %d\r\n", adcResultInfoStruct5.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct6.result = %d\r\n", adcResultInfoStruct6.result);
PRINTF("adcResultInfoStruct6.channelNumber = %d\r\n", adcResultInfoStruct6.channelNumber);
PRINTF("adcResultInfoStruct6.overrunFlag = %d\r\n", adcResultInfoStruct6.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
}
/*
GETCHAR();
ADC_DoSoftwareTriggerConvSeqB(DEMO_ADC_BASE);

/* Wait for the converter to be done. *./
while ((!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct6)))

{
}
PRINTF("adcResultInfoStruct6.result = %d\r\n", adcResultInfoStruct6.result);
PRINTF("adcResultInfoStruct6.channelNumber = %d\r\n", adcResultInfoStruct6.channelNumber);
PRINTF("adcResultInfoStruct6.overrunFlag = %d\r\n", adcResultInfoStruct6.overrunFlag ? 1U : 0U);
PRINTF("\r\n");*/

}

0 Kudos
2,953 Views
ahmed_mostafa
Contributor II

The code is stuck in the main while loop. It did not work for me.

What could be causing the issue?

0 Kudos
2,941 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I have checked that ADC0->FLAGS[SEQA_INT] can not be set,  I do not know why either, maybe it is only used in interrupt or DMA mode.

 

Any, pls use the code as you have done, I just modify it based on your architecture. Now it works fine. Note that the DATA VALID bit for DAT[0:11] register can only be read once. Reading the register will clear the bit.

 

DATA
VALID
This bit is set to 1 at the end of each conversion when a new result is loaded into the RESULT
field. It is cleared whenever this register is read.
This bit will cause a conversion-complete interrupt for the corresponding sequence if the MODE
bit (in SEQB_CTRL) for that sequence is set to 0 (and if the interrupt is enabled).

Hope it can help you

BR

XiangJun Rong

int main(void)
{
/* Initialize board hardware. */
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */

CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

BOARD_InitPins();
BOARD_BootClockPLL180M();
BOARD_InitDebugConsole();
/* Reset DMA since core reset in IDE will not reset DMA */
RESET_SetPeripheralReset(kDMA_RST_SHIFT_RSTn);
/* Enable the power and clock for ADC. */
ADC_ClockPower_Configuration();
PRINTF("ADC basic example.\r\n");

#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC)
uint32_t frequency = 0U;
/* Calibration after power up. */
#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG
DEMO_ADC_BASE->CTRL |= ADC_CTRL_BYPASSCAL_MASK;
frequency = CLOCK_GetFreq(kCLOCK_BusClk);
if (true == ADC_DoOffsetCalibration(DEMO_ADC_BASE, frequency))
#else
#if defined(SYSCON_ADCCLKDIV_DIV_MASK)
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE) / CLOCK_GetClkDivider(kCLOCK_DivAdcClk);
#else
frequency = CLOCK_GetFreq(DEMO_ADC_CLOCK_SOURCE);
#endif /* SYSCON_ADCCLKDIV_DIV_MASK */
if (true == ADC_DoSelfCalibration(DEMO_ADC_BASE, frequency))
#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */
{
PRINTF("ADC Calibration Done.\r\n");
}
else
{
PRINTF("ADC Calibration Failed.\r\n");
}
#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */

/* Configure the converter and work mode. */
ADC_Configuration();
PRINTF("Configuration Done.\r\n");

#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL
PRINTF("ADC Full Range: %d\r\n", g_Adc_12bitFullRange);
#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL */
while (1)
{
/* Get the input from terminal and trigger the converter by software. */
GETCHAR();
ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
//ADC_DoSoftwareTriggerConvSeqB(DEMO_ADC_BASE);
#if 1 //Rong wrote: it appears the lines is incorrect
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct);

while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5);

while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6)) {}
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6);
#endif

#if 0
/* Wait for the converter to be done. */
while(!(ADC0->FLAGS& 0x10000000)) //test the ADC0->FLAGS[SEQA_INT], bit 28
{
//PRINTF("In loop.\r\n");
}
ADC0->FLAGS|=0x10000000;
#endif
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER4, &adcResultInfoStruct);
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER5, &adcResultInfoStruct5);
ADC_GetChannelConversionResult(DEMO_ADC_BASE, DEMO_ADC_SAMPLE_CHANNEL_NUMBER6, &adcResultInfoStruct6);


PRINTF("adcResultInfoStruct.result = %d\r\n", adcResultInfoStruct.result);
PRINTF("adcResultInfoStruct.channelNumber = %d\r\n", adcResultInfoStruct.channelNumber);
PRINTF("adcResultInfoStruct.overrunFlag = %d\r\n", adcResultInfoStruct.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct5.result = %d\r\n", adcResultInfoStruct5.result);
PRINTF("adcResultInfoStruct5.channelNumber = %d\r\n", adcResultInfoStruct5.channelNumber);
PRINTF("adcResultInfoStruct5.overrunFlag = %d\r\n", adcResultInfoStruct5.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
PRINTF("adcResultInfoStruct6.result = %d\r\n", adcResultInfoStruct6.result);
PRINTF("adcResultInfoStruct6.channelNumber = %d\r\n", adcResultInfoStruct6.channelNumber);
PRINTF("adcResultInfoStruct6.overrunFlag = %d\r\n", adcResultInfoStruct6.overrunFlag ? 1U : 0U);
PRINTF("\r\n");
}

}

0 Kudos
2,882 Views
ahmed_mostafa
Contributor II

Hello,

I have used the code that you recommended, but I'm still not able to read accurate information for ADC0IN6. All I can read is 4092 every time I try to read, even though the result should be different (i'm measuring 1.6V on the pin so it should be ~2040 or so. Channels 4 and 5 are functioning correctly. Please review my main file and let me know what I am doing wrong.

Am I configuring the ADC wrong?

Thanks

0 Kudos