1. ADC generates Noise out and reads according value but, in very noise.
example when 1V was forced to ADC port at 16bit mode, it read 32882, 40049, 44011, 35050 in a short time.
2. I implemented the ADC in MK22FN128VLH10.
Environment:
Windows 10
KDS3.0
KSDK 1.2.0
3. Attached are "TPC Board_Program O.png", "MCU_ADC_port.png"
When applying MCU_ADC_port.png", and eleminating R1, R2 that means open ADC port from other circuit or connecting them,
pin 11(ADC1_DP0), pin 9(ADC0_DP0) generates noise like "TPC Board_Program O.png",
and reads swaying value.
4. I implemented two ways that are polling and interrupt.
My source code is as following:
- interrupt
const adc16_converter_config_t adConv1_InitConfig0 = {
.lowPowerEnable =
false,
.clkDividerMode = kAdc16ClkDividerOf1,
.longSampleTimeEnable = false,
.resolution = kAdc16ResolutionBitOf16,
.clkSrc = kAdc16ClkSrcOfBusClk,
.asyncClkEnable =
false,
.highSpeedEnable =
false,
.longSampleCycleMode
= kAdc16LongSampleCycleOf24,
.hwTriggerEnable =
false,
.refVoltSrc = kAdc16RefVoltSrcOfVref,
.continuousConvEnable
= false,
.dmaEnable = false,
};
// HW compare
const adc16_hw_cmp_config_t adConv1_HwConfig0 = {
.hwCmpEnable =
false,
.hwCmpGreaterThanEnable = false,
.hwCmpRangeEnable =
false,
.cmpValue1 = 0U,
.cmpValue2 = 0U,
};
// VDDA
const adc16_chn_config_t adConv1_ChnConfig0 = {
.chnIdx = kAdc16Chn29,
.convCompletedIntEnable = false,
.diffConvEnable =
false
};
// ADC0_DP0
const adc16_chn_config_t adConv1_ChnConfig1 = {
.chnIdx = kAdc16Chn0d,
//.convCompletedIntEnable
= false,
.convCompletedIntEnable = true,
.diffConvEnable =
false
};
// ADC1_DP0
const adc16_chn_config_t adConv1_ChnConfig2 = {
.chnIdx = kAdc16Chn3d,
//.convCompletedIntEnable
= false,
.convCompletedIntEnable
= true,
.diffConvEnable =
false
};
ADC16_DRV_Init(FSL_ADCONV1,
&adConv1_InitConfig0);
adc16_calibration_param_t adcCalibraitionParam;
ADC16_DRV_GetAutoCalibrationParam(FSL_ADCONV1,
&adcCalibraitionParam);
ADC16_DRV_SetCalibrationParam(FSL_ADCONV1,
&adcCalibraitionParam);
ADC16_DRV_Init(FSL_ADCONV1,
&adConv1_InitConfig0);
// ADC0 : MONITOR ->
Pressure Sensor
ADC16_DRV_ConfigConvChn(
FSL_ADCONV1, ADC16_CHN_GROUP, &adConv1_ChnConfig1
); // Software trigger the conversion.
// ADC1 : INPUT
ADC16_DRV_ConfigConvChn(
FSL_ADCONV1, ADC16_CHN_GROUP, &adConv1_ChnConfig2
); // Software trigger the conversion.
Main.c
while(1)
{
// ADC0 : MONITOR -> Pressure Sensor
ADC16_DRV_ConfigConvChn( FSL_ADCONV1, ADC16_CHN_GROUP,
&adConv1_ChnConfig1 ); // Software trigger the conversion.
// ADC1 : INPUT
ADC16_DRV_ConfigConvChn( FSL_ADCONV1, ADC16_CHN_GROUP,
&adConv1_ChnConfig2 ); // Software trigger the conversion.
}
Event.c
/*! adConv1 IRQ handler
*/
void ADC0_IRQHandler(void)
{
/*
Write your code here ... */
static
uint16_t readNr = 0;
if(readNr == 0) // ADC0, Pressure Sensor
{
readNr = 1;
Var_pressureAdc16 =
ADC16_DRV_GetConvValueSigned(FSL_ADCONV1, ADC16_CHN_GROUP);
// Fetch the conversion value.
}
else if(readNr == 1) // ADC1, Input
{
readNr = 0;
Var_inputAdc16 = ADC16_DRV_GetConvValueSigned(FSL_ADCONV1,
ADC16_CHN_GROUP); // Fetch the conversion
value.
}
}
- polling
adc16_converter_config_t
adcUserConfig; // structure for user config
ADC16_DRV_StructInitUserConfigDefault(&adcUserConfig);
adcUserConfig.resolution = kAdc16ResolutionBitOf16;
ADC16_DRV_Init(FSL_ADCONV1,
&adcUserConfig);
ADC_Calibration();
ADC16_DRV_Init(FSL_ADCONV1,
&adcUserConfig);
uint16_t ADC16_Measure(uint32_t instance, uint16_t channel_group, adc16_chn_t channel)
{
uint16_t adcValue;
adc16_chn_config_t
chnConfig;
// Configure the
conversion channel
// differential and
interrupt mode disable.
chnConfig.chnIdx =
(adc16_chn_t)channel;
chnConfig.diffConvEnable = false;
chnConfig.convCompletedIntEnable = false;
// Software trigger the
conversion.
ADC16_DRV_ConfigConvChn(instance, channel_group, &chnConfig);
// Wait for the conversion
to be done.
ADC16_DRV_WaitConvDone(instance, channel_group);
// Fetch the conversion
value.
adcValue
= ADC16_DRV_GetConvValueSigned(instance, channel_group);
// Pause the conversion.
ADC16_DRV_PauseConv(instance, channel_group);
return adcValue;
}
Main.c
while(1)
{
Var_inputAdc16 =
ADC16_Measure(FSL_ADCONV1, ADC16_CHN_GROUP, ADC1_DP0);
}
Both issues...
I need a solution to eleminate noise from adc port and read exact value, ugently.
Hi, Frank,
Regarding your question, I have some recommendation, but I do not guarantee to solve your problem, pls have a try.
1)from the schematics, it seems you use 10K ohm serial resistor on the ADC channel, it is too large, pls use 100 ohm or less.
2)The ADC clock frequency takes effect on the ADC accuracy, note that the ADC clock frequency should range from 2mHz to 12Mhz for K22, I suggest you set the fADCK as 2MHz to 8mhz.
How about not calibrating for a try.
For the firmware, I suggest you call the following function in ISR rather than in while(1). If you call it in while(), you should set a flag in ISR and poll the flag in while().
ADC16_DRV_ConfigConvChn( FSL_ADCONV1, ADC16_CHN_GROUP,
&adConv1_ChnConfig1 ); // Software trigger the conversion.
BR
Xiangjun Rong