Analog to Digital Converter
When using microcontrollers, everything is digital. But for some purposes you need to convert an analog signal to digital. And sometimes you need to convert digital signal to analog (like in DACs in VGA). ADCs (Analog to digital converters) are built-in to some microcontrollers and we’ll see how to use them. Example microcontroller is PIC 16F877A.
In PIC 16F877A there are four 8 bit registers to control these ADCs.
Microchip made the ADCs 10bit even though the microcontroller is 8 bit. This was to increase the resolution. For example you can convert a signal varying from 0V to 5V to digital number 0-1024, if it was 8 bit, the resolution will be 0-255. So to store a 10 bit value, you need a 10 bit register. But there aren’t any. So they joined two 8 bit registers and called them ADRESH and ADRESL (H stands for higher bits, and L stands for lower bits). But there will be 6 bits left unused.
Now we must look how to control these ADCs. The registers used for this purpose are ADCON0 and ADCON1. ADCON0 is specially reserved for controlling the operation of the ADCs while ADCON1 is reserved for changing the format of the 10 bits and to select what pins you need digital.
Above image is from the microcontroller datasheet. Bit 7 and 6 (ADCS1 and ADCS0) are A/D Conversion Clock Selection bits. These are here because ADC can’t operate as fast as the microcontroller. To give a 10bit result of an analog signal is much more work than just executing an instruction. So ADCs will take several clock ticks of the main oscillator to give the result. But you must tell the ADCs whats your main oscillator speed so that it can derive its clock speed.
i.e. You must set ADCS1 to “1” and ADCS0 to “0” if you are using a 20MHz Crystal. RC is there because ADC unit is also supplied with a RC oscillator to run without depending on the main clock.
Bits 5,4,3 are channel selection bits. ADC units available pins are called channels. RA0 to RA5 except RA4, and PORTE can be used as analog inputs in this microcontroller. But you can use only one channel at a time. So you need set the channel selection bits every time when you want to make the microcontroller monitor the pin you desire.
Bit 2 is A/D Conversion status bit. When a 10 bit result is ready this will be auto cleared. Just set it to “1”.
Bit 1 is unimplemented. You can set it to 1 or 0.
Bit 0 is A/D On bit. You can turn of ADC and save power when you don’t want it by setting this bit to 0. But to use ADC set it to 1. Programming examples with a 20MHz Crystal is shown below. Channel used is RA0.
ADCON0 = 0b10000101;
Compare this with what you learned for now.
As already said ADCON1 is reserved for changing the format of the 10 bits and to select what pins you need digital.
Bit 7 is the A/D Result Format Select bit. At the beginning I told that there will be 6 bits left of joined ADRESH and ADRESL registers. Because of this you can align the result to right side or left side. This becomes useful when you really want to work with 8 bits. You can align the 10 bit result to the right side and ignore the two bits left on the ADRESL. This does some change to the nice 10 bit result. But sometimes you can ignore the difference.
Bits 6,5,4 are unimplemented.
Bits 3,2,1,0 are A/D Port Configuration Control bits. In ADCON0 there was channels you can choose. ADCON1 helps to limit the channels you can choose. Reason is with all those pins used as analog inputs is a waste of microcontroller resources. You wouldn’t have that much analog inputs. So select which pins you want digital, and which pins you want analog, according to the table below.
In some rows you can see VREF+ and VREF-. This is the upper limit and the lower limit of the voltage of the signal you are going to monitor. For some combinations, VREF+ is VDD and VREF- is VSS.
ADCON1 = 0b10000101;
This will make 5 ADC pins used as digital and 3 pins used as analog. VREF- is VSS and VREF+ is the voltage supplied to RA3 pin.
You can read the 10 bit result in mikroC by syntax:
temp = Adc_Read(0);
This will get the ADC result for channel 0. Put the channel number you want.
If you want to represent the 10 bit result with an 8 bit value in mikroC, you can do it by dividing the 10 bit result with 4. What this doing here is changing the resolution. It was a number between 0-1024 when it was 10 bits. But when you divide 1024 by 4 you get 255. So new resolution is 0-255. Now the result is a number between 0 – 255. You’ll need this when you want to set the duty of PWM directly with reference to ADC input since you get the maximum duty when you set it to 255.
Ok, I described the most confusing stuff about ADC. Read the ADC section of the datasheet for more info if you are interested.