1 /*
2 * @brief LPC15xx ADC example
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2013
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "board.h"
33 #include <stdio.h>
34
35 /*****************************************************************************
36 * Private types/enumerations/variables
37 ****************************************************************************/
38
39 static volatile int ticks;
40 static bool sequence0Complete, sequence1Complete, threshold1Crossed;
41
42 #define TICKRATE_HZ (100) /* 100 ticks per second */
43
44 #if defined(BOARD_NXP_LPCXPRESSO_1549)
45 /* ADC is connected to the pot on LPCXPresso base boards */
46 #define BOARD_ADC_CH 1
47
48 #else
49 #warning "Using ADC channel 8 for this example, please select for your board"
50 #define BOARD_ADC_CH 8
51 #endif
52
53 /*****************************************************************************
54 * Public types/enumerations/variables
55 ****************************************************************************/
56
57 /*****************************************************************************
58 * Private functions
59 ****************************************************************************/
60
showValudeADC(LPC_ADC_T * pADC)61 void showValudeADC(LPC_ADC_T *pADC)
62 {
63 int index, j;
64 uint32_t rawSample;
65
66 if (pADC == LPC_ADC0) {
67 index = 0;
68 }
69 else {
70 index = 1;
71 }
72
73 /* Get raw sample data for channels 0-11 */
74 for (j = 0; j < 12; j++) {
75 rawSample = Chip_ADC_GetDataReg(pADC, j);
76
77 /* Show some ADC data */
78 if ((rawSample & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) != 0) {
79 DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", index, j,
80 ADC_DR_RESULT(rawSample), j);
81
82 /* Threshold events are only on ADC1 */
83 if (index == 1) {
84 DEBUGOUT("ADC%d_%d: Threshold range = 0x%x\r\n", index, j,
85 ADC_DR_THCMPRANGE(rawSample));
86 DEBUGOUT("ADC%d_%d: Threshold cross = 0x%x\r\n", index, j,
87 ADC_DR_THCMPCROSS(rawSample));
88 }
89 }
90 }
91 }
92
93 /*****************************************************************************
94 * Public functions
95 ****************************************************************************/
96
97 /**
98 * @brief Handle interrupt from SysTick timer
99 * @return Nothing
100 */
SysTick_Handler(void)101 void SysTick_Handler(void)
102 {
103 static uint32_t count;
104
105 /* Every 1/2 second */
106 count++;
107 if (count >= (TICKRATE_HZ / 2)) {
108 count = 0;
109
110 /* Manual start for ADC1 conversion sequence A */
111 Chip_ADC_StartSequencer(LPC_ADC0, ADC_SEQA_IDX);
112 Chip_ADC_StartSequencer(LPC_ADC1, ADC_SEQA_IDX);
113 }
114 }
115
116 /**
117 * @brief Handle interrupt from ADC0 sequencer A
118 * @return Nothing
119 */
ADC0A_IRQHandler(void)120 void ADC0A_IRQHandler(void)
121 {
122 uint32_t pending;
123
124 /* Get pending interrupts */
125 pending = Chip_ADC_GetFlags(LPC_ADC0);
126
127 /* Sequence A completion interrupt */
128 if (pending & ADC_FLAGS_SEQA_INT_MASK) {
129 sequence0Complete = true;
130 }
131
132 /* Clear any pending interrupts */
133 Chip_ADC_ClearFlags(LPC_ADC0, pending);
134 }
135
136 /**
137 * @brief Handle interrupt from ADC1 sequencer A
138 * @return Nothing
139 */
ADC1A_IRQHandler(void)140 void ADC1A_IRQHandler(void)
141 {
142 uint32_t pending;
143
144 /* Get pending interrupts */
145 pending = Chip_ADC_GetFlags(LPC_ADC1);
146
147 /* Sequence A completion interrupt */
148 if (pending & ADC_FLAGS_SEQA_INT_MASK) {
149 sequence1Complete = true;
150 }
151
152 /* Clear Sequence A completion interrupt */
153 Chip_ADC_ClearFlags(LPC_ADC1, ADC_FLAGS_SEQA_INT_MASK);
154 }
155
156 /**
157 * @brief Handle threshold interrupt from ADC1
158 * @return Nothing
159 */
ADC1_THCMP_IRQHandler(void)160 void ADC1_THCMP_IRQHandler(void)
161 {
162 uint32_t pending;
163
164 /* Get pending interrupts */
165 pending = Chip_ADC_GetFlags(LPC_ADC1);
166
167 /* Threshold crossing interrupt on ADC input channel */
168 if (pending & ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH)) {
169 threshold1Crossed = true;
170 }
171
172 /* Clear threshold interrupt */
173 Chip_ADC_ClearFlags(LPC_ADC1, ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH));
174 }
175
176 /**
177 * @brief main routine for ADC example
178 * @return Function should not exit
179 */
main(void)180 int main(void)
181 {
182 SystemCoreClockUpdate();
183 Board_Init();
184 DEBUGSTR("ADC sequencer demo\r\n");
185
186 /* Setup ADC for 12-bit mode and normal power */
187 Chip_ADC_Init(LPC_ADC0, 0);
188 Chip_ADC_Init(LPC_ADC1, 0);
189
190 /* Setup for maximum ADC clock rate */
191 Chip_ADC_SetClockRate(LPC_ADC0, ADC_MAX_SAMPLE_RATE);
192 Chip_ADC_SetClockRate(LPC_ADC1, ADC_MAX_SAMPLE_RATE);
193
194 /* For ADC0, seqeucner A will be used without threshold events.
195 It will be triggered manually by the sysTick interrupt and
196 only monitor the internal temperature sensor. */
197 Chip_ADC_SetupSequencer(LPC_ADC0, ADC_SEQA_IDX, (ADC_SEQ_CTRL_CHANSEL(0) |
198 ADC_SEQ_CTRL_MODE_EOS));
199
200 /* Power up the internal temperature sensor */
201 Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
202
203 /* For ADC0, select temperature sensor for channel 0 on ADC0 */
204 Chip_ADC_SetADC0Input(LPC_ADC0, ADC_INSEL_TS);
205
206 #if defined(BOARD_NXP_LPCXPRESSO_1549)
207 /* Use higher voltage trim for both ADCs */
208 Chip_ADC_SetTrim(LPC_ADC0, ADC_TRIM_VRANGE_HIGHV);
209 Chip_ADC_SetTrim(LPC_ADC1, ADC_TRIM_VRANGE_HIGHV);
210
211 /* For ADC1, seqeucner A will be used with threshold events.
212 It will be triggered manually by the sysTick interrupt and
213 only monitors the ADC1 input. */
214 Chip_ADC_SetupSequencer(LPC_ADC1, ADC_SEQA_IDX,
215 (ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS));
216
217 /* Disables pullups/pulldowns and disable digital mode */
218 Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 9, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
219
220 /* Assign ADC1_1 to PIO0_9 via SWM (fixed pin) */
221 Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_1);
222
223 #else
224 #warning "No ADC setup for this example"
225 #endif
226
227 /* Need to do a calibration after initialization and trim */
228 Chip_ADC_StartCalibration(LPC_ADC0);
229 Chip_ADC_StartCalibration(LPC_ADC1);
230 while (!(Chip_ADC_IsCalibrationDone(LPC_ADC0))) {}
231 while (!(Chip_ADC_IsCalibrationDone(LPC_ADC1))) {}
232
233 /* Setup threshold 0 low and high values to about 25% and 75% of max for
234 ADC1 only */
235 Chip_ADC_SetThrLowValue(LPC_ADC1, 0, ((1 * 0xFFF) / 4));
236 Chip_ADC_SetThrHighValue(LPC_ADC1, 0, ((3 * 0xFFF) / 4));
237
238 /* Clear all pending interrupts */
239 Chip_ADC_ClearFlags(LPC_ADC0, Chip_ADC_GetFlags(LPC_ADC0));
240 Chip_ADC_ClearFlags(LPC_ADC1, Chip_ADC_GetFlags(LPC_ADC1));
241
242 /* Enable sequence A completion interrupts for ADC0 */
243 Chip_ADC_EnableInt(LPC_ADC0, ADC_INTEN_SEQA_ENABLE);
244
245 /* Enable sequence A completion and threshold crossing interrupts for ADC1_1 */
246 Chip_ADC_EnableInt(LPC_ADC1, ADC_INTEN_SEQA_ENABLE |
247 ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, BOARD_ADC_CH));
248
249 /* Use threshold 0 for ADC channel and enable threshold interrupt mode for
250 channel as crossing */
251 Chip_ADC_SelectTH0Channels(LPC_ADC1, ADC_THRSEL_CHAN_SEL_THR1(BOARD_ADC_CH));
252 Chip_ADC_SetThresholdInt(LPC_ADC1, BOARD_ADC_CH, ADC_INTEN_THCMP_CROSSING);
253
254 /* Enable related ADC NVIC interrupts */
255 NVIC_EnableIRQ(ADC0_SEQA_IRQn);
256 NVIC_EnableIRQ(ADC1_SEQA_IRQn);
257 NVIC_EnableIRQ(ADC1_THCMP);
258
259 /* Enable sequencers */
260 Chip_ADC_EnableSequencer(LPC_ADC0, ADC_SEQA_IDX);
261 Chip_ADC_EnableSequencer(LPC_ADC1, ADC_SEQA_IDX);
262
263 /* This example uses the periodic sysTick to manually trigger the ADC,
264 but a periodic timer can be used in a match configuration to start
265 an ADC sequence without software intervention. */
266 SysTick_Config(Chip_Clock_GetSysTickClockRate() / TICKRATE_HZ);
267
268 /* Endless loop */
269 while (1) {
270 /* Sleep until something happens */
271 __WFI();
272
273 if (threshold1Crossed) {
274 threshold1Crossed = false;
275 DEBUGSTR("********ADC1 threshold event********\r\n");
276 }
277
278 /* Is a conversion sequence complete? */
279 if (sequence0Complete) {
280 showValudeADC(LPC_ADC0);
281 }
282 if (sequence1Complete) {
283 showValudeADC(LPC_ADC1);
284 }
285 }
286
287 /* Should not run to here */
288 return 0;
289 }
290