• AVR Freaks

Hot!ADC in 16F886

Author
buildlab
Starting Member
  • Total Posts : 32
  • Reward points : 0
  • Joined: 2019/06/26 11:50:03
  • Location: 0
  • Status: offline
2019/12/05 00:37:43 (permalink)
0

ADC in 16F886

Hi, i recently bought a 16f886 controller and been trying to make it work since then.
i know it is the problem with my register initialization part.
can anyone help me to make the adc pins working ?, below is a simple code for adc.
#define _XTAL_FREQ 8000000

#include <xc.h>

// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
int readAdc(int);
int sensor;
void main(void)
{
   PORTA = 0x00;
   PORTB = 0x00;
   PORTC = 0x00;
   TRISC = 0x00;
   TRISA = 0xFF; //RB0 as Output PIN
    ANSEL =0b00000111;
  // CMCON = 0x07;
 ADCON1 = 0xD0;
   RC7 = 0;
   RC6 = 0;
   RC5 = 0;
  while(1)
  {
      sensor = readAdc(2);
     if (sensor > 500)
     {
    RC7 = 1; // LED ON
     RC6 = 1;
     }
     if (sensor < 500)
     {
 RC7 = 0;
 RC6 = 0;
     }


  }
}

int readAdc(int channel){
    int vol;
        ADCON0 = 0x81 | (channel << 2);
       
        __delay_us(20);
        GO = 1;
        while(GO == 1);
        vol = (ADRESH << 8) + ADRESL;
        __delay_us(5);
        return vol;
}

post edited by buildlab - 2019/12/05 01:56:13
#1

