LPC54102 ADC triggering threshold interrupt

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

LPC54102 ADC triggering threshold interrupt

Jump to solution
2,091 Views
curryhuang3627
Contributor I

First I want to start by apologizing that I'm a newbie. I'm still learning from example codes and all that stuff. I have already watched all the ADC-related articles on the forum but there don't seem to have anyone having this problem. So, I'm trying to use ADC combined with SCTimer. The idea is that the SCTimer will generate a 100% duty cycle PWM while ADC reading the value. Once the ADC value reached the high threshold (I didn't set the low threshold), it will trigger threshold interrupt in which I set the SCTimer to change the duty cycle to 30%.

After multiple test runs, the ADC could successfully read the value, and I could see from the console that the "Threshold Range" shift from 0x0 to 0x2, which means the value is higher than the high threshold. The PWM, however, still stayed the same at 100% duty cycle, and there was no ADC threshold event shown on the console as well.

I then used ADC example to test the threshold interrupt, adding simple LED toggle in the threshold interrupt handler as below. The outcome was always the same. The LED didn't react, and there was no ADC threshold event shown on the console though the threshold range showed that the value already passed the threshold.

#include "board.h"
#include <stdio.h>

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

static volatile int ticks;
static bool sequenceComplete, thresholdCrossed;

#define TICKRATE_HZ (100)	/* 100 ticks per second */

#if defined(BOARD_NXP_LPCXPRESSO_54102)
#define BOARD_ADC_CH 8

#else
#warning "Using ADC channel 8 for this example, please select for your board"
#define BOARD_ADC_CH 8
#endif

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief	Handle interrupt from SysTick timer
 * @return	Nothing
 */
void SysTick_Handler(void)
{
	static uint32_t count;

	/* Every 1/2 second */
	count++;
	if (count >= (TICKRATE_HZ / 2)) {
		count = 0;

		/* Manual start for ADC conversion sequence A */
		Chip_ADC_StartSequencer(LPC_ADC, ADC_SEQA_IDX);
	}
}

/* SEQ-A interrupt handler */
void ADC_SEQA_IRQHandler(void)
{
	uint32_t pending;

	/* Get pending interrupts */
	pending = Chip_ADC_GetFlags(LPC_ADC);

	/* Sequence A completion interrupt */
	if (pending & ADC_FLAGS_SEQA_INT_MASK) {
		sequenceComplete = true;
	}

	/* Clear any pending interrupts */
	Chip_ADC_ClearFlags(LPC_ADC, ADC_FLAGS_SEQA_INT_MASK);
}

/* ADC threashold interrupt handler */
void ADC_THCMP_IRQHandler(void)
{
	uint32_t pending;

	/* Get pending interrupts */
	pending = Chip_ADC_GetFlags(LPC_ADC);

	/* Threshold crossing interrupt on ADC input channel */
	if (pending & ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH)) {
		thresholdCrossed = true;
		Board_LED_Toggle(0);
	}

	/* Clear any pending interrupts */
	Chip_ADC_ClearFlags(LPC_ADC, ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH));
}

/* main function (C entry point) */
int main(void)
{
	int loop = 1;	/* Prevents unreachable statement warning */
	uint32_t rawSample;
	int j;

	SystemCoreClockUpdate();
	Board_Init();
	DEBUGSTR("ADC sequencer demo\r\n");

	//Set the state of a board LED to on or off
	Board_LED_Set(0,false);

	/* Setup ADC for 12-bit mode and normal power */
	Chip_ADC_Init(LPC_ADC, (ADC_CR_RESOL(3) | ADC_CR_TSAMP(ADC_TSAMP_7CLK5)));

	/* FIXME: Enable ADC, should be at least 10mS after ADC is powered up */
	LPC_ADC->STARTUP = 0x1;
	LPC_ADC->STARTUP = 0x3;	/* Dummy calibration */

	/* Need to do a calibration after initialization and trim */
	Chip_ADC_Calibration(LPC_ADC);

	/* Setup for maximum ADC clock rate using sycnchronous clocking */
	Chip_ADC_SetClockRate(LPC_ADC, ADC_MAX_SAMPLE_RATE);

	/* Optionally, you can setup the ADC to use asycnchronous clocking mode.
	   To enable this, mode use 'LPC_ADC->CTRL |= ADC_CR_ASYNMODE;'.
	   In asycnchronous clocking mode mode, the following functions are
	   used to set and determine ADC rates:
	   Chip_Clock_SetADCASYNCSource();
	   Chip_Clock_SetADCASYNCClockDiv();
	   Chip_Clock_GetADCASYNCRate();
	   clkRate = Chip_Clock_GetADCASYNCRate() / Chip_Clock_GetADCASYNCClockDiv; */

	/* Setup sequencer A for ADC channel 0, EOS interrupt */
#if defined(BOARD_NXP_LPCXPRESSO_54102)
	/* Setup a sequencer to do the following:
	   Perform ADC conversion of ADC channels 0 and 8 only */
	Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX, (ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) |
													ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS));

	/* ADC input 8 is on PIO0_12 mapped to FUNC2 */
	Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 12, (IOCON_FUNC3 | IOCON_MODE_INACT |
											IOCON_ANALOG_EN));
