 In electronics world there are many varieties of analog sensors in the market that are used to measure temperature, speed, displacement, pressure etc. Analog sensors are used to produce output that are continuously changing over the time. These signals from analog sensors tend to be very small in value from a few micro-volts (uV) to several milli-volts (mV), so some form of amplification is required. For using these analog signals in microcontroller we need to convert analog signal into digital signal as the microcontroller understands and process only digital signals. So most of the microcontroller has an inbuilt important feature called ADC (Analog to Digital convertor). Our microcontroller ARM7-LPC2148 also has an ADC feature.

In this tutorial we will see how to use ADC in ARM7-LPC2148 by supplying a varying voltage to an Analog pin and display it on the 16x2 LCD screen after analog to digital conversion. So let’s start by a short introduction about ADC.

As said earlier ADC stands for Analog to digital conversion and it is used to convert analog values from real world into digital values like 1’s and 0’s. So what are these analog values? These are the ones that we see in our day to day life like temperature, speed, brightness etc. These parameters are measured as analog voltages by respective sensors and then these Analog values are converted into Digital values for microcontrollers.

Let us assume that our ADC range is from 0V to 3.3V and we have a 10-bit ADC this means our input voltage 0-3.3 Volts will be split into 1024 levels of discrete analog values(210 = 1024). Meaning 1024 is the resolution for a 10-bit ADC, similarly for a 8-bit ADC resolution will be 512 (28) and for a 16-bit ADC resolution will be 65,536 (216). LPC2148 has the 10 bit resolution ADC.

With this if the actual input voltage is 0V then the MCU’s ADC will read it as 0 and if it is 3.3V the MCU will read 1024 and if it somewhere in between like 1.65v then the MCU will read 512. We can use the below formulae to calculate the digital value that will be read by the MCU based on the Resolution of the ADC and Operating voltage.

(ADC Resolution / Operating Voltage) = (ADC Digital Value / Actual Voltage Value)

Like for example if reference voltage is 3v: • The LPC2148 contain two analog to digital converters.
• These converters are single 10-bit successive approximation analog to digital converters.
• Therefore, total number of available ADC inputs for LPC2148 is 14.
• It converts input voltage in range of (0 to 3.3V) only. It must not exceed 3.3V the voltage reference. As it will damage the IC and also provide uncertain values.

Some important feature of ADC in LPC2148

• Each converter capable of performing more than 400000 10-bit samples per second.
• Burst conversion mode for single or multiple inputs.
• Optional conversion on transition on input pin or timer match signal.
• Global Start command for both converters.

Also check how to use ADC in other Microcontrollers: Since the ADC input pins are multiplexed with other GPIO pins. We need to enable them by configuring the PINSEL register to select ADC function.

The table below shows pins of ADC and respected ADC channel no in LPC2148. AD0 is channel 0 and AD1 is channel 1

Registers are used in programming for using A/D conversion feature in LPC2148.

Below is a list of registers used in LPC2148 for A/D conversion

1. ADCR: Analog to Digital Control Register

Use: This register is used for configuring the A/D converter in LPC2148

2. ADGDR: Analog to Digital Global Data Register

Use: This register has DONE bit for A/D converter and the RESULT of the conversion is stored here.

3. ADINTERN: Analog to Digital Interrupt Enable Register

Use: This is an Interrupt Enable register.

Use: This register contains the A/D value for the respective channels.

5. ADSTAT: Analog to Digital Status Register.

Use: This register contains the DONE flag for respective ADC channel and also OVERRUN flag for respective ADC channel.

In this tutorial we will be using only ADCR & ADGDR registers only. Let’s see about them in detail

AD0CR & AD1CR for channel 0 and channel 1 respectively. It’s a 32-Bit register. Below table indicates the bit fields for ADCR register.

 31:28 27 26:24 23:22 21 20 19:17 16 15:8 7:0 RESERVED EDGE START RESERVED PDN RESERVED CLKS BURST CLCKDIV SEL

Let’s see about how to configure individual registers

1. SEL: The bits from (0 to 7) are used to select the channel for ADC conversion. One bit is allotted for each channel. For example setting the Bit-0 will make the ADC to sample AD0.1 for conversion. And setting the bit -1 will make AD0.1; similarly setting bit-7 will do the conversion for AD0.7. Important step is we have PINSEL according to the port we are using for example PINSEL0 for PORT0 in PLC2148.

