1 /*
2 * @brief LPC15xx ADC example
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2014
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 #define TICKRATE_HZ (100) /* 100 SysTicks per second */
40
41 #if defined(BOARD_NXP_LPCXPRESSO_1549)
42 /* ADC is connected to the pot on LPCXPresso base boards */
43 #define BOARD_ADC_CH 1
44 /* ADC Clock set to 36MHz for this board as SysClk is 72MHz and max ADC clock is 50MHz*/
45 #define ADC_CLOCK_RATE (36000000)
46
47 #else
48 #warning "Using ADC channel 8 for this example, please select for your board. Also setup ADC Clock"
49 #define BOARD_ADC_CH 8
50 #endif
51
52 /* RAM Block Sizes for ADC ROM API */
53 #define RAMBLOCK_H 60
54 #define BUFFER_SIZE 12
55
56 static volatile int ticks;
57 static bool sequence0Complete, sequence1Complete, threshold1Crossed;
58
59 static uint32_t size_in_bytes;
60 static const ADCD_API_T *pAdcApi; /* define pointer to type API function addr table */
61 static ADC_HANDLE_T adc_handle[2]; /* handle to ADC API */
62 static ADC_PARAM_T param[2]; /* Param Structure for ADC ROM API */
63 static ADC_CONFIG_T adc_cfg[2]; /* Config Structure for ADC ROM API */
64 static uint32_t start_of_ram_block[2][RAMBLOCK_H]; /* RAM Block */
65 static uint32_t adc_buffer[2][BUFFER_SIZE]; /* Buffer for ADC data */
66 static ErrorCode_t err_code;
67
68 /*****************************************************************************
69 * Public types/enumerations/variables
70 ****************************************************************************/
71
72 /*****************************************************************************
73 * Private functions
74 ****************************************************************************/
75
showValudeADC(LPC_ADC_T * pADC)76 void showValudeADC(LPC_ADC_T *pADC)
77 {
78 uint32_t rawSample;
79
80 if (pADC == LPC_ADC0) {
81 rawSample = adc_buffer[0][0];
82 DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", 0, 0, rawSample, 0);
83 }
84 else {
85 rawSample = adc_buffer[1][BOARD_ADC_CH];
86 DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", 1, BOARD_ADC_CH, rawSample, BOARD_ADC_CH);
87 }
88 }
89
adc_seq0_callback(ADC_HANDLE_T handle)90 void adc_seq0_callback(ADC_HANDLE_T handle)
91 {
92 ADC_DRIVER_T *driver = (ADC_DRIVER_T *) handle;
93
94 if ((ErrorCode_t) driver->error_code == LPC_OK) {
95 if (driver->comp_flags & 0x01) {
96 sequence0Complete = true;
97 }
98 }
99 }
100
adc_seq1_callback(ADC_HANDLE_T handle)101 void adc_seq1_callback(ADC_HANDLE_T handle)
102 {
103 ADC_DRIVER_T *driver = (ADC_DRIVER_T *) handle;
104
105 if ((ErrorCode_t) driver->error_code == LPC_OK) {
106 if (driver->comp_flags & (1 << BOARD_ADC_CH)) {
107 sequence1Complete = true;
108 }
109 }
110 }
111
adc_thcmp_callback(ErrorCode_t error_code,uint32_t num_channel)112 void adc_thcmp_callback(ErrorCode_t error_code, uint32_t num_channel)
113 {
114 if (error_code == LPC_OK) {
115 if (num_channel & (1 << BOARD_ADC_CH)) {
116 threshold1Crossed = true;
117 }
118 }
119 }
120
121 /*****************************************************************************
122 * Public functions
123 ****************************************************************************/
124
125 /**
126 * @brief Handle interrupt from SysTick timer
127 * @return Nothing
128 */
SysTick_Handler(void)129 void SysTick_Handler(void)
130 {
131 static uint32_t count;
132
133 /* Every 1/2 second */
134 count++;
135 if (count >= (TICKRATE_HZ / 2)) {
136 count = 0;
137 /* ADC0 Param for SEQA read */
138 param[0].buffer = (uint32_t *) adc_buffer[0];
139 param[0].driver_mode = 0x01;/* Interrupt Mode */
140 param[0].seqa_hwtrig = 0;
141 param[0].adc_cfg = &adc_cfg[0]; /* ADC0 Config */
142 param[0].comp_flags = 0;
143 param[0].seqa_callback_pt = adc_seq0_callback; /* Call back for SeqA Interrupt */
144 /* ADC1 Param for SEQA read */
145 param[1].buffer = (uint32_t *) adc_buffer[1];
146 param[1].driver_mode = 0x01;/* Interrupt Mode */
147 param[1].seqa_hwtrig = 0;
148 param[1].adc_cfg = &adc_cfg[1]; /* ADC1 Config */
149 param[1].comp_flags = 0;
150 param[1].seqa_callback_pt = adc_seq1_callback; /* Call back for SeqA Interrupt */
151 param[1].thcmp_callback_pt = adc_thcmp_callback;/* Call back for Threshold Compare Interrupt */
152 err_code = LPC_OK;
153 err_code |= (ErrorCode_t) pAdcApi->adc_seqa_read(adc_handle[0], ¶m[0]);
154 err_code |= (ErrorCode_t) pAdcApi->adc_seqa_read(adc_handle[1], ¶m[1]);
155 if (err_code != LPC_OK) {
156 Board_LED_Toggle(0);
157 }
158 }
159 }
160
161 /**
162 * @brief Handle interrupt from ADC0 sequencer A
163 * @return Nothing
164 */
ADC0A_IRQHandler(void)165 void ADC0A_IRQHandler(void)
166 {
167 pAdcApi->adc_seqa_isr(adc_handle[0]);
168 }
169
170 /**
171 * @brief Handle interrupt from ADC1 sequencer A
172 * @return Nothing
173 */
ADC1A_IRQHandler(void)174 void ADC1A_IRQHandler(void)
175 {
176 pAdcApi->adc_seqa_isr(adc_handle[1]);
177 }
178
179 /**
180 * @brief Handle threshold interrupt from ADC1
181 * @return Nothing
182 */
ADC1_THCMP_IRQHandler(void)183 void ADC1_THCMP_IRQHandler(void)
184 {
185 pAdcApi->adc_thcmp_isr(adc_handle[1]);
186 }
187
188 /**
189 * @brief main routine for ADC example
190 * @return Function should not exit
191 */
main(void)192 int main(void)
193 {
194 SystemCoreClockUpdate();
195 Board_Init();
196 DEBUGSTR("ADC ROM sequencer demo\r\n");
197
198 /* Power up, enable clock and reset ADC0 */
199 Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC0_PD);
200 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC0);
201 Chip_SYSCTL_PeriphReset(RESET_ADC0);
202 /* Power up, enable clock and reset ADC1 */
203 Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC1_PD);
204 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC1);
205 Chip_SYSCTL_PeriphReset(RESET_ADC1);
206 /* Power up the internal temperature sensor */
207 Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
208
209 #if defined(BOARD_NXP_LPCXPRESSO_1549)
210 /* Disables pullups/pulldowns and disable digital mode */
211 Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 9, (IOCON_MODE_INACT | IOCON_ADMODE_EN));
212
213 /* Assign ADC1_1 to PIO0_9 via SWM (fixed pin) */
214 Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_1);
215
216 #else
217 #warning "No ADC setup for this example"
218 #endif
219 /* Initialize ROM API base address for ADC */
220 pAdcApi = LPC_ADCD_API;
221 size_in_bytes = pAdcApi->adc_get_mem_size();
222 if (size_in_bytes / 4 > RAMBLOCK_H) {
223 /* Adjust RAMBLOCK size in this case */
224 return 1;
225 }
226 /* ADC Handle Setup*/
227 adc_handle[0] = pAdcApi->adc_setup(LPC_ADC0_BASE, (uint8_t *) start_of_ram_block[0]);
228 adc_handle[1] = pAdcApi->adc_setup(LPC_ADC1_BASE, (uint8_t *) start_of_ram_block[1]);
229 /* ADC0 Config */
230 adc_cfg[0].system_clock = SystemCoreClock; /* System clock */
231 adc_cfg[0].adc_clock = 500000; /* ADC clock set to 500KHz for calibration*/
232 /* ADC1 Config */
233 adc_cfg[1].system_clock = SystemCoreClock; /* System clock */
234 adc_cfg[1].adc_clock = 500000; /* ADC clock set to 500KHz for calibration*/
235 pAdcApi->adc_calibration(adc_handle[0], &adc_cfg[0]);
236 pAdcApi->adc_calibration(adc_handle[1], &adc_cfg[1]);
237
238 /* ADC0 Config for Init */
239 adc_cfg[0].system_clock = SystemCoreClock; /* System clock */
240 adc_cfg[0].adc_clock = ADC_CLOCK_RATE; /* ADC clock */
241 adc_cfg[0].async_mode = 0; /* Synchronous mode */
242 adc_cfg[0].tenbit_mode = 0; /* 12 Bit ADC mode */
243 adc_cfg[0].lpwr_mode = 0; /* Disable low power mode */
244 adc_cfg[0].input_sel = ADC_INSEL_TS;
245 adc_cfg[0].seqa_ctrl = (ADC_SEQ_CTRL_CHANSEL(0) | ADC_SEQ_CTRL_MODE_EOS);
246 adc_cfg[0].channel_num = 1; /* Channel number is one higher than the maximum channel number used */
247 /* ADC1 Config for Init */
248 adc_cfg[1].system_clock = SystemCoreClock; /* System clock */
249 adc_cfg[1].adc_clock = ADC_CLOCK_RATE; /* ADC clock */
250 adc_cfg[1].async_mode = 0; /* Synchronous mode */
251 adc_cfg[1].tenbit_mode = 0; /* 12 Bit ADC mode */
252 adc_cfg[1].lpwr_mode = 0; /* Disable low power mode */
253 adc_cfg[1].seqa_ctrl = (ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS);
254 adc_cfg[1].thrsel = 0;
255 adc_cfg[1].thr0_low = ((1 * 0xFFF) / 4) << 4;
256 adc_cfg[1].thr0_high = ((3 * 0xFFF) / 4) << 4;
257 adc_cfg[1].thcmp_en = ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, BOARD_ADC_CH);
258 adc_cfg[1].channel_num = BOARD_ADC_CH + 1; /* Channel number is one higher than the maximum channel number used */
259 pAdcApi->adc_init(adc_handle[0], &adc_cfg[0]);
260 pAdcApi->adc_init(adc_handle[1], &adc_cfg[1]);
261
262 /* When using ADC ROM API's lower the priority of ADC Sequence completion interrupt when compared to the threshold interrupt*/
263 NVIC_SetPriority(ADC1_SEQA_IRQn, 1);
264 /* Enable related ADC NVIC interrupts */
265 NVIC_EnableIRQ(ADC0_SEQA_IRQn);
266 NVIC_EnableIRQ(ADC1_SEQA_IRQn);
267 NVIC_EnableIRQ(ADC1_THCMP);
268
269 /* This example uses the periodic sysTick to manually trigger the ADC,
270 but a periodic timer can be used in a match configuration to start
271 an ADC sequence without software intervention. */
272 SysTick_Config(Chip_Clock_GetSysTickClockRate() / TICKRATE_HZ);
273
274 /* Endless loop */
275 while (1) {
276 /* Sleep until something happens */
277 __WFI();
278
279 if (threshold1Crossed) {
280 threshold1Crossed = false;
281 DEBUGSTR("********ADC1 threshold event********\r\n");
282 }
283
284 /* Is a conversion sequence complete? */
285 if (sequence0Complete) {
286 sequence0Complete = false;
287 showValudeADC(LPC_ADC0);
288 }
289 if (sequence1Complete) {
290 sequence1Complete = false;
291 showValudeADC(LPC_ADC1);
292 }
293 }
294
295 /* Should not run to here */
296 return 0;
297 }
298