View previous topic :: View next topic |
Author |
Message |
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
10 bit a/d |
Posted: Mon Apr 12, 2004 9:17 pm |
|
|
Is there anyone around knowing how to read a 10 bit a/d input from my PIC16F876. I want to read an input voltage and need a resolution of 1024.I have looked around and it has to do with the 8 bit representation of the pic. If you want the code please let me know!!! |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Apr 12, 2004 9:24 pm |
|
|
First of all, make sure you have this line in your code:
Then, you can read a 10-bit value like this:
Code: | int16 ADC;
ADC=read_adc(); |
Last edited by Haplo on Mon Apr 12, 2004 9:29 pm; edited 1 time in total |
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Mon Apr 12, 2004 9:27 pm |
|
|
is that simple???I was looking around and they said something about ADRESH and ADRESL and got kind of worried........I will try and see.....thank you for now!!!! |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Apr 12, 2004 9:32 pm |
|
|
Yes it is simple. Remember, the setup_adc_ports() and setup_adc() functions need to be called (once) to setup the module prior to reading the A/D port. You can use the set_adc_channel() function to change the A/D channel.
And make sure your variable is int16, not int.
For more information, take a look at the ex_admm.c file in the \Examples directory. |
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Mon Apr 12, 2004 9:42 pm |
|
|
i just checked it....it is not working ....this is the code...if you have any comments let me know...it is based on the EX_ADMM file...but it doesnt give the proper resolution i want....10 bits. |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Apr 12, 2004 9:52 pm |
|
|
Do you have the #device adc=10 line? Is the variable you are using to read the A/D defined as int16?
Post your code. |
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Mon Apr 12, 2004 9:55 pm |
|
|
oopppsss...forgot to do it in the previews message...anyway thats the code
#include <16F876.h>
#define PIC16F876 ADC = 10
#FUSES XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (clock=20000000)
#include <LCDDRIVER.h>
#include <math.h>
void main() {
int i,min,max;
long value;
//unsigned int ADRESULT ;
lcd_init();
lcd_putc("\fA/D Converter\nWARMING UP...");
delay_ms(500);
setup_port_a( ALL_ANALOG );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
do {
min=1023;
max=0;
//for(i=0;i<=30;++i) {
delay_ms(100);
value = Read_ADC();
// ADRESULT = ADRESL;
//if(value<min)
// min=value;
//if(value>max)
//max=value;
printf(lcd_putc, "\fA/D Input Vals\nMin: %4ld",value);
//printf(lcd_putc, "\fA/D Input Vals\nMin: %3U",ADRESULT);
} while (TRUE);
} |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon Apr 12, 2004 10:20 pm |
|
|
How do you know you are not getting the correct precision? What is the value you get back from Read_ADC() ?
Quoting from the datasheet:
Quote: | When the device frequencies are greater than 1 MHz, the RC A/D conversion clock source is only recommended
for SLEEP operation. |
Change your code to setup_adc(ADC_CLOCK_DIV_32);
And remember, in CCS the data type int is the same as int8. So 'min' in your code is a byte, and the line 'min=1023' will not work properly. |
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Tue Apr 13, 2004 7:10 am |
|
|
Even doing all the above I still get a maximum of 255 samples on the LCD screen. Regarding what is in page 117 of the manual about how the values obtained from the a/d are stored on the pics memory i thing a different approach should be taken...Any suggestions? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 13, 2004 8:26 am |
|
|
Haplo told you this:
Quote: | First of all, make sure you have this line in your code:
#device adc=10 |
But you did this. There is a difference.
Quote: | #define PIC16F876 ADC = 10 |
|
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Tue Apr 13, 2004 9:54 am |
|
|
If i am not mistaken is the same thing the only i do extra is also making sure to define the pic.but the ADC=10 is defined.Anyway you stillhave to use the ADRESL and ADRESH registers.this is the working code i figured it out. thanks for any help!!
*******************************************************
#include <16F876.h>
#define PIC16F876 ADC = 10
#FUSES XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (clock=4000000)
#include <LCDDRIVER.h>
#include <math.h>
#BYTE ADRESH = 0x1E // ADRESH memory address for high bits
#BYTE ADRESL = 0x9E // ADRESL memory address for low bits
//ADMF is set to 0 by default.Check the pic manual for it.
void main() {
int i,min,max,value;
unsigned long RESULT ;
lcd_init();
lcd_putc("\fA/D Converter\nWARMING UP...");
delay_ms(500);
setup_port_a( ALL_ANALOG );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
do {
//for(i=0;i<=30;++i) {
delay_ms(100);//time for capacitor to charge up
value = Read_ADC();//read proper channel
min=ADRESL; //get values
max=ADRESH; //get values from registers
RESULT = ADRESH; //give 8 first bits in result
RESULT=(RESULT <<2 | min >>6);//take those shiftthem
//positions and OR them by
//value of min shifted 6 pos
printf(lcd_putc,"\fmin:%3U max:%3U\nVAL:%3U RES:
4ld",min,max,value,RESULT);
} while (1);
} |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 13, 2004 10:33 am |
|
|
In electronics, one of the most important things is attention to detail.
That's all I have to say. |
|
|
languer
Joined: 09 Jan 2004 Posts: 144 Location: USA
|
|
Posted: Tue Apr 13, 2004 12:46 pm |
|
|
Three things I want to point out:
1. What are you expecting out of 'value', since you now declared it as a int8?
2. You do notice that you were printing with the 'signed decimal long' modifier (%ld).
3. Although I have never had a problem with the read_adc() function as is, you can also use the make16() to join ADRESH and ADRESL also. |
|
|
drzxoulis
Joined: 12 Apr 2004 Posts: 14
|
|
Posted: Tue Apr 13, 2004 1:30 pm |
|
|
languer thanks for the remarks
First of all i left value like that because i am not going to use it after all.
Being new to the thing i don't see a problem printing with %ld. i get the exact output i want and is very very accurate too. i have never used make16 before but i will take a look in it. Have you ever used read_adc for 10 bit output???
And it is not possible to compile with #device adc = 10 as some stated previously.
with the code i sent and a few mods i can read from like 5 analog inputs and have great accuracy......any suggestion welcomed......not comments ending in "thats all i have to say". |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 13, 2004 2:00 pm |
|
|
Quote: | any suggestion welcomed......not comments ending in "thats all i have to say" . |
The reason I made that comment is because Haplo showed you
how to use the #device adc=10 statement.
You then changed it to #define which is a completely different
word, and it won't work.
Then you said this:
Quote: | And it is not possible to compile with #device adc = 10 as some stated previously |
But of course, that is not what Haplo posted. You have added spaces
before and after the '=' symbol. It will not compile if you add those
spaces.
Also, the statement must be placed on the next line after the main
include statement. Like this:
Quote: | #include <16F877.h>
#device adc=10 |
The basic problem is that you don't follow instructions very well,
so it's very difficult to give you any help. |
|
|
|