2. CLCKDIV: The bits from (8 to 15) are for Clock Divisor. Here the APB clock (ARM Peripheral Bus clock) is divided by this value plus one to produce the clock required for the A/D converter, which should be less than or equal to 4.5 MHz as we are using successive approximation method in LPC2148.

3. BURST: The bit 16 is used for BURST conversion mode.

Setting 1: The ADC will do the conversion for all the channels that are selected in SEL bits.

Setting 0:  Will disable the BURST conversion mode.

4. CLCKS: The bits from (17 to 19) three bits are used for selecting resolution and the number of clocks for A/D conversion in burst mode as it is continuous A/D conversion mode.

 Value for bits (17 to 19) Bits (Accuracy) No of Clock 000 10 11 001 9 10 010 8 9 011 7 8 100 6 7 101 5 6 110 4 5 111 3 4

5. PDN: The bit 21 is for selecting Power down Mode of ADC in LPC2148.

1. A/D is in PDN mode.
2. A/D is in operational mode

6. START: The bits from (24 to 26) are for START. When the BURST conversion mode is OFF by setting 0, these START bits are useful for when to start the A/D conversion. The START is used for edge controlled conversion also. That is when there is an input in CAP or MAT pin of LPC2148 the A/D starts to convert. Let’s check the below table

 Value for Bits (24 to 26) Pin’s of LPC2148 Function of ADC 000 Used to set ADC in PDN mode No Start 001 Start A/D Conversion 010 CAP0.2/MAT0.2 Start A/D conversion on EDGE selected on pin 27 (Rising or Falling) on CAP/MAT pins of LPC2148 011 CAP0.0/MAT0.0 100 MAT0.1 101 MAT0.3 110 MAT1.0 111 MAT1.1

7. EDGE: The 27th bit is for EDGE is used only when the START bit contains 010-111. It starts conversion when there is CAP or MAT input you can see above table for that.

Setting: 0 - On Falling Edge

1- On Rising Edge

It is a 32-bit register contains the RESULT of A/D conversion and also the DONE bit which indicates that A/D conversion is done. Below table indicates the bit fields for ADGDR register.

 31 30 29:27 26:24 23:16 15:6 5:0 DONE OVERRUN RESERVED CHN RESERVED RESULT RESERVED

1. RESULT: These bits (6 to 15) contains the result of A/D conversion for the selected channel in the ADCR SEL register. The value is read only after the A/D conversion is completed and this is indicated by DONE bit.

EXAMPLE: For a 10-Bit ADC result the value stored varies from (0 to 1023).

2. CHANNEL: These bits 24 to 26 contain the channel number for which the A/D conversion is done. The converted digital value is present in RESULT bit.

EXAMPLE: 000 is for ADC channel 0 and 001 is for ADC channel 1, etc

3. OVERRUN: The 30th bit for OVERRUN is used in BURST mode. When set 1 the previous converted ADC value is overwritten by the newly converted ADC value. When the register is read it clears the OVERRUN bit.

4. DONE: The 31th bit is for DONE bit.

Set 1: When A/D conversion is completed.

We have seen about the important registers that are used in ADC in LPC2148. Now lets start using ADC in ARM7.

### Components Required

Hardware

• ARM7-LPC2148 Microcontroller
• 3.3V voltage regulator IC
• 5V voltage regulator IC
• 10K Potentiometer – 2 Nos
• LED (Any Colour)
• LCD display(16X2)
• 9V battery
• Connecting Wires

Software

• Keil uVision5
• Magic Flash Tool

### Circuit Diagram  The table below shows the circuit connections between LCD & ARM7-LPC2148.

 ARM7-LPC2148 LCD (16x2) P0.4 RS (Register Select) P0.6 E (Enable) P0.12 D4 (Data pin 4) P0.13 D5(Data pin 5) P0.14 D6(Data pin 6) P0.15 D7 (Data pin 7)

IMPORTANT: Here we are using two voltage regulator ICs one for 5V LCD display and another 3.3V for analog input which can be varied by potentiometer.