#endif

	/* Setup threshold 0 low and high values to about 25% and 75% of max */
	//Chip_ADC_SetThrLowValue(LPC_ADC, 0, 0xf50);	// ((1 * 0xFFF) / 4));
	Chip_ADC_SetThrHighValue(LPC_ADC, 0, 0xf70);// ((3 * 0xFFF) / 4)); 

	/* Clear all pending interrupts */
	Chip_ADC_ClearFlags(LPC_ADC, Chip_ADC_GetFlags(LPC_ADC));

	/* Enable ADC overrun and sequence A completion interrupts */
	Chip_ADC_EnableInt(LPC_ADC, (ADC_INTEN_SEQA_ENABLE | ADC_INTEN_OVRRUN_ENABLE));

	/* Use threshold 0 for ADC channel and enable threshold interrupt mode for
	   channel as crossing */
	Chip_ADC_SelectTH0Channels(LPC_ADC, ADC_THRSEL_CHAN_SEL_THR1(BOARD_ADC_CH));
	Chip_ADC_SetThresholdInt(LPC_ADC, BOARD_ADC_CH, ADC_INTEN_THCMP_CROSSING);

	/* Enable ADC NVIC interrupt */
	NVIC_EnableIRQ(ADC_SEQA_IRQn);
	NVIC_EnableIRQ(ADC_THCMP_IRQn);

	/* Enable sequencer */
	Chip_ADC_EnableSequencer(LPC_ADC, ADC_SEQA_IDX);
        
        SysTick_Config(SystemCoreClock / TICKRATE_HZ);

	/* Endless loop */
	while (loop) {
		/* Sleep until something happens */
		__WFI();

		if (thresholdCrossed) {
			thresholdCrossed = false;
			DEBUGSTR("********ADC threshold event********\r\n");
		}

		/* Is a conversion sequence complete? */
		if (sequenceComplete) {
			sequenceComplete = false;

			/* Get raw sample data for channels 0-11 */
			for (j = 0; j < 12; j++) {
				rawSample = Chip_ADC_GetDataReg(LPC_ADC, j);

				/* Show some ADC data */
				if ((rawSample & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) != 0) {
					DEBUGOUT("Sample value = 0x%x (Data sample %d)\r\n", ADC_DR_RESULT(rawSample), j);
					DEBUGOUT("Threshold range = 0x%x\r\n", ADC_DR_THCMPRANGE(rawSample));
					DEBUGOUT("Threshold cross = 0x%x\r\n", ADC_DR_THCMPCROSS(rawSample));
				}
			}

			DEBUGOUT("Overrun    = %d\r\n", ((rawSample & ADC_DR_OVERRUN) != 0));
			DEBUGOUT("Data valid = %d\r\n", ((rawSample & ADC_SEQ_GDAT_DATAVALID) != 0));
			DEBUGSTR("\r\n");
		}
	}

	/* Should not run to here */
	return 0;
}

 Thanks

0 Kudos
Reply
1 Solution
2,062 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello curryhuang3627,

After I checked your question and code, I think you need configure threshold comparison interrupt to 

outside threshold, not crossing threshold:

 

5555.jpg5555.jpg

 

 

Regards,

Alice

View solution in original post

0 Kudos
Reply
4 Replies
2,063 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello curryhuang3627,

After I checked your question and code, I think you need configure threshold comparison interrupt to 

outside threshold, not crossing threshold:

 

5555.jpg5555.jpg

 

 

Regards,

Alice

0 Kudos
Reply
2,052 Views
curryhuang3627
Contributor I

Thanks for the quick reply.

I think "outside threshold" might be the solution to my problem but I'm still having a hard time understanding the difference between the two. To me, I feel like they were saying the same thing.

How do you define "threshold crossing" and what do you expect to see if you configure this register? 

sorry to bother you.

0 Kudos
Reply
2,046 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello ,

In my opinion, "crossing threshold " option means when ADC data just equal to the threadold.

 

Regards,

Alice

0 Kudos
Reply
2,032 Views
curryhuang3627
Contributor I

Thanks for the timely help.

I owe you a big one.

0 Kudos
Reply