MKL26Z How can 2 ADC inputs be read using an interrupt?

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

MKL26Z How can 2 ADC inputs be read using an interrupt?

1,093 Views
bgraham
Contributor IV

MCUXpresso IDE v10.2.1 [Build 795] [2018-07-25]

MKL26Z256VLH4

I am working on a Medical device. It needs to read 2 ADC inputs, a battery voltage and temperature.

I have 2 questions.

1) The ADC channel are on ADC0_SE11 pin 45, and ADC0_SE6b pin 62.

Are the channel numbers 0x11 and 0x6B?

0x6B is higher then 31, so that does not look correct.

2) See my attached project. I setup 2 ADCs in interrupt mode, so they use ADC0_IRQHandler().

Since ADC0_IRQHandler() is shared by the ADC channels, it must be able to determine which ADC channel has caused the interrupt.

How do I set up and use 2 ADCs inputs?

Thanks,

Bruce Graham
Senior Software Engineer
TechnoSoft Innovations, Inc

0 Kudos
5 Replies

846 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Bruce Graham,

1)

Please check the "Table 3-35. ADC0 channel assignment" of KL26P121M48SF4RM.

adc16_channel_config_t.pngTable 3-35. ADC0 channel assignment.png

2)

You can refer: Using DMA to Emulate ADC Flexible Scan Mode with SDK 2.x

Best Regards,

Robin

 

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

0 Kudos

846 Views
bgraham
Contributor IV

The provided example is for a MCU with a EDMA controller, so the example did not help.

.

I created a simple app that polls the ADC value on pin 45 of my MKL16Z256VLH4 board.

The code came from the ADC16 polling example.

See attached.

.

I started with a FRDM-KL26Z board, and replace the KL26Z with a KL16Z.

In the code, I set the input to ADC0_SE11 pin 45. 

.

When the app runs, the ADC conversion completes, but the ADC value does not change when the voltage on pin 45 changes.

The ADC value jumps between 0 and 4, so is it possible that my code is reading the wrong ADC channel?

.

Can somebody point out the program with the code?

.

Thanks,

Bruce

0 Kudos

846 Views
bgraham
Contributor IV

I would have provided the code, but I don't know to add it. So, I pasted main and support functions.

Bruce

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MKL16Z4.h"
#include "fsl_debug_console.h"
/* TODO: insert other include files here. */
void FloatToStringNew(char *str, float f, char size);

/* TODO: insert other definitions and declarations here. */


// Table 3-35. ADC0 channel assignment" of KL26P121M48SF4RM
#define ADC16_CHANNEL_BATT_VOLT 0x11 // ADC0_SE11 pin 45
//#define ADC16_CHANNEL_BATT_TEMP 0x06 // ADC0_SE6b pin 62
#define ADC16_CHANNEL_GROUP 0

/* BATT_VOLT
4.2V full charge
3.4V low, must charge
3.3V protection kicks in

Vin 4.2V (Full Charge)
|
10k
|---- Vout (BATT_VOLT)
4.7k
|
GND

Vout = (Vin * R2) / (R1 + R2)
Vout = (Vin * 4700) / (10000 + 4700)
= 19740 / 14700
Max BATT_VOLT = 1.34V
*/

#define VOLTS_PER_BIT (3.3f / 4096.0f) // Vref / 12 full scale 0x0FFF

float ADC_ValueToVoltage(uint16_t iAdcValue)
{
float fVolts = VOLTS_PER_BIT * (float)iAdcValue;

return fVolts;
}