Connections between 5V Voltage Regulator with LCD & ARM7 Stick

 5V Voltage Regulator IC Pin function LCD & ARM-7 LPC2148 1.Left Pin + Ve from battery 9V Input NC 2.Centre Pin - Ve from battery VSS,R/W,K of LCD GND of ARM7 3.Right Pin Regulated +5V Output VDD,A of LCD +5V of ARM7

Potentiometer with LCD

A potentiometer is used to vary the contrast of LCD display. A pot has three pins, Left pin (1) is connected to +5V and centre (2) to VEE or V0 of LCD module and right pin (3) is connected to GND. We can adjust the contrast by turning the knob.

Connection between LPC2148 & potentiometer with 3.3V voltage regulator

 3.3V Voltage Regulator IC Pin function ARM-7 LPC2148 1.Left Pin - Ve from battery GND pin 2.Centre Pin Regulated +3.3V Output To potentiometer Input and potentiometer’s output to P0.28 3.Right Pin + Ve from battery 9V Input NC

To Program ARM7-LPC2148 we need keil uVision & Flash Magic tool. We are using USB Cable to program ARM7 Stick via micro USB port. We write code using Keil and create a hex file and then the HEX file is flashed to ARM7 stick using Flash Magic. To know more about installing keil uVision and Flash Magic and how to use them follow the link Getting Started With ARM7 LPC2148 Microcontroller and Program it using Keil uVision.

In this tutorial we convert the analog input voltage (0 to 3.3V) into digital value by using ADC in LPC2148 and display the analog voltage on LCD display (16x2). A potentiometer will be used to vary the input analog voltage.

The complete code for using ADC with ARM 7 is given at the end of this tutorial, here we are explaining few parts of it.

1. PINSEL register is used to select the port pin of LPC2148 and the ADC function as analog input.

`PINSEL1 = 0x01000000; // Select P0.28 as AD0.1`

2. Select the clock and bit accuracy for conversion by writing value to the ADxCR (ADC control register).

`AD0CR = 0x00200402; //Sets ADC operation as 10-bits/11 CLK for conversion (000)`

3. Start the conversion by writing the value to START bits in ADxCR.

Here I have written to 24th bit of AD0CR register.

`AD0CR = AD0CR | (1<<24);`

4. Now we to have check the DONE bit (31th) of corresponding ADxDRy (ADC data register) as it changes from 0 to 1. So we use while loop to constantly check if conversion is done on the 31th bit of data register.

`while ( !(AD0DR1 & 0x80000000) );`

5. After done bit is set to 1, conversion is successful, next we read the result from the same ADC data register AD0DR1 and store the value in a variable.

`adcvalue = AD0DR1;`

Next we use a formula to convert the digital value to voltage and store in a variable named voltage.

`voltage = ( (adcvalue/1023.0) * 3.3 );`

5. Following lines are used to display digital values (0 to 1023) after analog to digital conversion.

```adc = adcvalue;

6. Following lines are used to display input analog voltage (0 to 3.3V) after analog to digital conversion and after step 5.

```LCD_SEND(0xC0);
sprintf(voltvalue, "Voltage=%.2f V  ", voltage);
LCD_DISPLAY(voltvalue);                //Display (input analog voltage)```

7. Now we have to display the input voltage and digital values on the LCD display. Before that we have to initialize the LCD display and use appropriate commands for sending message to display.

Below code is used to Initialize the LCD

```void LCD_INITILIZE(void)          //Function to get ready the LCD
{
IO0DIR = 0x0000FFF0; //Sets pin P0.12,P0.13,P0.14,P0.15,P0.4,P0.6 as OUTPUT
delay_ms(20);
LCD_SEND(0x02);  // Initialize lcd in 4-bit mode of operation
LCD_SEND(0x28);  // 2 lines (16X2)
LCD_SEND(0x0C);   // Display on cursor off
LCD_SEND(0x06);  // Auto increment cursor
LCD_SEND(0x01);   // Display clear
LCD_SEND(0x80);  // First line first position
}```

Below code is used to Display the values on LCD

