AnsweredAssumed Answered

KL27Z switching between ADC channels in polled mode - timing problem?

Question asked by Robert Poor on Jan 31, 2017
Latest reply on Apr 18, 2017 by Ergun Sbn

I extended the sample application from


to read multiple ADC channels.  What I observe is that the first channel to be polled gets a reasonable value, the other channels polled after that get a full-scale reading (0xffff).  After inserting a delay between readings, I get reasonable values on all the channels.


My question: is there some flag that I must honor, or some known delay I must insert, when switching between input channels on the ADC?


Here is the code in question:


#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_adc16.h"

#include "pin_mux.h"
#include "clock_config.h"

#define DEMO_ADC16_BASE ADC0
#define CH08_ADC16_USER_CHANNEL 8U  /* PTB0, A0-ADC0_SE8 */
#define CH09_ADC16_USER_CHANNEL 9U  /* PTB1, A0-ADC0_SE9 */
#define CH11_ADC16_USER_CHANNEL 11U /* PTC2, A0-ADC0_SE11 */

void delay(void) {
for (uint32_t i = 0; i < 400000; i++) {

* Initialize a channel_config struct: no interrupts, no differential conversion.
void initChannelConfig(adc16_channel_config_t *config, int channelNumber) {
  config->channelNumber = channelNumber;
  config->enableInterruptOnConversionCompleted = false;
  config->enableDifferentialConversion = false;

When in software trigger mode, each conversion would be launched once calling the
"ADC16_ChannelConfigure()" function, which works like writing a conversion command
and executing it. For another channel's conversion, just to change the "channelNumber"
field in channel's configuration structure, and call "ADC16_ChannelConfigure() again.

* Read a sample from the ADC on the provided channel using polling.
uint32_t pollChannel(adc16_channel_config_t *config) {
  ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, config);
  while (0U == (kADC16_ChannelConversionDoneFlag &
         ADC16_GetChannelStatusFlags(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP))) {
return ADC16_GetChannelConversionValue(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP);

int main(void) {
  adc16_config_t adc16ConfigStruct;
  adc16_channel_config_t ch08ChannelConfig;
  adc16_channel_config_t ch09ChannelConfig;
  adc16_channel_config_t ch11ChannelConfig;


  PRINTF("\r\nADC16 polling example.\r\n");
  adc16ConfigStruct.enableLowPower = true;
  adc16ConfigStruct.longSampleMode = kADC16_LongSampleCycle24;
  ADC16_Init(DEMO_ADC16_BASE, &adc16ConfigStruct);
  ADC16_EnableHardwareTrigger(DEMO_ADC16_BASE, false); /* Make sure the software trigger is used. */
  if (kStatus_Success == ADC16_DoAutoCalibration(DEMO_ADC16_BASE)) {
    PRINTF("ADC16_DoAutoCalibration() Done.\r\n");
  } else {
    PRINTF("ADC16_DoAutoCalibration() Failed.\r\n");
  PRINTF("Press any key to get user channel's ADC value ...\r\n");

  initChannelConfig, &ch08ChannelConfig, CH08_ADC16_USER_CHANNEL);
  initChannelConfig, &ch09ChannelConfig, CH09_ADC16_USER_CHANNEL);
  initChannelConfig, &ch11ChannelConfig, CH11_ADC16_USER_CHANNEL);

  while (1) {

    uint32_t ch08_val = pollChannel(&ch08ChannelConfig);
    delay();  // without this delay, ch09_val reads as 0xffff
    uint32_t ch09_val = pollChannel(&ch09ChannelConfig);
    delay();  // without this delay, ch11_val reads as 0xffff
    uint32_t ch11_val = pollChannel(&ch11ChannelConfig);

    PRINTF("CH08: %d \tCH09: %d \tCH11: %d\r\n", ch08_val, ch09_val, ch11_val);


Example output WITHOUT the calls to delay():

CH08: 47808   CH09: 65535   CH11: 65535

Example output WITH the calls to delay():

CH08: 47808   CH09: 46678   CH11: 48726