PIC16F876 - read analog values

(instructions, reset, WDT, specifications...) PIC12F6xx, PIC16Fxxx, PIC16F6x, PIC16F7x

PIC16F876 - read analog values

Postby chakal » Mon Dec 07, 2015 10:25 am

Hello,
I am trying to read the tempreture using a TMP36 sensor on a PIC16F876.I use MPLab and a XC8 compiler to compile my code. I simply don't know what are the values that I should put in the ADC registers.
Here is a code I found for the PIC16F877 but it does not work on my microcontroller.
Code: Select all
    ADCON1bits.ADFM = 1;    //Result right justified

    ADCON1bits.PCFG = 0;    //Setting all the analog ports as Analog inputs

    ADCON0bits.ADON = 1;    //Turns on ADC module

    ADCON0bits.CHS = 0;     //Selects channel 0 ( AN0 )
    int ADCResult;
    while(1)
    {
        __delay_us(25); //Waits for the acquisition to complete

        ADCON0bits.GO = 1;   //Starts ADC conversion

        while (ADCON0bits.nDONE) continue;   //wait till ADC conversion is over

        ADCResult = (ADRESH<<8) + ADRESL ;
    }


Can you please tell me what modifications should I do to this code so that it works properly on the PIC16F876?
Thank you
chakal
 
Posts: 3
Joined: Mon Dec 07, 2015 10:17 am

Re: PIC16F876 - read analog values

Postby ric » Mon Dec 07, 2015 1:06 pm

You've only shown a small snippet of your code, and not explained why you think it is not working properly.
It's much better to post a fully self contained program you have used to do the test, and explain what you did, what you expected to happen, and what did happen.

p.s. you never mention how fast your PIC is running, or show what you set the ADCSx bits to.
My new leslie-special website (for fans of The Great Race) :)
User avatar
ric
Verified identity
 
Posts: 334
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: PIC16F876 - read analog values

Postby chakal » Mon Dec 07, 2015 5:49 pm

What I am trying is a just read the values from the tempreture sensor and put the result in the ADCResult variable.
I've connected the TMP36 sensor directly to the AN0 pin, however with the above code ADCResult = 0 all the time.
I'm using a 20MHz oscillator.
Here is the full code.
Code: Select all
#include <xc.h>
#define _XTAL_FREQ 8000000
#include <pic16f876.h>
#include <stdlib.h>
#include <stdio.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 = ON // 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 main()
{

  int ADCResult;
    ADCON1bits.ADFM = 1;    //Result right justified

    ADCON1bits.PCFG = 0;    //Setting all the analog ports as Analog inputs

    ADCON0bits.ADON = 1;    //Turns on ADC module

    ADCON0bits.CHS = 0;     //Selects channel 0 ( AN0 )
   
    while(1)
    {
        __delay_us(25); //Waits for the acquisition to complete

        ADCON0bits.GO = 1;   //Starts ADC conversion
           
        while (ADCON0bits.nDONE) continue;   //wait till ADC conversion is over

        ADCResult = (ADRESH<<8) + ADRESL ;
       
    }

  return 0;
}
chakal
 
Posts: 3
Joined: Mon Dec 07, 2015 10:17 am

Re: PIC16F876 - read analog values

Postby ric » Mon Dec 07, 2015 8:43 pm

As I mentioned in my "p.s.", you are not setting the ADCx bits, so they are defaulting to 0b000, which means the ADC is running at Fosc/2 which is way too fast at 20MHz.
From Table 11-1 in the datasheet, a 20MHz oscillator means you can only use Fosc/32 or Fosc/64,
so try setting <ADCS1:ADCS0> in ADCON0 to 0b10

You still did not mention HOW you are testing this. There is nothing in your code to output the value read, so I assume you must be running this in the debugger and inspecting the ADCresult variable directly.
Note that depending upon the compiler optimisation level, it could decide to not bother updating that variable at all, as you never use its value anywhere, and you have not declared it as "volatile".

A few other points.
[1] Some of the old PIC16F chips had a small problem in that if you checked the ADC's GO/DONE bit in the very next instruction cycle after setting it, it may not have got set yet.
It is possible that the compiler may generate assembly code doing just that from your source, so it would be a good idea to insert a NOP or something else between the instruction setting ADCON0bits.GO =1, and the test for conversion complete.

[2]
Code: Select all
#define _XTAL_FREQ 8000000

If your clock is 20MHz, then this should be:
Code: Select all
#define _XTAL_FREQ 20000000

however it doesn't matter in this program, as you don't use any of the built in delay macros, so the _XTAL_FREQ value is never used.

[3]
Code: Select all
#include <pic16f876.h>
#include <stdlib.h>
#include <stdio.h>

You don't need any of these.
The PIC specific header has already been included for you by xc.h, so you are just doing it a second time.
There is nothing in your code requiring stdlib or stdio. There rarely is in an embedded program.
My new leslie-special website (for fans of The Great Race) :)
User avatar
ric
Verified identity
 
Posts: 334
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: PIC16F876 - read analog values

Postby chakal » Mon Dec 07, 2015 11:08 pm

Thank you for assistance.
Yes, for now I test ther result in the debugger.
Can you please tell me exactly which registers should to make the ADC work properly.Up until now, I know I should modify:
Code: Select all
ADCS1 = 1; ADCS0 = 0;//choose the 20MHz frequency
CHS0 = 0;CHS1 = 0;CHS2 = 0;//choose the pin AN0 as routed for the ADC conversion

I do not understand how should I modify the ADCON1 register. Can you explain me this point.
Furthermore, are there any other registers that I need to modify?
chakal
 
Posts: 3
Joined: Mon Dec 07, 2015 10:17 am

Re: PIC16F876 - read analog values

Postby ric » Tue Dec 08, 2015 2:38 am

ADCON1 has three bit-fields in it.

ADFM.
You have set this to 1, for right-justified, which is appropriate of you are using the whole 10 bit value.

ADCS2
This is the third speed selection bit, with ADCS1 and ADCS0 from ADCON0. You can leave it set to 0 for Fosc/32.

PCFG (3:0)
You have set this to zero (0b0000), which makes all the PORTA pins analog, and connects Vref+ to Vdd and Vref- to Gnd, which is ok.

Now, how are you testing, and what results are you getting?
I keep asking for this, and you keep not saying.
My new leslie-special website (for fans of The Great Race) :)
User avatar
ric
Verified identity
 
Posts: 334
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products


Return to 14-Bit Core

Who is online

Users browsing this forum: No registered users and 1 guest