```void LCD_DISPLAY (char* msg)         //Function to print the characters sent one by one
​
{
uint8_t i=0;
while(msg[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //Sends Upper nibble
IO0SET = 0x00000050;  //RS HIGH & ENABLE HIGH to print data
IO0CLR = 0x00000020;  //RW LOW Write mode
delay_ms(2);
IO0CLR = 0x00000040; // EN = 0, RS and RW unchanged(i.e. RS = 1, RW = 0)
delay_ms(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //Sends Lower nibble
IO0SET = 0x00000050; //RS & EN HIGH
IO0CLR = 0x00000020;
delay_ms(2);
IO0CLR = 0x00000040;
delay_ms(5);
i++;
}
}```

Below function is used to create delay

```void delay_ms(uint16_t j)  // Function for making delay in milliseconds
{
uint16_t x,i;
for(i=0;i<j;i++)
{
for(x=0; x<6000; x++);    // Forloop to generate 1 millisecond delay with Cclk = 60MHz
}
}```

Complete code with demonstration Video is given below.

Code
//Circuit Digest

#include <lpc214x.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

void delay_ms(uint16_t j)  // Function for making delay in milliseconds
{
uint16_t x,i;
for(i=0;i<j;i++)
{
for(x=0; x<6000; x++);    // Forloop to generate 1 millisecond delay with Cclk = 60MHz
}
}

void LCD_SEND(char command)     //Function to send hex commands
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((command & 0xF0)<<8) ); //Send upper nibble of command
IO0SET = 0x00000040; //Making Enable HIGH
IO0CLR = 0x00000030; //Making RS & RW LOW
delay_ms(5);
IO0CLR = 0x00000040; //Makeing Enable LOW
delay_ms(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((command & 0x0F)<<12) ); //Send Lower nibble of command
IO0SET = 0x00000040;  //ENABLE HIGH
IO0CLR = 0x00000030;  //RS & RW LOW
delay_ms(5);
IO0CLR = 0x00000040;  //ENABLE LOW
delay_ms(5);
}

void LCD_INITILIZE(void)          //Function to get ready the LCD
{
IO0DIR = 0x0000FFF0; //Sets pin P0.12,P0.13,P0.14,P0.15,P0.4,P0.6 as OUTPUT
delay_ms(20);
LCD_SEND(0x02);  // Initialize lcd in 4-bit mode of operation
LCD_SEND(0x28);  // 2 lines (16X2)
LCD_SEND(0x0C);   // Display on cursor off
LCD_SEND(0x06);  // Auto increment cursor
LCD_SEND(0x01);   // Display clear
LCD_SEND(0x80);  // First line first position
}

void LCD_DISPLAY (char* msg)         //Function to print the characters sent one by one
{
uint8_t i=0;
while(msg[i]!=0)
{
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0xF0)<<8) ); //Sends Upper nibble
IO0SET = 0x00000050;  //RS HIGH & ENABLE HIGH to print data
IO0CLR = 0x00000020;  //RW LOW Write mode
delay_ms(2);
IO0CLR = 0x00000040; // EN = 0, RS and RW unchanged(i.e. RS = 1, RW = 0)
delay_ms(5);
IO0PIN = ( (IO0PIN & 0xFFFF00FF) | ((msg[i] & 0x0F)<<12) ); //Sends Lower nibble
IO0SET = 0x00000050; //RS & EN HIGH
IO0CLR = 0x00000020;
delay_ms(2);
IO0CLR = 0x00000040;
delay_ms(5);
i++;
}
}

int main(void)
{
LCD_INITILIZE();        //Calls function to get ready the LCD to display
float voltage;
char voltvalue;
LCD_DISPLAY("CIRCUIT DIGEST");
delay_ms(900);
LCD_SEND(0xC0);
delay_ms(900);
PINSEL1 = 0x01000000; // Select P0.28 as AD0.1
while(1)                                //while loop that excecutes continueously
{
while ( !(AD0DR1 & 0x80000000) ); // Waits for DONE
LCD_SEND(0x80);
voltage = ( (adcvalue/1023.0) * 3.3 ); // formula to convert ADC value into voltage
LCD_SEND(0xC0);
sprintf(voltvalue, "Voltage=%.2f V  ", voltage);
LCD_DISPLAY(voltvalue);                //Display (input analog voltage)
memset(voltvalue, 0, 18);