I am using custom board with K63. I would like to use ADC interrupt to be triggered when value is less than threshold.
I have gone through ADC sample code and write my own ADC interrupt, yet I am not able to get ADC interrupt.
#define VBUS_ADC ADC1
#define VBUS_THRESH 0.64
/* Alias for ADC0 peripheral */
#define VBUS_ADC_IRQ_HANDLER ADC1_IRQHandler
#define VBUS_ADC_IRQ ADC1_IRQn
#define SE_12BIT 4096.0
#define VREF_BRD 3.300 /* ADC VREF voltage */
#define ADC_THRSHLD 750
void VBUS_ADC_IRQ_HANDLER(void)
{
uint32_t g_Adc16ConversionValue = 0;
static bool low_voltage = false;
g_Adc16ConversionValue = ADC16_GetChannelConversionValue(VBUS_ADC, 0);
if (g_Adc16ConversionValue < ADC_THRSHLD && !low_voltage)
{
low_voltage = true;
}
else if (g_Adc16ConversionValue >= ADC_THRSHLD)
{
low_voltage = false;
}
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void VBUS_ADC_init(void)
{
NVIC_SetPriority(VBUS_ADC_IRQ, 4);
/* Enable ADC1 IRQ */
EnableIRQ(VBUS_ADC_IRQ);
adc16_config_t ADC16_config = {
.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref,
.clockSource = kADC16_ClockSourceAsynchronousClock, /* ADC clock freq is (5.2Mhz / 8). see ADC electrical characteristics */
/* calculated time of conversion is 3.8us. Refer pg 881 of RM */
.enableAsynchronousClock = true,
.clockDivider = kADC16_ClockDivider8,
.resolution = kADC16_ResolutionSE12Bit,
.longSampleMode = kADC16_LongSampleDisabled,
.enableHighSpeed = false,
.enableLowPower = false,
.enableContinuousConversion = true};
adc16_hardware_compare_config_t compare_config = { .hardwareCompareMode = kADC16_HardwareCompareMode0,
.value1 = (int) (VBUS_THRESH * SE_12BIT / VREF_BRD)
};
/* Initialize ADC16 converter */
ADC16_Init(VBUS_ADC, &ADC16_config);
ADC16_EnableHardwareTrigger(VBUS_ADC, false);
/* Setting hardware compare value */
ADC16_SetHardwareAverage(VBUS_ADC, kADC16_HardwareAverageCount8);
/* Auto-calibrate the ADC value */
ADC16_DoAutoCalibration(VBUS_ADC);
ADC16_SetHardwareCompareConfig(VBUS_ADC, &compare_config);
/* Set channel and enable generation of interrupt */
ADC16_SetChannelConfig(VBUS_ADC, 0, &VBUS_ADC_channelsConfig);
//ADC16_SetHardwareAverage(VBUS_ADC, kADC16_HardwareAverageCount32);
return;
}
Here, I am not able to get interrupt when ADC voltage is < value1.
Hi
If the ADC interrupt was not triggered it is possible the last ADC conversion was above your threshold value.
You could try to comment the ADC16_SetHardwareCompareConfig call in your code and check if the ADC interrupt is triggered as expected.
I tested on my FDRM-K64F, using the ADC0, after modifying the interrupt example to have a continuous conversion, and adding a threshold value of 1000, I was able to enter to the interrupt when the ADC conversion was below the threshold.
If required I can share my configurations , but they almost similar to yours. In my case I called the ADC16_SetHardwareCompareConfig after initializing the ADC and setting the ADC trigger to false.
I am curious regarding your custom board configuration. I assume that you can read properly the ADC even using a pulling example, right?
Regards, Diego
Hi,
Sorry one of my configuration is missing in the post that is as below,
adc16_channel_config_t VBUS_ADC_channelsConfig = {
.channelNumber = 16U,
.enableDifferentialConversion = false,
.enableInterruptOnConversionCompleted = false};
So I would like to get interrupt only when ADC converted value is less than value1 as per compare_config.
I would not like to get interrupt on every conversion.
Thank you for your reply
Could you try to change the:
enableInterruptOnConversionCompleted = false
to
enableInterruptOnConversionCompleted = true.
it seems that you will need to enable the channel interrupt also.
Regards,
Diego
Hi,
With the suggested change I am able to get interrupt. Thank you.
In my system once voltage goes down, it will never comes up and so I am getting interrupt continuously.
Is there any provision to get interrupt only one time?
Since in your configuration you had a continuous conversion mode enabled for the ADC. The ADC interrupts will be triggered periodically when the conversion falls into the compare range. I am afraid that there is no provision to have only one interrupt with that setting.
In this case, you will need to analyze how often the signal you are checking changes in your system. If the signal changes very slowly, (compared to ADC sample rate or anything else in your system ) I am thinking that you may disable the ADC interrupts after one was triggered, then enable the ADC interrupts again in a certain time . Or configure the ADC in a non-continuous conversion mode, then trigger a single conversion every once in a while , if the signals is in the compare range, the ADC will trigger a single interrupt.
My apologies for the delayed reply,
Regards,
Diego.