View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
reading ADC |
Posted: Wed Aug 29, 2007 11:29 am |
|
|
I'm using a pic18f452.
I can send it serial commands or I2C commands and everything works great until I start calling the function below.
Code: |
void read_analog()
{
int channel;
int16 value;
for(channel=0;channel<=5;channel++)
{
set_adc_channel(channel);
// delay_us(600);
value = Read_ADC();
analog_array[channel] = value;
}
}
|
I'm setting up the port like this
setup_adc_ports(AN0_AN1_AN2_AN3_AN4_AN5);
setup_adc( ADC_CLOCK_INTERNAL );
It works as above, but if I uncomment the line delay_us(600); then the I2C and serial comms work about 10% of the time. I've tried different delays and they all act the same. It seems from a long time ago I remember that you should have a delay from switching channels to reading the ADC (for accuracy), that is why I put in that line.
So 2 questions,
1) do I need a delay?
2) why would the delay hose my comms?
Thanks
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 11:42 am |
|
|
Do you have an interrupt routine that calls delay_us() ? |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 11:47 am |
|
|
no, I only use delay_us in 2 functions, this one and one other that runs after this one returns. I dont have delay_us or delay_ms in any ints at all. _________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 12:17 pm |
|
|
It looks like it is a compiler version problem. I'm using a different IDE and still had this one set to use the 4.x compiler. When I compiled with 3.249 the problem appears to have gone away.
I need to delete the 4.x crap, it has caused me pain before. _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 12:18 pm |
|
|
My thought was that interrupts were being disabled, due to calling the
delay routine in an isr and outside the isr. If you have Warnings enabled
the compiler will tell you if it's doing this.
According to the 18F452 data sheet the minimum required acquisition
time for the A/D is 12.86 us. So instead of 600 us, try this:
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 12:19 pm |
|
|
I didn't see you other post about the 4.x compiler when I made the
post above. Are you still using 4.013 or something like that, as I recall ?
Definitely get rid of that early version. Just delete it. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 2:33 pm |
|
|
I lied about the version being the problem. It does it less often with 3.249, but still does it. Here is the entire program. As soon as I uncomment the line read_analog, it starts hanging. I'm also blinking an led in main now and that stops so the whole program is hung. I had a similar issue before and PCM programmer found a pointer I was not initializing. I'm only using 1 pointer in here and I made sure it was this time. I also have "errors" in my use232 statement. There must be something I'm missing here causing it to hang but I'm not sure how to find it.
Any ideas will be greatly appreciated.
Thanks
Ringo
_________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 2:46 pm |
|
|
That code doesn't compile. It's missing some routines in utilities.c.
Also, you've still got the delay_us(600) in there, even though I said to
reduce it to delay_us(15). |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 2:50 pm |
|
|
oops, sory about utilities.c
I put the code in the main program. I changed the delay to 15us, but after I had posted last time.
Here is the complete code.
_________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 2:56 pm |
|
|
I added this code
printf("entering read_analog\r\n");
Read_analog();
printf("out of read_analog\r\n");
and when it locks up the last thing it prints is "entering read_analog" so it must be hanging reading the adc. _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 3:07 pm |
|
|
1. Comment out the lines in read_analog(), one at a time, in order to
find out which line is causing the problem.
2. Post the version of the PCH compiler that you're using.
3. Get rid of the delay for 600 us and change it to 15 us, and try it,
and tell if it fixes the problem. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 3:15 pm |
|
|
CCS PCH C Compiler, Version 3.249, 34836
This works
Code: |
void read_analog()
{
int channel;
int16 value;
for(channel=0;channel<=5;channel++)
{
set_adc_channel(channel);
delay_us(15);
// value = Read_ADC();
analog_array[channel] = value;
}
}
|
This does not
Code: |
void read_analog()
{
int channel;
int16 value;
for(channel=0;channel<=5;channel++)
{
set_adc_channel(channel);
delay_us(15);
value = Read_ADC();
analog_array[channel] = value;
}
} |
_________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 29, 2007 3:30 pm |
|
|
Make a small test program that only tests the ADC, and see if it works.
Code: | #include <18F452.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//=================================
void main()
{
int16 result;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(15);
while(1)
{
result = read_adc();
printf("%LX ", result);
delay_ms(500);
}
} |
|
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 3:39 pm |
|
|
This runs fine
Code: |
#include "18F452.h"
#fuses hs,nowdt,noprotect,put,nolvp
#device *=16
#device adc=10
#device HIGH_INTS=TRUE
#use delay(clock=20000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_c7,errors,bits=8,parity=N)
//=================================
void main()
{
int16 value;
int channel;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(15);
while(1)
{
for(channel=0;channel<=5;channel++)
{
set_adc_channel(channel);
delay_us(15);
value = Read_ADC();
printf("Channel %d value = %LX \r\n", channel,value);
delay_ms(50);
}
}
} |
_________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Wed Aug 29, 2007 3:49 pm |
|
|
This code seems to be working
Code: |
for(channel=0;channel<=5;channel++)
{
printf("setting--");
set_adc_channel(channel);
delay_us(15);
value = 42*channel;
printf("reading--");
value = Read_ADC();
printf("storing--");
analog_array[channel] = value;
}
|
which makes me wonder if I need a delay after reading before going to another channel. I'm going to try that next. _________________ Ringo Davis |
|
|
|