The 18F452 and the 18F4520 have built-in analog to digital converters (ADC). These converters allow analog voltages to be converted to a digial number inside the PIC. The digital number can then be analyzed and processed. These ADCs are great for analog sensors such as temperature sensors, pressure sensors, humidity sensors, optical sensors, and power sensors. Any sensor between with a voltage between 0V and 5V can be used.

• NOTE: If a sensor is not available, you can substitute the sensor using any voltage output device ranging betweeen 0V and 5V, such as a power supply or function generator. Vary the voltage source to simulate the change in sensor output.

The following is geared for the 18F4520. This tutorial will also work with the 18F452 and the 18F4525. Before continuing, be sure to read through the first tutorial in this series, PIC Programming Basics

## Basic Theory

### Voltage Conversion Process

PICs generally have several analog channels (ports) available to the user. Any number of these can be configured to take in analog values between 0V (GND) and 5V (Vdd). This range can be changed however, in this tutorial, we will assume the range to be from 0V to 5V.

Each analog voltage applied to a channel can be intepreted into a digital number in memory. Also, the digital number can be of any length. In our example, a 10-bit ADC will be used. If 0V is detected by the ADC channel, then once the conversion is complete, `00 0000 0000` should be stored in memory. On the other extreme, if 5V is detected by the ADC channel, `11 1111 1111` should be stored in memory. Any value in between will produce a corresponding binary number.

Once the digital number is stored in memory, any manipulation or calculation can be applied. In the following example’s, we will use the ADC channels to intepret sensors.

### Flow

There are 2 basic steps in using the ADCs logically:

• Convert the analog voltage into a digital number in memory.
• Manipulate the converted digital number into something that represents what is being “sensed” by the sensor.

As the sensor changes, the voltage output changes. During the ADC conversion, the ADC takes a sample of the voltage and begins to generate a digital number. The digital number in memory is manipulated to represent the actual real-world value. The following graph shows a simple example of how the ADC maps a voltage to a digital number.

The key to using the ADCs properly is to map the incoming digital number to the sensor’s real-world input. For example, if a pressure sensor is detecting 120 kilopascals of pressure, then the final memory value should contain “120”. If a humidity sensor is detecting 50% relative humidity, then the final memory value should contain “50”.

## Getting Started

You will need the following:

• a sensor in which the output is an analog voltage between 0V and 5V maximum. (Alternate: A varying voltage supply can be used.)
• a MAX232 chip, setup and installed
• a serial cable and DB-9, setup and installed

According to the temperature sensor datasheet, the sensor contains 3 pins.

• power
• ground
• output

Connect the groud pin to ground, connect the power pin to power, and connect the output to pin 2 of the PIC.

## Open PORTA

Several pins on the PIC are identified as analog input pins. Port A contains several analog input pins. Each analog input pin is labeled as AN. For our example, we will use AN0 which is pin 2.

Set port A to all inputs.

``` 9:  TRISA = 0xFF;
```

You have now opened port A for use. Now, on to opening an ADC channel.

According to the libraries file, in order to use an ADC channel, the ADC must be opened. `OpenADC` function will open an ADC channel. Be sure to include `adc.h`

``` 1:  #include <p18cxxx.h>
2:  #include <usart.h>
4:
5:  void main()
6:  {
7:
8:       TRISC = 0x00;
9:       TRISA = 0xFF;
10:
11:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
12:
14:
15:  }
```

### ADC Parameters for the 18F452

• NOTE: If you are using the 18F4520, skip this section.

For the 18F452, several parameters must be chosen in order to properly open the ADC channel. According to the libraries file, we will use the following parameters:

• `ADC_FOSC_2`
• `ADC_RIGHT_JUST`
• `ADC_8ANA_0REF`
• `ADC_CH0`
• `ADC_INT_OFF`

Later, these options can be changed.

``` 1:  #include <p18cxxx.h>
2:  #include <usart.h>
4:
5:  void main()
6:  {
7:
8:       TRISC = 0x00;
9:       TRISA = 0xFF;
10:
11:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
12:
14:
15:  }
```

