• Analog input display
• Voltage measurement
• ADC setup codes
A microcontroller analog input allows an external voltage to be converted to digital form, stored, and processed. This type of input occurs in data loggers, control systems, digital audio, and signal processors, to mention just a few. The dsPIC range is designed specifically for high-speed analog signal processing.
A basic setup to demonstrate analog input is shown in Figure 3.1. The PIC16F877 has eight analog inputs, which are accessed via RA0, RA1, RA2, RA3, RA5, RE0, RE1, and RE2, being renamed AN0 to AN7 in this mode. All these pins default to analog operation, but a combination of analog and digital inputs can be selected using the system function set_up_adc_ports().
These inputs are multiplexed into a single converter, so they can be read only one at a time. The function set_ADC_channel(n) selects the input channel. The analog-to-digital converter module has a resolution of 10 bits, giving a binary output of 0×000to 0×3FF(102310). Therefore, the measurement has a precision of 1/1024×100%, which is slightly better than 0.1%. This is good enough for most practical purposes. A 16-bit integer or floating point variable is needed to receive this result.
Alternatively, the low-resolution mode can be used if an 8-bit conversion is sufficiently precise (output=0–255). This mode is selected using the directive #device ADC=8. The function read_ADC() then returns the input value as an unsigned integer. The default input voltage range is 0–5 V, which does not give an exact conversion factor. In the demo program, Listing 3.1, the 8-bit input value is divided by 32 to give an arbitrary voltage level from 0 to 8. This is then converted to the ASCII code by adding 0×30 and sending it to the display. The operation is repeated endlessly, using the statement for(;;), which means execute a for loop unconditionally.
Listing 3.1. Source Code for simple Analog Input Test Program
/* ANALIN.C MPB 5-1-07
Read & display analog input
***************************************************************/
#include “16F877A.h”
#device ADC=8 //8-bit conversion
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_D0, rcv=PIN_D1) //LCD output
void main() //*************************************************
{
int vin0; // Input variable
setup_adc(ADC_CLOCK_INTERNAL); // ADC clock
setup_adc_ports(ALL_ANALOG); // Input combination
set_adc_channel(0); // Select RA0
for(;;)
{ delay_ms(500);
vin0=read_adc(); //Get input byte
vin0=(vin0/32)+0×30; //Convert to ASCII
putc(254); putc(1); delay_ms(10); // Clear screen
printf(“Input=“); putc(vin0); // Display input
}
}
The circuit shown in Figure 3.2 allows the input voltage at each analog input to be displayed. An external reference voltage (2.56 V) is connected to RA3, which sets the maximum of the input range. This allows a more accurate and convenient scaling of the measurement. The reference voltage is supplied by a zener diode and voltage divider circuit. The value of the zener load resistor has been selected by simulation to adjust the voltage to 2.560±0.1%. A potentiometer is connected to each of the measured inputs so it can be set to an arbitrary test value. The test program VOLTS.C is provided in Listing 3.2.
Listing 3.2. Test Program for Voltage Measurement
/* VOLTS.C MPB 25-3-07
Read & display 10-bit input voltage
*****************************************************************/
#include “16F877A.h”
#device ADC=10 // 10-bit operation
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_D0,rcv=PIN_D1)
void main() //**************************************************
{
int chan;
float analin[8], disvolts[8]; // Array variables
setup_adc(ADC_CLOCK_INTERNAL); // ADC Clock source
setup_adc_ports(AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF); // ADC inputs
while(1) // Loop always
{
for(chan=0;chan<8;chan++) // Read 8 inputs
{ delay_ms(1000); // Wait 1 sec
set_adc_channel(chan); // Select channel
analin[chan]= read_adc(); // Get input
disvolts[chan]=(analin[chan])/400; // Scale input
putc(254);putc(1);delay_ms(10); // Clear display
printf(“ RA%d=%4.3 g”,chan,disvolts[chan]); // Display volts
}
}
}
This time, the ADC resolution is set to 10 bits, to obtain a more precise reading. Floating point array variables are declared for the input readings (0–1023) and the calculated voltage. The reference voltage, 2.56 V, is represented by the maximum conversion value, 1024, so the scaling factor is 1024/2.56=400 bits per volt. The input is therefore divided by this factor to obtain a display in volts. Note that, in the division operation, both values must be float types.
The ADC port setup code selects all inputs as analog, with RA3 an external reference (although this is not obvious from the select statement format). All the possible combinations of analog and digital inputs are given in the 16F877A.H header file, Listing 2.19. When the program is compiled, the define statement selected is replaced by the corresponding hex code, which is then loaded into the ADC control register to set up the ADC.
The set of functions that control the ADC are listed in Table 3.1
Action | Description | Example |
---|---|---|
ADC SETUP | Initialize ADC | setup_adc(ADC_CLOCK_INTERNAL); |
ADC PINS SETUP | Initialize ADC pins | setup_adc_ports(RA0_ANALOG); |
ADC CHANNEL SELECT | Select ADC input | set_adc_channel(0); |
ADC READ | Read analog input | inval=read_adc(); |
3.133.149.168