View previous topic :: View next topic |
Author |
Message |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
ADC trouble with the PIC 16F873 |
Posted: Thu May 06, 2004 3:28 am |
|
|
Hello,
I have some trouble reading the ADC. Below I copy-pasted some pieces of the code I use. When I read the ADC I always get the same values (always: 0, 64, 192). I do not understand. I red a lots of articles about this in the forum, but I do not see what I am doing wrong.
Please note:
- I did set the #device with adc=10
- I have to but back the ports to NO_ANALOGS because I have to share some ports
- The program compiles fine and all the drivers (like SetMux and SetResistor) are tested and are good
- I do wait at least 10 ms
- It goes into the ADC_TEST because I can read stuff
Code listing:
==================================================
Code: |
Please review the code provided later in this topic !
It has the same problem, but is more easy to read !
IT DOES WORK NOW... PLEASE READ THE LAST POST(S)
|
==================================================
End of code listing
If anybody can help me solving my problem I would be very grateful.
Best regards
Patrick
Last edited by hanckmann on Fri May 07, 2004 5:17 am; edited 4 times in total |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Thu May 06, 2004 4:24 am |
|
|
Just a few questions:
1. What is the value of SETPORTA? Are you setting the A/D pins as inputs?
2. What is the maximum frequency of the signal you are trying to convert? For a 4MHz crystal ADC_CLOCK_DIV_32 is too slow, You'd better use SETUP_ADC_PORTS(ADC_CLOCK_DIV_8);.
3. You said your ADC reads values like 0, 64 and 192. Do you mean the ADC itself, or the value of the variables adc1 and adc2? Since you have a division by 0x7F you shouldn't get anything higher than 8. |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
Answers |
Posted: Thu May 06, 2004 4:39 am |
|
|
1. #DEFINE SETPORTA 0x0B //binary: 001011 RA0
2. I am measuring a DC power. It might change a bit, but at this moment not. (I will think of this for my fnal design)
3. I made an error in the post. The division by 0x7F was to check something else. This was not included in the piece of software which I was testing. Sorry for that (I changed in the source code listed above).
If you have more questions please let me know...
P |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Thu May 06, 2004 4:44 am |
|
|
Two quick things:
You are setting RA0,RA1 and RA3 to analog. But you are using SET_ADC_CHANNEL(1); and SET_ADC_CHANNEL(2); which correspond to RA1 and RA2. Your RA2 is not even set as an analog pin, and according to the value of SETPORTA, it is set to output. Remember for RA0 and RA1 you have to use SET_ADC_CHANNEL(0); and SET_ADC_CHANNEL(1);.
Secondly, still your RA1 reading should be correct. Did you try the SETUP_ADC_PORTS(ADC_CLOCK_DIV_8); to see if it helps? |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
Changed, but nothing changes |
Posted: Thu May 06, 2004 5:04 am |
|
|
Ok, I changed the program following your directions.
The output to the lcd did not change except that the values are now alway 32 or 160.
I don't know if you can do anything with those values, but ...
P |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Thu May 06, 2004 5:14 am |
|
|
Well what are the DC voltages you are measuring? What values are you expecting to see on the LCD? |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
Expecting... |
Posted: Thu May 06, 2004 5:48 am |
|
|
Well I expect to see a number between 0-1024 corresponding to the voltage which I can measure at the input of the AN0/AN1 to appear at the lcd screen.
The input is now connected to a powersupply (adjustable)
^- that was a mistake (it said not but it had to be now) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 06, 2004 1:06 pm |
|
|
Quote: | I expect to see a number between 0-1024 corresponding to the
voltage which I can measure at the input of the AN0/AN1 to appear at the
lcd screen. |
Quote: | When I read the ADC I always get the same values (always: 0, 64, 192). I do not understand |
The fact that the bottom 6 bits are always 0 should be an important clue.
In the A/D section of the data sheet you will find a chart showing how
the A/D result can be left or right justified. Some versions of the CCS
compiler handle this automatically, depending on the setting of the
#device adc=xx statement, but your version may not have that feature.
To set the bit manually, see the last post in this thread.
http://www.ccsinfo.com/forum/viewtopic.php?t=2771&highlight=adfmbit
You didn't say what PIC you are using. The address shown for the
ADFM_BIT of 0x9F.7 will work for the 16F877, etc. If you have some
other PIC, you should check the data sheet to verify the address. |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
Tried but.... |
Posted: Fri May 07, 2004 2:31 am |
|
|
Ok I tried this:
Code: |
0x9F= 0x9F | 0x80; // this sets the ADFM bit
|
but now i get this error message:
Error[61] MAIN.C 81 : LVALUE required
The PIC I use is the 16F873
What to do because i think you have a good point there...
The code I am using now is as follows:
Code: |
#NOLIST // Provided units
#INCLUDE <16F873.h>
#INCLUDE <stdlib.h>
#INCLUDE <stdio.h>
#INCLUDE <LAMdefines.c> // All global defines (partly provided)
#LIST
#FUSES HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP
#USE DELAY(CLOCK=4000000)
#USE FAST_IO(A)
#USE FAST_IO(B)
#USE FAST_IO(C)
#NOLIST
#INCLUDE <Button.c> // Button driver (for 2 buttons, MODE and SET)
#INCLUDE <LCD_c.c> // Lcd driver --> This is NOT the standard lcd driver
#INCLUDE <Multiplexer.c> // Multiplexer driver
#INCLUDE <Resistor.c> // Digital potentiometer driver
// GENERAL UNITS
#LIST
void InitSystem(void)
// Initialize system
// pre: -
// post: System initialized; I/O and LCD are set
{
// define inputs and outputs
Set_Tris_A (SETPORTA);
Set_Tris_B (SETPORTB);
Set_Tris_C (SETPORTC);
Disable_Interrupts(GLOBAL);
SetMux(0);
InitResistor();
Lcd_init();
}
void main(void)
{
int16 adc1, adc2;
InitSystem();
while(FOREVER)
{
SETUP_PORT_A(RA0_RA1_RA3_ANALOG);
SETUP_ADC_PORTS(ADC_CLOCK_DIV_8);
0x9F= 0x9F | 0x80; // this sets the ADFM bit // added sinds the last post
SetResistor(1, AMP_A_12); // Amplification chanal 1
SetResistor(2, AMP_A_12); // Amplification chanal 2
SetResistor(3, OFFSET_A1X);
SET_ADC_CHANNEL(0);
delay_us(40);
SetMux(0);
adc1= READ_ADC();
SET_ADC_CHANNEL(1);
delay_us(10);
SetMux(2);
adc2= READ_ADC();
lcd_clear();
printf(lcd_putc,"X1: %ld\nX2: %ld", adc1, adc2);
SETUP_PORT_A(NO_ANALOGS);
Set_Tris_A (SETPORTA);
} // end of while(FOREVER)
} // end of main(void)
|
Last edited by hanckmann on Fri May 07, 2004 3:05 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 07, 2004 2:50 am |
|
|
Quote: | Ok I tried this:
0x7F= 0x7F | 0x80;
but now i get this error message:
Error[61] MAIN.C 81 : LVALUE required |
I suggest that you do it exactly the way it's shown in the linked post. |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Fri May 07, 2004 2:51 am |
|
|
Quote: | 0x7F= 0x7F | 0x80; // this sets the ADFM bit |
That is not a correct C statement. The left hand side must be a variable. |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
ADFM bit set |
Posted: Fri May 07, 2004 3:04 am |
|
|
I tried this as well:
ADFM_BIT = 1; // Right justify the A/D result
and this is a copy past from the other post. When I did this the following error occurs:
Error[12] MAIN.C 82 : Undefined identifier ADFM_BIT
Then i looked up the ADFM_BIT. It is the most significant bit of the ADCON1 register. This register is at address 0x9F. Here I thought that if I want to set the MSB in that register I would have to OR it with 0x80 (0b1000 0000).
This gave me the statement
0x9F = 0x9F | 0x80
(I first made the mistake by typing 0x7F, but the compiler result is the same:
Error[61] MAIN.C 81 : LVALUE required )
Then Haplo is ofcourse right, but how should I do this in this case ? |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Fri May 07, 2004 3:14 am |
|
|
Try:
#bit ADFM_BIT=0x9F.7
ADFM_BIT=1; |
|
![](templates/subSilver/images/spacer.gif) |
hanckmann
Joined: 16 Apr 2004 Posts: 9
|
Tried again, nothing changes again... |
Posted: Fri May 07, 2004 3:45 am |
|
|
Ok, my program compiled succesfully now. It might be a part of my problem, but not everything. It is stil not working. At this moment it only reads a 0 (zero). At least, that is what my program prints on the LCD screen.
If somebody has some more ideas ???? Please ???? |
|
![](templates/subSilver/images/spacer.gif) |
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Fri May 07, 2004 4:18 am |
|
|
Tell us more about your circuit configuration.
Try these (all at the same time) and see if anything changes:
1.Change your oscillator fuse from HS to XT. For a 4MHz crystal you have to use XT, not HS. This may be the cause of the problem.
2.Change all FAST_IO lines to STANDARD_IO
3.Move the two fucntuion calls SETUP_PORT_A(RA0_RA1_RA3_ANALOG) and SETUP_ADC_PORTS(ADC_CLOCK_DIV_8) out of the while loop
4.Do not tweak the ADFM_BIT manually
5. Comment out the two SETUP_PORT_A(NO_ANALOGS) and Set_Tris_A (SETPORTA) lines at the end of the loop |
|
![](templates/subSilver/images/spacer.gif) |
|