PIC 16f877A C program for ADC averaging
First of all, if your input is noisy, you can simply take a number of readings inside a tight loop, say 10, and use the average value from that as your reading.

To average over a period of time, you want to use a rolling average, such as implemented by the following code.  Readings are added to an array, and then the average of all the readings is computed and returned.  I did not include the initialization of the ADC module, and the ADC channel is hard-coded as 0.

Because of the limited register size of the PIC16, I am using #if statements to select the smallest variable sizes possible (i.e. unsigned char index if array is less than 256). 

#define MAX_ADC_VALUES  20
#define ADC_CHANNEL  0

unsigned short adcValues [MAX_ADC_VALUES];   // array of ADC readings
#if MAX_ADC_VALUES &lt; 256
unsigned char adcValueIndex = 0;       // current index into array
#else
unsigned short adcValueIndex = 0; 
#endif
unsigned char fullArray = 0;       // set to 1 after we have filled array

// call this on a periodic basis
unsigned short getAveragedAdcReading()
{
#if MAX_ADC_VALUES &lt; 256
unsigned char i; 
#else
unsigned short i; 
#endif
unsigned short adcReading;         // latest reading from ADC
#if MAX_ADC_VALUES &lt; 66
unsigned short adcAverage;         // 10-bit ADC; sum of 65 readings just fit in an unsigned  short
#else
unsigned long adcAverage;      
#endif

    // if your input is noisy, then add a loop here to take several readings in a row and average
    ADCON0bits.CHS = ADC_CHANNEL;  // channel set here
    ADCON0bits.GO = 1;             // start ADC conversion
    while (ADCON0bits.nDONE);      // wait till ADC conversion is over

    adcReading = (ADRESH&lt;&lt;8) + ADRESL ;   //merge the MSB and LSB of the result
    adcValues[adcValueIndex++] = adcReading;    // overwrite oldest reading with newest one

    adcAverage = 0;
    for (i=0; i &lt; MAX_ADC_VALUES; i++)
    {
        adcAverage += adcValues[i];
    }
    if (fullArray)
    {
        adcAverage /= MAX_ADC_VALUES;          // get average of MAX_ADC_VALUES readings
    }
    else
    {
        adcAverage /= adcValueIndex;          // use this if array not filled yet
    }       

    if (adcValueIndex &gt;= MAX_ADC_VALUES)
    {
        adcValueIndex= 0;          // if at end of array, loop around
        fullArray = 1;             // we have now filled array, can divide by MAX_ADC_VALUES from now on            
    }

    return (unsigned short)adcAverage;    // cast only needed if adcAverage is unsigned long
}