Electronic – PIC12F675 ADC not working properly

adcanalogcembeddedpic

I wrote a code that takes an analog input from a potentiometer and controls the frequency of a clock pulse. So, the idea is to increase the frequency when I increase the pot and decrease the frequency when I decrease the pot. It should change at a constant rate.

The problem:

When I change the pot, the frequency changes, but not in a constant rate. For example, when I increase the pot, the frequency may decrease and if I increase the pot more, it may increase again. And so on.

Here are some examples of when I keep ONLY INCREASING the pot:
enter image description here
enter image description here
enter image description here

The Config:

#pragma config FOSC = INTRCCLK  
#pragma config WDTE = OFF       
#pragma config PWRTE = OFF      
#pragma config MCLRE = OFF       
#pragma config BOREN = ON       
#pragma config CP = OFF         
#pragma config CPD = OFF

The Code:

#include <xc.h>
#include "config.h"
#define _XTAL_FREQ 4000000

void delay(unsigned char freq){
    for(int i = 0; i < (int)freq; i++){
        __delay_ms(1);
    }
}

void dClock(unsigned char freq){
    GPIO1 = 1;
    delay(freq);
    GPIO1 = 0;
    delay(freq);
}

void InitADC(){
    ANSEL = 0x11;
    ADCON0 = 0b00000001;
    CMCON = 0x7;
    VRCON = 0;
}

unsigned char GetADCValue(){
    ADCON0 = 0b00000011;
    while(GO_nDONE);
    return ADRESL;
}

void main(void) {
    TRISIO0 = 1; //analog input
    TRISIO1 = 0; //output
    TRISIO2 = 0;
    TRISIO3 = 1; //mode
    TRISIO5 = 1; //pulse_button

    char pressed = 0;
    GPIO1 = 0;

    InitADC();

    while(1){
        if(GPIO3 == 0){
            GPIO2 = 1;
            unsigned char freq = GetADCValue();
            dClock(freq);
        }
        else{
            GPIO2 = 0;
            if(GPIO5 == 1 && pressed == 0){
                GPIO1 = 1;
                __delay_ms(500);
                GPIO1 = 0;
                pressed = 1;
            }
            else if(GPIO5 == 0 && pressed == 1){
                pressed = 0;
            }
        }
    }
    return;
}

Other than that, everything works fine. Could someone help me with that?
Thank you.

Best Answer

The ADC is only returning the least significant bits with return ADRESL;.
So, if the pot was in such position the returned ADC value was 0b011, "increasing the pot" will return 0b000 as next step.

enter image description here

You should either return ADRESH; or set ADCON0 = 0b**1**0000001; or change freq to an unsigned int and return (ADRESH<8) & ADRESL