Problem in ADC Free Running Mode!

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

I wrote the following code for using the ADC of atmega16 in Free Running mode. 

#include <mega16.h>
#include <delay.h>

void main(void)
{
DDRD = 0xff;
ADMUX=(0<<REFS1) | (0<<REFS0) | (0<<ADLAR);
ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
SFIOR=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

ADCSRA |= (1<<ADSC);
    while(1){
      delay_ms(1000);
      PORTD = ADCW;
            }
}

As I've set the Free Running mode, I excepted that new values display on PORTD as the temperature changes, but it does not happen! Only one conversion is done and the displayed value never changes. I tried repeating the statement 

ADCSRA |= (1<<ADSC);

in the while loop and obviously it worked, but it is the Free Running, yes!? I should not have to add that. Help plz!

 

Last Edited: Tue. Dec 26, 2017 - 03:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"It worked", eh?  Do you realize that you tell itoa() to create a string at address 0?  which is GP register address space...

 

Before worrying about free-running, get a proper buffer, and intelligent display loop.

 

Then, tell the voltage RIGHT AT THE PIN for ADC0.

 

Tell your AVR clock speed.  Unless you are runing the AVR very slow, the ADC is probably being clocked [much] faster than recommended.

 

What AVR model are you really using?  Mega16?  Mega16A?  What voltage is on the AREF pin?  AVcc?  Is AGND connected? 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes it worked. Although itoa was correct certainly, I replaced it with a simple PORTD assignment and no change.  

1MHz Mega16 with AREF and AVcc = 5v.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

azariun wrote:
Although itoa was correct certainly

Did you mean certainly INcorrect?  If not, I don't know if I want to continue.

 

[Can you even get a non-A Mega16?]

 

How are you determining that there is only one conversion being done?

 

as the temperature changes

So, there is a temperature sensor connected to ADC0/PA0?  What type?  What voltage is right on PA0?

 

What toolchain and version?  I'm guessing CodeVision,  but the version would be a mystery.  [That would help to explain why the itoa() "worked", as in CV the low GP registers were otherwise unused and indirectly turned into a buffer.  So indeed if you counted on this, then it would "work".  Still, using a null pointer as a buffer address is sure to cause problems in a full application.] 

 

We still don't know what results to expect.  Using the PORTD method, the low 8 bits of a 10-bit value are shown.

 

And that indeed, if only ADCL is read, might cause the appearance of the result not changing.

 

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
And that indeed, if only ADCL is read, might cause the appearance of the result not changing.

No, that is not the cause -- at least in version 3.29.  ADCL and ADCH are read, so the temp registers are not locked.

 

                 ;0000 000E       PORTD = ADCW;
000055 b1e4      	IN   R30,0x4
000056 b1f5      	IN   R31,0x4+1
000057 bbe2      	OUT  0x12,R30

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what is the optimizer set to ? (if to low the delay don't work correct, remove the line will solve it for now)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
if to low the delay don't work correct, remove the line will solve it for now)

???  This is CodeVision.  Yes, CV does have some restrictions on proper delay execution but optimization settings are not part of that. 

void delay_us(unsigned int n)

 

      generates a delay of n mseconds. n must be a constant expression.

 

void delay_ms(unsigned int n)

 

      generates a delay of n milliseconds.

This function automatically resets the wtachdog timer every 1ms by generating the wdr instruction.

I assume you are referring to GCC caveats?

 

OP's situation is indeed puzzling -- the only thing left is the actual values of the conversion(s) and the level right on the pin.  I've only used free-running in a few apps over the years, and a couple more with other auto-trigger.  The one-page program looks pretty straightforward to me.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.