Jump to content


View Other Content



Search Articles



Recent Comments


* * * * *

Configuring the PIC18F4550 10-bit ADC module




As always, make sure you have a copy of the datasheet for your PIC. Here's a link to the PIC18F4550 datasheet.

The Analog to Digital Converter on your PIC microcontroller is an incredibly useful tool. Using the ADC, you can interface all sorts of wonderful peripherals, such as potentiometers, gyroscopes, accelerometers, and many other types of sensors. The ADC takes a VSS-VDD (0-5V on my PIC mcu) DC signal as its input and then converts the voltage to a digital value. Using the 10-bit ADC, this means that a voltage level of 0V should be read as 0, and 5V as 1023 (2^10 - 1). Some PIC microcontrollers also have 12-bit ADC modules, allowing for a much higher resolution. Depending on the number of pins on the microcontroller, it has between 10 and 13 analog inputs.

The ADC module on the PIC18F4550 has five registers associated with it (page 267 in the datasheet):
  • Result High Register (ADRESH)
  • Result Low Register (ADRESL)
  • Control Register 0 (ADCON0)
  • Control Register 1 (ADCON1)
  • Control Register 2 (ADCON2)
We'll start by configuring the ADCON0 control register.


ADCON0bits.ADON = 0; // Disable A/D module
 
ADCON0bits.CHS0 = 0; // Select channel 0 (AN0)
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;

Only one channel (I/O pin) may be sampled at one time. The CHS3:CHS0 (CHannel Select) bits are used to select the channel that will be sampled when the GO_DONE bit is set. I'm only using one analog input and so I decided to use channel 0 (AN0), as this will leave the rest of the I/O pins available as digital inputs or outputs. I choose channel 0 by clearing bits CHS3:CHS0 and, since I'm not using any other channels, I will always leave them cleared. If you use multiple channels, just change the CHS3:CHS0 bits to select the channel you want to sample, then set the GO_DONE bit to start the sample/conversion process.

Next is the ADCON1 register. This register controls which I/O pins are analog and which are digital. As previously metioned, I chose to use channel 0 so that the rest of the pins would be available as digital I/O. Two bits in the register also determine what the voltage reference source is. A table in the datasheet shows the different options:

Posted Image

ADCON1 configuration:

ADCON1bits.VCFG1 = 0; // Use VSS for Vref- source
ADCON1bits.VCFG0 = 0; // Use VDD for Vref+ source
 
ADCON1bits.PCFG0 = 0; // Make AN0 pin analog and all others digital
ADCON1bits.PCFG1 = 1;
ADCON1bits.PCFG2 = 1;
ADCON1bits.PCFG3 = 1;

The last configuration register is ADCON2. The ADFM bit determines whether the result in the ADRESH:ADRESL byte pair is right or left justified.

Posted Image

I prefer to make the result right justified. Everything else is little endian, so why shouldn't the A/D result be? Actually, there is a valid reason for having left justification. If you only wanted 8-bits from the 10-bit result, then you could use left justification and only use the ADRESH byte, effectively discarding the two least significant bits.

Now the A/D conversion clock needs to be set. The time to convert one bit is called TAD and must be greater than the minimum TAD time, shown below in Table 28-29:

Posted Image

As you can see, the minimum TAD time is 0.8 μs. TAD can be configured to equal:
  • 2 TOSC
  • 4 TOSC
  • 8 TOSC
  • 16 TOSC
  • 32 TOSC
  • 64 TOSC
TOSC = 1/FOSC, where FOSC is the frequency of your crystal or oscillator (after the PLL, if you're using it). In my case, FOSC is 48MHz, making TOSC = 1/48MHz ~= 20.833 ns. So, divide 0.8 μs by 20.833 ns and the result is ~38.4, meaning that for TAD to be longer than the minimum time, I need to make it at least 38.4*TOSC. This is between the 32 TOSC and 64 TOSC configuration options, so we must go with the longer one, 64 TOSC.


If you don't feel like doing the math, then table 21-1 is an easy way to determine what the A/D conversion clock bits should be set to:

Posted Image

Finally, the three bits selecting the acquisition time need to be configured. You can find the formula to calculate the acquisition time in the datasheet, but it's probably sufficient to say that it needs to be about 2.5 μs. The acquisition time determines how long the channel is sampled before starting the conversion. The acquisition time can be one of the following options:
  • 0 TAD
  • 2 TAD
  • 4 TAD
  • 6 TAD
  • 8 TAD
  • 12 TAD
  • 16 TAD
  • 20 TAD
Since my TAD is 64*TOSC = 64*20.833 ns ~= 1.33 μs, I need to make the acquisition time at least 2 TAD.


ADCON2 configuration:

ADCON2bits.ADFM = 1;  // A/D result is right justified
 
ADCON2bits.ACQT0 = 1; // Acquisition time
ADCON2bits.ACQT1 = 0;
ADCON2bits.ACQT2 = 0;
 
ADCON2bits.ADCS0 = 0; // A/D conversion clock
ADCON2bits.ADCS1 = 1;
ADCON2bits.ADCS2 = 1;

Don't forget to set the TRIS bits corresponding to your analog input pins:

TRISAbits.TRISA0 = 1; // input

The last step is to enable the A/D module:

ADCON0bits.ADON = 1; // Enable A/D module

Now the A/D module on your PIC18F4550 should be configured! All that's left is to actually sample the analog input by setting the GO_DONE bit, waiting for the GO_DONE bit to be cleared, and save the result by reading the ADRESH:ADRESL pair (or ADRES).

One final thing that should be noted is that the maximum recommended input impedance is 2.5KΩ . So if you're using a 10K or 100K potentiometer, for instance, you need to put a buffer amplifier (also called a "line follower") between the input pin and the signal source.


0 Comments


or Sign In