12 Replies Related Threads

    buildlab
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2019/06/26 11:50:03
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/05 02:59:50 (permalink)
    0

    #define _XTAL_FREQ 8000000
    #include <xc.h>
    // BEGIN CONFIG
    #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR enabled)
    #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
    #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
    #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
    //END CONFIG
    int readAdc(int);
    int sensor;
    void main(void)
    {
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    TRISC = 0x00;
    TRISA = 0xFF; //RB0 as Output PIN
    ANSEL =0b00000111;
    // CMCON = 0x07;
    ADCON1 = 0b100;
    RC7 = 0;
    RC6 = 0;
    RC5 = 0;
    while(1)
    {
    sensor = readAdc(2);
    if (sensor > 500)
    {
    RC7 = 1; // LED ON
    RC6 = 1;
    RC5 = 1;
    RC4 = 1;
    }
    if (sensor < 500)
    {
    RC7 = 0;
    RC6 = 0;
    RC5 = 0;
    RC4 = 0;
    }

    }
    }
    int readAdc(int channel){
    int vol;
    ADCON0 = 0x83 | (channel << 2);
    ADCON1 = 0b100;

    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = (ADRESH << 8) + ADRESL;
    __delay_us(5);
    return vol;
    }

     
    changed to this and the adc seems working but in the opposite state.
    the led attached to the RC4,RC5.. glows when the sensor value is less than 500 instead of greater than 500.
    also i am getting errors in proteus simulator.

    "
    [PIC16 ADC] PC=0x07A1. ADC conversion started before 'wait' time has expired following previous conversion or channel change. [U1]    "
    post edited by buildlab - 2019/12/05 03:07:33
    #2
    buildlab
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2019/06/26 11:50:03
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/05 03:37:10 (permalink)
    0

    int readAdc(int channel){
    int vol;
    ADCON0 = 0b10000001 | (channel << 2);
    ADCON1 = 0b100;

    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = (ADRESH << 8) + ADRESL;
    __delay_us(5);
    return vol;
    }

     
    now there are no errors but the leds are glowing when the pot value is less than 500 
    don't understand why.
    #3
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/05 05:10:20 (permalink)
    0
    What do you think this is doing?
    ADCON1 = 0b100;

    Hint: Bit 2 is unused in the datasheet, so it is obviously not what you think.
    Try commenting your code rather than just using "magic numbers".
    Also you have set the exact same value in the readAdc routine as you set in initialization.  That won't cause a problem, but is somewhat pointless.
     
    Perhaps you have your pot around the wrong way?
    Or your LEDs wired to Vdd, in which case a 0v out on the PIN will turn the LED on?
     
    Show your circuit diagram.
    #4
    1and0
    Access is Denied
    • Total Posts : 10997
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: ADC in 16F886 2019/12/05 07:32:33 (permalink)
    +1 (1)
    buildlab

    int readAdc(int channel){
    int vol;
    ADCON0 = 0b10000001 | (channel << 2);
    ADCON1 = 0b100;

    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = (ADRESH << 8) + ADRESL;
    __delay_us(5);
    return vol;
    }

    now there are no errors but the leds are glowing when the pot value is less than 500 
    don't understand why.

    Because your ADC is configured to return left justified result; hint: lookup the ADCON1 register in your PIC datasheet.  That 5 us delay is unnecessary.  Also, it's better to select the channel with this
      ADCON0bits.CHS = channel;

     
    #5
    1and0
    Access is Denied
    • Total Posts : 10997
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: ADC in 16F886 2019/12/05 07:45:04 (permalink)
    +2 (2)
    Using the correct types in embedded programming is very important; always use the smallest type possible. That function should return an unsigned int (uint16_t) and the input parameter should be unsigned char   (uint8_t). Use of the local variable "vol" is unnecessary.
    #6
    buildlab
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2019/06/26 11:50:03
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/07 04:36:50 (permalink)
    0

    int readAdc(int channel) {
    int vol;
    ADCON0 = 0b10000001 | (channel << 2);
    ADCON1 = 0b10000000;

    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = ADRESH + (ADRESL << 8);
    __delay_us(5);
    return vol;
    }

    Thank you @1and0 it worked properly.
    #7
    ric
    Super Member
    • Total Posts : 27979
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: ADC in 16F886 2019/12/07 04:40:15 (permalink)
    +1 (1)
    You really only need to write to ADCON1 once, not every time you do a reading.
    now you've seen what was wrong with ADCON0, you can initialise it once, then use this construct to just update the channel bits.
    ADCON0bits.CHS = channel;
    instead of
     ADCON0 = 0b10000001 | (channel << 2);
     
    That is much less error prone, and portable to other similar model PICs.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    buildlab
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2019/06/26 11:50:03
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/07 04:48:51 (permalink)
    0
    Thank you for the support Ric.It worked well!

    int readAdc(int channel) {
    int vol;
    ADCON0bits.CHS = channel;
    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = ADRESH + (ADRESL << 8);
    __delay_us(5);
    return vol;
    }

    #9
    1and0
    Access is Denied
    • Total Posts : 10997
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: ADC in 16F886 2019/12/07 04:53:26 (permalink)
    +1 (1)
    buildlab

    int readAdc(int channel) {
    int vol;
    ADCON0 = 0b10000001 | (channel << 2);
    ADCON1 = 0b10000000;

    __delay_us(20);
    GO = 1;
    while(GO == 1);
    vol = ADRESH + (ADRESL << 8);
    __delay_us(5);
    return vol;
    }

    Thank you @1and0 it worked properly.

    Are you sure?  Take a second look at the assignment to "vol" statement!
     
    #10
    ric
    Super Member
    • Total Posts : 27979
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: ADC in 16F886 2019/12/07 04:57:05 (permalink)
    +1 (1)
    1and0
    Are you sure?  Take a second look at the assignment to "vol" statement!

    +1.
    You will get something back, but not the correct data.
    Also, that final delay is uneccessary.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #11
    buildlab
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2019/06/26 11:50:03
    • Location: 0
    • Status: offline
    Re: ADC in 16F886 2019/12/07 10:54:46 (permalink)
    0

    int readAdc(int channel) {
    ADCON0bits.CHS = channel;
    __delay_us(20);
    GO = 1;
    while(GO == 1);
    return ((ADRESH << 8)+ ADRESL );
    }
     
    #12
    1and0
    Access is Denied
    • Total Posts : 10997
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: ADC in 16F886 2019/12/07 11:14:34 (permalink)
    +1 (1)
    buildlab
    int readAdc(int channel) {
      ADCON0bits.CHS = channel;
      __delay_us(20);
      GO = 1;
      while(GO == 1);
      return ((ADRESH << 8)+ ADRESL );
    }
     

    Why you keep insisting on using "int" type for both the function parameter and the return value?
     
    #13
    Jump to:
    © 2020 APG vNext Commercial Version 4.5