1 /*
2 * @brief LPC11u6x 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 bool tempSequenceComplete;
40 static volatile int tempSampleIdx;
41
42 /* Temperature sample ADC read buffer - only index 9 is used for the valid
43 temperature sample. */
44 #define TEMPSAMPLES 10
45 static uint32_t temp[TEMPSAMPLES];
46
47 #define TICKRATE_HZ (100) /* 100 ticks per second */
48
49 /*****************************************************************************
50 * Public types/enumerations/variables
51 ****************************************************************************/
52
53 /*****************************************************************************
54 * Private functions
55 ****************************************************************************/
56
57 /* This starts an ADC temperature sampling sequence using the recommended
58 burst method. It bursts 10 temperature sensor samples via the ADC and
59 then stops the ADC sequencer. The single sequence (non-burst) mode can
60 also be used for ADC temperature sensor read. */
tempStartCycle(void)61 static void tempStartCycle(void)
62 {
63 tempSampleIdx = 0;
64 tempSequenceComplete = false;
65
66 /* Enable burst mode */
67 Chip_ADC_StartBurstSequencer(LPC_ADC0, ADC_SEQA_IDX);
68 }
69
70 /* Used to indicate when a temperature cycle is complete and the sample
71 is ready */
tempCycleComplete(void)72 static bool tempCycleComplete(void)
73 {
74 return tempSequenceComplete;
75 }
76
77 /* Returns the last temperature sample only. Only valid if tempCycleComplete()
78 returns true */
tempGetSample(void)79 static uint32_t tempGetSample(void)
80 {
81 tempSequenceComplete = false;
82 return temp[TEMPSAMPLES - 1];
83 }
84
85 /*****************************************************************************
86 * Public functions
87 ****************************************************************************/
88
89 /**
90 * @brief Handle interrupt from SysTick timer
91 * @return Nothing
92 */
SysTick_Handler(void)93 void SysTick_Handler(void)
94 {
95 static uint32_t count;
96
97 /* Every 1/2 second */
98 count++;
99 if (count >= (TICKRATE_HZ / 1)) {
100 count = 0;
101
102 /* Restart temperature cycle */
103 tempStartCycle();
104 }
105 }
106
107 /**
108 * @brief Handle interrupt from ADC sequencer A
109 * @return Nothing
110 */
ADC0A_IRQHandler(void)111 void ADC0A_IRQHandler(void)
112 {
113 uint32_t pending;
114
115 /* Get pending interrupts */
116 pending = Chip_ADC_GetFlags(LPC_ADC0);
117
118 /* Sequence A completion interrupt */
119 if (pending & ADC_FLAGS_SEQA_INT_MASK) {
120 if (tempSampleIdx < TEMPSAMPLES) {
121 /* Save sample */
122 temp[tempSampleIdx] = Chip_ADC_GetDataReg(LPC_ADC0, 0);
123 tempSampleIdx++;
124
125 if (tempSampleIdx >= TEMPSAMPLES) {
126 Chip_ADC_StopBurstSequencer(LPC_ADC0, ADC_SEQA_IDX);
127 tempSequenceComplete = true;
128 }
129 }
130 }
131
132 /* Clear any pending interrupts */
133 Chip_ADC_ClearFlags(LPC_ADC0, pending);
134 }
135
136 /**
137 * @brief main routine for ADC example
138 * @return Function should not exit
139 */
main(void)140 int main(void)
141 {
142 uint32_t rawSample;
143
144 SystemCoreClockUpdate();
145 Board_Init();
146 DEBUGSTR("Temperature sensor demo\r\n");
147
148 /* Setup ADC for 12-bit mode and normal power */
149 Chip_ADC_Init(LPC_ADC0, 0);
150
151 /* Setup ADC clock rate */
152 Chip_ADC_SetClockRate(LPC_ADC0, 250000);
153
154 /* For ADC0, select temperature sensor for channel 0 on ADC0 */
155 Chip_ADC_SetADC0Input(LPC_ADC0, ADC_INSEL_TS);
156
157 /* Setup a sequencer to do the following:
158 Perform ADC conversion of ADC channels 0 with EOS interrupt */
159 Chip_ADC_SetupSequencer(LPC_ADC0, ADC_SEQA_IDX, (ADC_SEQ_CTRL_CHANSEL(0) |
160 ADC_SEQ_CTRL_MODE_EOS));
161
162 /* Power up the internal temperature sensor - this also selects the
163 temperature sensor as the input for the ADC0 input */
164 Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
165
166 /* Use higher voltage trim */
167 Chip_ADC_SetTrim(LPC_ADC0, ADC_TRIM_VRANGE_HIGHV);
168
169 /* Need to do a calibration after initialization and trim */
170 Chip_ADC_StartCalibration(LPC_ADC0);
171 while (!(Chip_ADC_IsCalibrationDone(LPC_ADC0))) {}
172
173 /* Clear all pending interrupts */
174 Chip_ADC_ClearFlags(LPC_ADC0, Chip_ADC_GetFlags(LPC_ADC0));
175
176 /* Enable ADC sequence A completion interrupt */
177 Chip_ADC_EnableInt(LPC_ADC0, ADC_INTEN_SEQA_ENABLE);
178
179 /* Enable ADC NVIC interrupt */
180 NVIC_EnableIRQ(ADC0_SEQA_IRQn);
181
182 /* Enable sequencer */
183 Chip_ADC_EnableSequencer(LPC_ADC0, ADC_SEQA_IDX);
184
185 /* This example uses the periodic sysTick to manually trigger
186 the ADC burst cycle */
187 SysTick_Config(SystemCoreClock / TICKRATE_HZ);
188
189 /* Endless loop */
190 while (1) {
191 /* Sleep until something happens */
192 __WFI();
193
194 /* Is a conversion sequence complete? */
195 if (tempCycleComplete()) {
196 rawSample = tempGetSample();
197 if ((rawSample & ADC_SEQ_GDAT_DATAVALID) != 0) {
198 DEBUGOUT("Sampled temp value = 0x%04x (first = 0x%04x)\r", ADC_DR_RESULT(rawSample),
199 ADC_DR_RESULT(temp[0]));
200 }
201 else {
202 DEBUGSTR("\r\nInvalid sample read\r\n");
203 }
204 }
205 }
206
207 /* Should not run to here */
208 return 0;
209 }
210