The ADC is now configured. Next, on to starting an analog to digital conversion.

### ADC Parameters for the 18F4520

* NOTE: If you are using the 18F452, skip this section.

For the 18F4520, several parameters must be chosen in order to properly open the ADC channel. According to the libraries file, we will use the following parameters:

• `ADC_FOSC_2`
• `ADC_RIGHT_JUST`
• `ADC_20_TAD`
• `ADC_CH0`, this selects channel 0. A different channel can be selected later.
• `ADC_INT_OFF`
• `ADC_VREFPLUS_VDD`, this sets the upper range as 5V (Vdd)
• `ADC_VREFMINUS_VSS`, this sets the lower range as 0V (GND)
• `0`, this sets all ADC channels as “analog inputs”. Later, you can select which ones are analog inputs and which ones are digital I/O.

Later, these options can be changed.

``` 1:  #include <p18cxxx.h>
2:  #include <usart.h>
4:
5:  void main()
6:  {
7:
8:       TRISC = 0x00;
9:       TRISA = 0xFF;
10:
11:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
12:
14:
15:  }
```

The ADC is now configured. Next, on to starting an analog to digital conversion.

## Start a Conversion

To begin, an integer variable is needed to store the digital result from a conversion process. Therefore, `xvalue` will be used.

```8:  int xvalue = 0;
```

Accoding to the libraries file, to begin converting, `ConvertADC()` function must be called. Afterwards, the PIC must wait until a conversion is complete before storing the value in `xvalue`. Therefore, the `BusyADC()` funtion will be used to monitor when the conversion process is complete. A `while` loop will be used to wait until the conversion process is complete.

```17:  ConvertADC();
```

When a conversion process is complete, then the value can be stored in `xvalue` using the `ReadADC()` function.

```17:  ConvertADC();
19:
```

`xvalue` now contains the digital representation of the analog signal. If 0V is applied to the analog input, `0000 0000 0000 0000` will be stored in `xvalue`. If 5V is applied to the analog input, then `0000 0011 1111 1111` will be stored in `xvalue`.

• NOTE: Only 10 bits of the 16 bits in `xvalue` will ever change. The reason for this is because the PIC ADC is a 10bit ADC. It only has a 10bit resolution. In otherwords, the smallest digital number will be 0 and the largest digital number will be 1023.

The code should look like this.

``` 1:  #include <p18cxxx.h>
2:  #include <usart.h>
4:
5:  void main()
6:  {
7:
8:       int xvalue = 0;
9:
10:       TRISC = 0x00;
11:       TRISA = 0xFF;
12:
13:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
14:
16:
19:
21:
22:  }
```

This will perform one conversion and store the digital value. This may not be very useful. Most analog signals change constantly (like temperature) and therefore conversions need to occur repeatedly. Also, there needs to be a way to display the digital value to a PC screen using USART. Next, using USART to display the digital value.

To display the ADC value stored in memory, it must be converted to ASCII in order to be printed to a screen. We will use what we learned in the USART tutorial. As a reference, the value displayed should be between 0 and 1023.

### Convert ADC Value to ASCII

We will need a char array in order to store all the digits of the value. Since the largest value to be displayed is 4 digits long (1023), then we need a 5 element array to store all the characters. We name this array `xvalueASCII`.

The binary number stored in `xvalue` must now be converted to ASCII. We use the `itoa()` function which converts a, integer binary number into an array of ASCII characters (integer to ascii). For example, if `0000 0000 0000 1010` was stored in `xvalue`, then `xvalueASCII` will contain the 2 characters ‘1’ and ‘0’ representing the number 10. `xvalueASCII` is now a string of characters waiting to be printed to the PC screen.

``` 1:  #include <p18cxxx.h>
2:  #include <usart.h>
4:
5:  void main()
6:  {
7:
8:       int xvalue = 0;
9:       char xvalueASCII = 0;
10:
11:       TRISC = 0x00;
12:       TRISA = 0xFF;
13:
14:       OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 129);
15:
17:
20:
Using the `putsUSART()` function, we can now print the string.