|
|
View previous topic :: View next topic |
Author |
Message |
danielkr
Joined: 27 Aug 2006 Posts: 5
|
16F676 ADC-problem |
Posted: Sun Aug 27, 2006 12:50 pm |
|
|
Hi,
My 16F676 seems to hang when calling the read_adc() function.
I've tried to change to other pins, different references etc.
Using CCS PCM 3.128
Can someone please help??
Code: |
#include <16f676.h>
#device adc=10
#fuses INTRC_IO,NOWDT,NOBROWNOUT,NOPROTECT,PUT
#use delay(clock=4629167)
#use RS232(BAUD=9600, XMIT=PIN_C4, RCV=PIN_C5)
int16 result;
void main() {
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN3 | VSS_VDD);
set_adc_channel(3);
delay_us(10);
while(TRUE) {
getc();
result=read_adc();
printf("AD=%x\n\r",result);
}
}
|
|
|
|
Guest
|
|
Posted: Sun Aug 27, 2006 2:22 pm |
|
|
Hi,
Try adding 'NOLVP' to your fuses.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Aug 27, 2006 2:43 pm |
|
|
The 16F676 doesn't support LVP mode. The compiler won't accept the
NOLVP fuse. Here is what is wrong:
Quote: |
My 16F676 seems to hang when calling the read_adc() function.
I've tried to change to other pins, different references etc.
Using CCS PCM 3.128 |
Your version of the compiler has got a lot of problems with the 16F676.
1. It doesn't call address 0x3FF at start-up so it can get the OSCCAL
value, which is stored at that address by Microchip. I notice you've got
a weird frequency in your #use delay() statement. It now becomes
clear why you've done that. You've tried to fix the delay code so it
will work with the unadjusted internal oscillator frequency.
2. The start-up code doesn't turn off the comparator. They're left in
the default state, which is "on". If you tried to use RA0, RA1, or RA2
this could cause problems.
3. The start-up code loads the ADCON0 register with 0x07. This is a
bug. It was supposed to load CMCON with 0x07, except they used
the wrong address.
4. The setup_adc(ADC_CLOCK_INTERNAL) function doesn't work
correctly. It should set the ADCS bits in ADCON1 to 011.
Instead, it sets them to 100, which selects OSC/4, not the internal
clock as intended. Also, this function is supposed to set the ADFM
bit = 1, to right-justify the result. It doesn't do this, so the result
will be left-justified.
5. The setup_adc_ports(sAN3 | VSS_VDD) function does work.
It sets up ANSEL correctly. They must have got lucky on this one.
6. The set_adc_channel(3) function doesn't work. It sets the A/D
to channel 6, instead of the intended channel 3. Also, it's using
RAM address 0x58 for a temporary register in this function.
Normally, CCS uses low ram for this, such as 0x20, 0x21, etc.
That alone, shows that this version has got major problems.
7. The read_adc() function doesn't work. It sets and polls bit 2 of the
ADCON0 register, when it should be bit 1, which is the GO/DONE bit.
This is what's causing your program to hang.
To fix all this, you would have to write some inline ASM code to fetch
the OSCCAL value from 0x3FF, and load the OSCCAL register.
You would have to write your own A/D functions. |
|
|
danielkr
Joined: 27 Aug 2006 Posts: 5
|
|
Posted: Mon Aug 28, 2006 12:43 am |
|
|
I guess this explains why I've experienced so much problems. I guess I've learned a lesson too, never put too much trust to the compiler
I'll try to write my own routines now.
Quote: |
5. The setup_adc_ports(sAN3 | VSS_VDD) function does work.
It sets up ANSEL correctly. They must have got lucky on this one.
|
- Lucky with this one..... I get your point after looking at the datasheet
Thank you for you help PCM! |
|
|
danielkr
Joined: 27 Aug 2006 Posts: 5
|
read_adc |
Posted: Mon Aug 28, 2006 2:47 pm |
|
|
I wrote my own read_adc. What do you guys think?
Code: |
int16 my_read_adc(){
bit_set(*0x1F,1);
while(bit_test(*0x1F,1)){}
return *0x9E+*0x1E*256;
}
|
Where 9E and 1E are the low and high result register.
Cheers! |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 28, 2006 3:02 pm |
|
|
Though it ought to work, why not use the byte/bit ability of the compiler?.
Code: |
#byte ADRESL=0x9E
#byte ADRESH=0x1E
#bit ADGO=0x1F.1
int16 my_read_adc(void){
ADGO=TRUE;
while(ADGO) ;
return(ADRESL+(ADRESH<<8));
}
|
I think this will make it easier to follow what is being done, especially if someone else has to look at the code sometime in the future.
Best Wishes |
|
|
danielkr
Joined: 27 Aug 2006 Posts: 5
|
|
Posted: Tue Aug 29, 2006 1:40 pm |
|
|
A lot easier, and much prettier too..
I wonder if a <<8 and *256 is handled diffrent by the compiler?
Thanks Ttelmah Man! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|