The data that we use for programming a microcontroller normally deals with digital signals. But there are situations where a microcontroller has to deal with inputs from external devices that gives an analog output. In such cases, we can interface the microcontroller with an external device such as an ADC0808 to convert the analog signal to a digital signal. But in more advanced and powerful microcontrollers such as LPC1768, these processes are handled internally rather than externally, using an internal ADC module. In this tutorial, we will learn the basic functionality of the built-in ADC module of the LPC1768 ARM controller. A potentiometer will be used to take the input and the measured value will be processed by the built-in ADC module and the output will be displayed in the serial terminal via UART. More info on UART, refer UART Communication.
#define ADC_CLOCK 1000000 //(SHOULD BE LESS THAN OR EQUAL TO 13MHz) /* These are the pin definitions for the ADC pins defined under PINSELECT1 */ #define AD0_0 14 #define AD0_1 16 #define AD0_2 18 #define AD0_3 20 /* These are the pin definitions for the AD control 32 bit register ADCR */ #define ADCR_SEL0 0 #define ADCR_SEL1 1 #define ADCR_SEL2 2 #define ADCR_SEL3 3 #define ADCR_SEL4 4 #define ADCR_SEL5 5 #define ADCR_SEL6 6 #define ADCR_SEL7 7 #define ADCR_CLKDIV 8 #define ADCR_BURST 16 #define ADCR_PDN 21 #define ADCR_START 24 #define ADCR_EDGE 27 /* These are the pin definitions for the AD result and status*/ #define ADC_OFFSET (1<<4) #define ADC_RESULT 4 #define ADC_DONE (1<<31) #define ADC_OVERRUN (1<<30)
LPC_SC->PCONP |= (1 << 12); // Power up the ADC module LPC_PINCON->PINSEL1 &= ~0x002FC000; /* Funtions as ADC (0-3) pins when 01 is selected resp. under PINSEL1 reg. P0.23 (15,14), P0.24 (17,16), P0.25 (19,18), P0.26 (21,20)*/LPC_PINCON->PINSEL1 |= (0x01 << AD0_0); // We will be using AD0 channel only.
clock = SystemFrequency/4; LPC_ADC->ADCR |= (1 << ADCR_SEL0); // Select channel 0 on ADC0 LPC_ADC->ADCR |= ((clock/ADC_CLOCK - 1) << ADCR_CLKDIV); // CLKDIV = (clock/ADC_CLOCK - 1) LPC_ADC->ADCR |= ((0 << ADCR_BURST) | (1 << ADCR_PDN) | (0 << ADCR_START) | (0 << ADCR_EDGE));
LPC_ADC->ADCR &= 0xFFFFFF00; LPC_ADC->ADCR |= (1 << ADCR_START) | (1 << ADCR_SEL0); //Select AD0 channel and start the conversion process.
do{ DataReg = *(volatile unsigned long *)(LPC_ADC_BASE + ADC_OFFSET + ADC_RESULT * channelNum); }while(!(DataReg & ADC_DONE)); // When ADC_DONE is 1, the conversion is complete.
LPC_ADC->ADCR &= 0xF8FFFFFF; //Stop AD0 conversion process. ADC_Data = (DataReg>>ADC_RESULT)&0xFFF; // The max value for the result will be in the range Vrefp (0xfff) and Vrefn (0x000)
void split(unsigned char s) { unsigned char a[4]; int i=0; while(i<4){ a[i] = s%10; s = s/10; i++; } do { --i; Write_UART_Char(a[i]+48); }while(i); }
This program only serves as a reference to set up the most basic functionality of the ADC module.
Normally, the flag values have to be checked to make the code more efficient.
The converted digital data has been acquired through the ADC module of the LPC1768 controller. This data is displayed on the serial monitor using the UART module of the LPC1768.
The code based on this tutorial is available in the Code Library under the section ARM.