/*
* @brief Application entry point.
*/
int main(void)
{
adc16_config_t adc16ConfigStruct;
adc16_channel_config_t adc16ChannelConfigStruct;

/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
/* Init FSL debug console. */
BOARD_InitDebugConsole();

PRINTF("Hello World\n");

ADC16_GetDefaultConfig(&adc16ConfigStruct);
ADC16_Init(ADC0, &adc16ConfigStruct);

PRINTF(" referenceVoltageSource: %d\n", adc16ConfigStruct.referenceVoltageSource);
PRINTF(" clockSource: %d\n", adc16ConfigStruct.clockSource);
PRINTF(" enableAsynchronousClock: %d\n", adc16ConfigStruct.enableAsynchronousClock);
PRINTF(" clockDivider: %d\n", adc16ConfigStruct.clockDivider);
PRINTF(" resolution: %d\n", adc16ConfigStruct.resolution);
PRINTF(" longSampleMode: %d\n", adc16ConfigStruct.longSampleMode);
PRINTF(" enableHighSpeed: %d\n", adc16ConfigStruct.enableHighSpeed);
PRINTF(" enableLowPower: %d\n", adc16ConfigStruct.enableLowPower);
PRINTF("enableContinuousConversion: %d\n", adc16ConfigStruct.enableContinuousConversion);

ADC16_EnableHardwareTrigger(ADC0, false);

#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
if (kStatus_Success == ADC16_DoAutoCalibration(ADC0))
{
PRINTF("ADC16_DoAutoCalibration() Done.\r\n");
}
else
{
PRINTF("ADC16_DoAutoCalibration() Failed.\r\n");
}
#endif // FSL_FEATURE_ADC16_HAS_CALIBRATION

adc16ChannelConfigStruct.channelNumber = ADC16_CHANNEL_BATT_VOLT;
adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = false;// Disable the interrupt.

#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
adc16ChannelConfigStruct.enableDifferentialConversion = false;
#endif // FSL_FEATURE_ADC16_HAS_DIFF_MODE

while(1)
{
//PRINTF("Press any key to get user channel's ADC value ...\r\n");
//GETCHAR(); // Input any key in terminal console.

ADC16_SetChannelConfig(ADC0, ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);

while (kADC16_ChannelConversionDoneFlag != ADC16_GetChannelStatusFlags(ADC0, ADC16_CHANNEL_GROUP))
{
}
uint16_t iValueAdc = ADC16_GetChannelConversionValue(ADC0, ADC16_CHANNEL_GROUP);
float fBatteryVoltage = ADC_ValueToVoltage(iValueAdc);
#if 1
char szBatteryVoltage[32];
FloatToStringNew(szBatteryVoltage, fBatteryVoltage, 6);
PRINTF("ADC Value: 0x%04X %s Volts\r\n", iValueAdc, szBatteryVoltage);
#else
PRINTF("ADC Value: 0x%04X %f Volts\r\n", iValueAdc, fBatteryVoltage);
#endif
}
}

#if 1
// convert float to string one decimal digit at a time
// assumes float is < 65536 and ARRAYSIZE is big enough
// problem: it truncates numbers at size without rounding
// str is a char array to hold the result, float is the number to convert
// size is the number of decimal digits you want
void FloatToStringNew(char *str, float f, char size)
{
int pos; // position in string
char len; // length of decimal part of result
int value; // decimal digit(s) to convert

pos = 0; // initialize pos, just to be sure

value = (int)f; // truncate the floating point number
itoa(value, str, 10); // this is kinda dangerous depending on the length of str
// now str array has the digits before the decimal
strcat(str, ".");

if (f < 0 ) // handle negative numbers
{
f *= -1;
value *= -1;
}

len = strlen(str); // find out how big the integer part was
pos = len; // position the pointer to the end of the integer part

while(pos < size) // process remaining digits
{
f = f - (float)value; // hack off the whole part of the number
f *= 10; // move next digit over
value = (int)f; // get next digit
itoa(value, &str[pos], 10); // convert digit to string
pos++;
}
str[pos] = 0;
}

#endif

0 Kudos

846 Views
bgraham
Contributor IV

The ADC problem occurs with:

ADC0_SE6b pin 62   FRDM dev kit J2-12

ADC0_SE7b pin 63   FRDM dev kit J2-8

ADC0_SE11 pin 45   FRDM dev kit J4-10

.

The LIGHT_SNS works:

ADC0_SE3 pin 11    FRDM dev kit J4-5.

.

Why does ADC0_SE3 work, but not ADC0_SE6b, ADC0_SE7b and ADC0_SE11?

.

Thanks,

Bruce

0 Kudos

846 Views
bgraham
Contributor IV

I created a new app using the KL26Z SDK, and the problems have changed.

.

The ADC problem occurs with:

ADC0_SE6b pin 62   FRDM dev kit J2-12 is stuck at 0x0FFF

ADC0_SE7b pin 63   FRDM dev kit J2-8 is reading noise about 0x0A00

ADC0_SE11 pin 45   FRDM dev kit J4-10 values are not linear

ADC0_SE3 pin 11    FRDM dev kit J4-5 0x0C12  at 2.4895 Volts, 0x0FF5  3.2911 Volts

.

The values returned from ADC0_SE11 are not linear.

ADC16_DoAutoCalibration() passed.

.

#define VOLTS_PER_BIT (3.3f / 4096.0f) // Vref / 12 full scale 0x0FFF

fComputedVolts = VOLTS_PER_BIT * (float)iAdcValue;

.

See values below.

Input    ADC       Computed V
===== ======   ==========
3.3 V   0x0F17   3.1122 V
3.0 V   0x0E19   2.9076 V
2.5 V   0x0C04   2.4782 V
2.0 V   0x0A01   2.0633 V
1.5 V   0x07E0   1.6242 V
1.0 V   0x0612   1.2520 V
0.5 V   0x0465   0.9063 V
0.0 V   0x0387   0.7275 V

Input is Orange. Computed V is Blue.

pastedImage_3.png

.

Is there a known ADC failure problem with the KL16Z SDK?

What is up with the non-linear ADC readings?

.

Thanks,

Bruce

0 Kudos