[TUT] [C] Newbie's Guide to the AVR ADC

Go To Last Post
324 posts / 0 new

Pages

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

Koshchi wrote:
Quote:
I changed the DDRB in pwm cause i want pwm out of PB1.
But you also want output to PB3. You don't want to keep switching between input and output for these pins. If you want PB1 off when the PWM is enabled, then turn it off using PORTB, don't change it to an input. The same goes for PWM, don't change it to input, disable PWM. (By the way, 0x02 is PB2, not PB1).
Quote:
I am changing the prescaler inside pwm to control the pwm.
But why change it there? Either the rest of the app doesn't care, or worse, it does care and you are changing the pre-scaler without warning. Either way, the best place to do this is at the beginning of main. And since you have:

#define F_CPU 8000000UL

You are telling the compiler that you are running at a specific speed. Any code relying on this will have no clue that you change the speed at a random time during runtime.

Well everything is working its producing PWM but the only problem is its not doing what its suppose to do.

for ( ;; ) { 
        
        if(ADCH < 127) { 
           pwm();
		   _delay_ms(2);
		    //PORTB = 0x08; 
        } else { 
		PORTB = 0x00;
            //pwm();
       } 
        
        //optional 
       // PORTB = 0x00;
        
    } 
    
    return 0; 

clearly it should only produce PWM when the adc is between 0 to 127 but its producing pwm after 127. Why is this happening?

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

Because as I said in my earlier post, you are never turning PWM off.

Regards,
Steve A.

The Board helps those that help themselves.

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

Koshchi wrote:
Because as I said in my earlier post, you are never turning PWM off.

ya i think thats the problem, but how do i turn off pwm? thanks.

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

Turn off the timer that is creating the PWM.

Regards,
Steve A.

The Board helps those that help themselves.

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

i have found the problem. it was with the adc0 pic of atmel. i changed the adc to adc1 and adc 2 respectively and the code works fine. lol nothing wrong with the code. from 0 to 127 led 1 turns on then 127 to 255 pwm turns on led 1 off. after that pwm turns off. no need to do anything else. (i changed the for loop)

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

Quote:
ADCSRB = 0x48

uint32_t measurement = 0x0000;

ADCSRA |= (1 << ADEN); // Enable ADC
ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);//Free running-mode
ADCSRA|=(1<<ADATE);
ADCSRA |= (1 << ADSC); // Start A2D Conversions

for(uint8_t i = 0x00; i < settings[1]; i++)
{
_delay_ms(1);
measurement = measurement + ADCL;
}
measurement = measurement/ settings[1];
ADCSRA &= (0 << ADEN);

I want to sample in free-runningmode the time between every sample should be ~10-20ms.
Settings[1] contains the value on how may samples should be used to calulate the mean value.

Feels lika something is wrong couse I seem to get wierd numbers in ADCL. :/

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

Quote:

I want to sample in free-runningmode the time between every sample should be ~10-20ms.

If the readings are to be spaced temporally then what's the advantage of free running? You could just run a 10-20ms CTC interrupt and set ADSC each time. Or, depending on AVR model, you should be able to configure the ADC to be triggered automatically by the timer.

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

Cause this was easier? :)

I just wanted a to sample x-times and get the mean value. The time between the samples dosent have to be exact so I figured this was the easiest way to do it.

Just needed to check if it would work. Even if its sloppy done. :)

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

This does nothing:

ADCSRA &= (0 << ADEN);

Neither does this:

ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);//Free running-mode

What does this do?

ADCSRB = 0x48 

I'm not going to bother looking up in the datasheet to see what those bits do, particularly since we don't even know which AVR you are using. And it won't compile anyways since there is no ';'.

You are never reading ADCH, so you will never get a correct answer.

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:

ADCSRB = 0x48

I'm too lasy to look up what your magic number translates to but if it isn't "8-bit, right justified" then ADCL is expected to jump around more or less like crazy, yes.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:
then ADCL is expected to jump around more or less like crazy, yes.
But if ADCL is read and ADCH is not (regardless of whether the result is left shifted), you will never get the correct value since the ADC will not be able to update the ADCH or ADCL registers to the current value.

Regards,
Steve A.

The Board helps those that help themselves.

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

Koshchi wrote:
This does nothing:

ADCSRA &= (0 << ADEN);

Neither does this:

ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);//Free running-mode

What does this do?

ADCSRB = 0x48 

(Im using ATTiny861)
I clear ADEN in ADCSRA to disable the ADC.

And the ";" is just a misstake when I pasted it here.

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

Quote:

But if ADCL is read and ADCH is not (regardless of whether the result is left shifted), you will never [...]

You are of-course correct, as usual Steve.

So we need to repeat,

Quote:
What does this do?

ADCSRB = 0x48


until Blipp-Blopp-Bob bothers to
i) answer, and hopefully
ii) rewrite it to something more readable.
I'm still too lazy to look that magical number up.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Strange..
Thought I've answered it, guess not. :?

But here goes:
"ADCSRB = 0x48" should be "ADCSRB |= 0x48"
This will set the MUX5 which gives us 20x/32x gain.
It also sets GSEL which makes the gain 32x instead of 20x.
So it should set Gain 32x.

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

Quote:

I clear ADEN in ADCSRA to disable the ADC.

But

ADCSRA &= (0 << ADEN); 

is not the way to clear a bit? The way to clear that bit is:

ADCSRA &= ~(1 << ADEN);

and if you don't understand why then you need to read the "bit manipulation 101" thread in this forum.

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

ATTiny861

ADCSRB = (1<<GSEL) | (1<<MUX5); //choose 32x gain

ADCSRA |= (1 << ADATE);	//Free-runningmode
ADCSRA |= (1 << ADEN);  // Enable ADC
ADCSRA |= (1 << ADSC);  // Start A2D Conversions

for(uint8_t i = 0x00; i < settings[1]; i++)
{
_delay_ms(1);		
temp1 = temp1 + ADCH;
temp2 = temp2 + ADCL;
}

ADCSRA &= ~(1 << ADEN); // Disable ADC

Maybe this is easier will make it easier.

Best regards
Master of spelling errors

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

Quote:

Maybe this is easier will make it easier.

You cannot read ADCH/ADCL immediately after setting ADSC - you haven't given it time to actually take a reading and make a conversion. Try:

ADCSRB = (1<<GSEL) | (1<<MUX5); //choose 32x gain 

ADCSRA |= (1<<ADATE);   //Free-runningmode 
ADCSRA |= (1 << ADEN);  // Enable ADC 
ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
while (ADCSRA & (1<<ADSC)); // wait for result
temp1 = ADCH; 
temp2 = ADCL; 

ADCSRA &= ~(1 << ADEN); // Disable ADC 

By the way did you read this in the datasheet:

Quote:
When ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently, if
the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH.

If you happen to be using GCC then you don't need to worry about the reading order because you can just do:

uint16_t reading_16_bit;
...
reading_16_bit = ADCW;

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

clawson wrote:
Quote:

Maybe this is easier will make it easier.

Try:

ADCSRB = (1<<GSEL) | (1<<MUX5); //choose 32x gain 

ADCSRA |= (1<<ADATE);   //Free-runningmode 
ADCSRA |= (1 << ADEN);  // Enable ADC 
ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
while (ADCSRA & (1<<ADSC)); // wait for result
temp1 = ADCH; 
temp2 = ADCL; 

ADCSRA &= ~(1 << ADEN); // Disable ADC 
uint16_t reading_16_bit;
...
reading_16_bit = ADCW;

The ADSC dosent flip so it's caught in the while-loop.

reading_16_bit = ADCW; should be reading_16_bit = ADC; on ATTiny861 but I understand what u mean anyway.

Thank you once more clawson!

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

Quote:

The ADSC dosent flip so it's caught in the while-loop.

Then you must be using one of the bug ridden simulators and wasting hours chasing smoke and mirrors. Suggest you see what happens in a REAL chip.

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

Quote:
Then you must be using one of the bug ridden simulators and wasting hours chasing smoke and mirrors. Suggest you see what happens in a REAL chip.
No, the code sets free-running mode. In that mode ADSC remains set. You must test for ADIF going high to determine the end of conversion (and then manually clear that flag).
Quote:
reading_16_bit = ADCW; should be reading_16_bit = ADC;
Both should work in avr-gcc. ADCW is safer since in some circumstances ADC conflicts with the assembler opcode ADC (ADd with Carry).

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
AVCC with external capacitor at AREF pin

This is the requirment for AREF to connect to ground...
My intend is to coneect a 14pF cap then to ground, am I right?

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

Quote:

My intend is to coneect a 14pF cap then to ground, am I right?

What does the datasheet say? No one minds you asking questions but if you start trolling these boards with endless questions about every last detail contained in the datasheet (such as you already did in the timer tutorial) then action will be taken.

Here are some excerpts from a typical AVR datasheet found by searching for "AREF":

Quote:
The ADC converts an analog input voltage to a 10-bit digital value through successive approxi-
mation. The minimum value represents GND and the maximum value represents the voltage on
the AREF pin minus 1 LSB. Optionally, AVCC or an internal 1.1V reference voltage may be con-
nected to the AREF pin by writing to the REFSn bits in the ADMUX Register. The internal
voltage reference may thus be decoupled by an external capacitor at the AREF pin to improve
noise immunity.

Quote:
The reference voltage for the ADC (VREF) indicates the conversion range for the ADC. Single
ended channels that exceed VREF will result in codes close to 0x3FF. VREF can be selected as
either AVCC, internal 1.1V reference, or external AREF pin.

AVCC is connected to the ADC through a passive switch. The internal 1.1V reference is gener-
ated from the internal bandgap reference (VBG) through an internal amplifier. In either case, the
external AREF pin is directly connected to the ADC, and the reference voltage can be made
more immune to noise by connecting a capacitor between the AREF pin and ground. VREF can
also be measured at the AREF pin with a high impedance voltmeter. Note that VREF is a high
impedance source, and only a capacitive load should be connected in a system.

If the user has a fixed voltage source connected to the AREF pin, the user may not use the other
reference voltage options in the application, as they will be shorted to the external voltage. If no
external voltage is applied to the AREF pin, the user may switch between AVCC and 1.1V as ref-
erence selection. The first ADC conversion result after switching reference voltage source may
be inaccurate, and the user is advised to discard this result.

Moderator

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

First of all, great tutorial. I think a good extension to this tutorial may be how to sample at slower sampling frequencies. Thanks for the tutorial though!

I do have one small question. I'm using the Atmega644P and reading the datasheet, I realise that I will have to use auto-triggering with a timer since I want to sample at about the 8Khz range.

My question is, is it possible to use one timer to trigger both its timer interrupt on compare match and to also trigger the ADC? I haven't read anything explicitly about this scenario in the datasheet.

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

Quote:
My question is, is it possible to use one timer to trigger both its timer interrupt on compare match and to also trigger the ADC?
Yes, they are not mutually exclusive.

Regards,
Steve A.

The Board helps those that help themselves.

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

Great, thanks Koshchi.

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

Hello,

How do I handle separate Interrupt for ADC0 and ADC1(my output is different for both inputs)?

Thanks,
Nilesh

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

You can do something like this:

ISR(ADC_vect)
{
   if (ADMUX & (1<<MUX0))
   {
      // Code for channel 1 (well, odd numbers)
   }
   else
   {
       // Code for channel 0 (even)
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your reply @snigelen

I have changed my code according your above code, see below my code but it still not working, my code before ISR is same as start of this tutorial need to change anything in that part? Please let me know.

ISR(ADC_vect) 
{ 
   if(ADMUX & (1<<MUX0))	//Joystick X	
    {
	if(ADCH < 100)
	{
	PORTB |= (1 << 0);       // motor1 forward 
    PORTB &= ~(1 << 1);      // motor1 forward
    }
	else if(ADCH > 150) 
	{ 
    PORTB |= (1 << 1);       // motor1 reverse 
    PORTB &= ~(1 << 0);      // motor1 reverse 
    }
	else if((ADCH <= 100) && (ADCH >= 150)) 
   	{
	PORTB &= ~(1 << 0);       // motor1 stop (Joystick center position) 
    PORTB &= ~(1 << 1);       // motor1 stop (Joystick center position)
    }
	}                         //end of coding for ADC0
	
	else if(ADMUX & (1<<MUX1)) //Joystick Y
	{
	if(ADCH < 100)
	{
	PORTB |= (1 << 2);       // motor2 forward 
    PORTB &= ~(1 << 3);      // motor2 forward
    }
	else if(ADCH > 150) 
	{ 
    PORTB |= (1 << 3);       // motor2 reverse 
    PORTB &= ~(1 << 2);      // motor2 reverse 
    }
	else if((ADCH <= 100) && (ADCH >= 150)) 
   	{
	PORTB &= ~(1 << 3);       // motor2 stop (Joystick center position) 
    PORTB &= ~(1 << 2);       // motor2 stop (Joystick center position)
    }
	}                         //end of coding for ADC1 

} 

Thanks,
Nilesh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   if(ADCH < 100) 
   { 
    } 
   else if(ADCH > 150) 
   { 
   else if((ADCH <= 100) && (ADCH >= 150)) 
      { 
    } 

Sorry but how do you ever see it entering the third clause of this block?

Was that third clause supposed to capture readings between 100 and 150? If so why does it need a conditional test at all - why not just else?

Last Edited: Tue. Jul 27, 2010 - 03:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Sorry but how do you ever see it entering the third clause of this block?

Was that third clause supposed to capture readings between 100 and 150? If so why does it need a conditional test at all - what not just else?

Yes true only else will work, I'm not just new to AVR new to C too! :D

so other code is OK? for separate interrupt handling?

Thanks,
Nilesh

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

I followed your example but am having a bit of problem.

https://www.avrfreaks.net/index.p...

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

thank you so much ^^

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

On a scale of 1 - 10. 10 being a first rate tutorial where you come away knowing how to apply what you just learned and 0 being an utter waste of time. This tutorial is so low on the scale Im ashamed to post a score.. although.. you definitely get a big 10 for effort and Im grateful for that.

I mean.. the sign on the door does say "for noobs" and me being a noob.. im thinking.. hmm swell.. Im really gonna learn something here because its designed for noobs like me, right? WELL.. WRONG! I DONT GET IT.

in case you ask.. "what?"

Oh ok.. Lets say (for starters) Im using the atmega328p - which I am - and my project forces me to use PORTB. Some of these pins will have to be outputs and some inputs. Well.. just so happens the crystal pins of PORTB are smack dab in the middle so I have to leave those alone and change the others as needed according to their purpose. Gee.. no problem... WRONG!! WRONG WRONG WRONG.

What Im getting at is that on MIKROC.. you set individual DDR bits with one instruction.. something like..

DDRB.B5 = 1; // set pin 5 on PORTB for output 0 for input

And then I open up the "NEW AND IMPROVED" avrstudio with 2 whole brand new service packs attached.. AND SHAAZAM! ITS THE SAME "OLD HASH" IT WAS 2 YEARS AGO!! which was the last time I opened it up and was so disgusted I deleted it immediately.

Is ATMEL's argument.. "well what do you expect.. its free" duh..?

I mean if you offer me the option of this:

DDRB.B5 = 1; // set pin 5 on PORTB for output
PORTB.B5 = 1; // turn on pull up resistors

to HASH like this:

DDRB &= (1 >> 4) // this is 469 to 98284 do you read? roger over?
PORTB |= (1 << 2); // Turn on LED1
PORTB &= ~(1 << 0); // Turn off LED2

Ill take the prior. Meaning.. Im sticking with MIKROC when I need to get things done.

Now let me state clearly why Im so angry. Im angry because Im very grateful to Atmel for even coming up with such a cool chip like the atmega328p that opens doors and so i naturally want to stick with atmel in everything.. BUT I OPEN UP AVRSTUDIO AND ITS A BLOODY STICKY GOOEY MESS!

The only reason I even opened up AVRSTUDIO again in the first place was to get at the debugger which is better than MIKROC's debugger ""ALL THE WAY AROUND"". But even the debugger has bugs in it. It reminds me of the opening scene of the movie "a scanner darkly". A big gooey icky mess. How a company like ATMEL can come up with such a BRILLIANT chip structure and fail so miserably at the software is well.. is like being forced to watch old mexican movies in black and white on a $500 color monitor. I take that back.. there are things I dont want to accidentally invoke.

There's another serious problem here.. lets say I need to whip up some code to do some fast tests.. like say I want to try out a new sonar device and need to triangulate vectors. No doubt Ill need some trig and stuff like that. Ok, here we are in AVRSTUDIO. Hmm gee... im using a GLCD 128x64 lcd.. lets see now.. where is that library? Must be where the libraries are.. duh... TICK TOCK. have to "TRACK DOWN" the appropriate library that WILL GET THE JOB DONE. TICK TOCK..

Ahhh.. who knows. I guess Ill just use AVRSTUDIO's for debugging ONLY WHEN I HAVE GOBS AND GOBS OF EXCESS DOWN TIME. I know what.. Ill make a template with all the libraries in it.. yeeeech.. reminds me of microsoft office yuk.

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

@wlewis: And what the f#@k does any of your post have to do with this tutorial? You say that the tutorial is crap, then you tear up Atmel about AVR Studio and never mention the tutorial again.

Quote:
ITS THE SAME "OLD HASH" IT WAS 2 YEARS AGO!!
So you have been a noob for 2 years? Rather slow learner, aren't you.

Quote:
to HASH like this:
That HASH is called the C language. Get used to it.

DDRB &= (1 >> 4)

And this one shows that you have no clue about what the code does. Besides, this is a property of the compiler, not the IDE.

Quote:
BUT I OPEN UP AVRSTUDIO AND ITS A BLOODY STICKY GOOEY MESS!
Then don't use it. Again, there are alternatives. Choose whatever IDE you want.

Quote:
lets see now.. where is that library?
A library in what language? Assembler since that is the only language that AVR Studio comes with? Which graphic driver chip does your display use? There are several.

Regards,
Steve A.

The Board helps those that help themselves.

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

This idiotic diatribe has nothing to do with the tutorial you have hijacked onto the end of. Tell me what you want the thread called and I'll split this off into a separate thread and move it to an appropriate forum.

Moderator.

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

Ohhh.... Sometimes programming is a little hard. Especially for microcontrollers. And I don't want hard. I want easy. I'm pissed for not getting easy. And I don't like compilers following language standards. Because that makes prevents the easy I want.

I wonder: Have you posted at the Micro C forums about them not supplying a better debugger with their product so that you can be relieved of the hash in AVR Studio altogether? With the same attitude, and tone?

Supplying a given library is much esier when the hardware ca be assumed, as for the MicroC tool that can assume the displays on the EasyAVR and BIGAVR boards.

And why this sudden outburst? Why not simply stay with MicroC? Demo limit reached?

[Just had to stick this onto the thread. Moderator: This will of-course go along with the rest of the "break-out".]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I blame "No child left behind".

Stealing Proteus doesn't make you an engineer.

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

Thank You!
Now i can scroll knight rider leds by myself with potentiometer :D:D:D:D

Estonia, Otepää is the place where you can find me...

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

Dear all,

The tutorial let me clearer about interrupts.
Thanks a lot.

I'd like to ask,from the source code with interrupt,
the for loop is empty. Do you mean that if I write something inside the for loop, it can run the program(in the for loop) and at the same time it is running the ISP loop?

Thanks for replying

songying

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

What is "the ISP loop"? Do you mean the ISR? That is not a loop, it is a function that is called when the interrupt happens. When the ISR function is not running, then yes, the AVR will be doing whatever is inside the for loop.

Regards,
Steve A.

The Board helps those that help themselves.

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

sorry,it's ISR.
Which means that it is impossible to run the thing in the for loop and at the same time running the ISR?

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

No, the opposite. That is the whole point of using interrupts. You have a main loop that is running code, but is occasionally interrupted to run an ISR.

Regards,
Steve A.

The Board helps those that help themselves.

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

ok...So now, I’d like to ask for interrupt, if I write the code below, what does it means?

void main()
{
 unsigned char data;

 // Initialize the USART
 InitUSART(12);

 // Initialize ADC
 InitADC();

ReadADC(0);

 while(1)
 {
  // Read data from ADC 
  ReadADC(0);
  }
}

ISR(ADC_vect)
{
data=ReadADC(0);
USARTWriteChar(data);
}

From my understanding, does it means that when ADC complete convert the data, the ISR function will be run. Then it will run the while(1) loop again and after that it runs the ISR function. This process repeats.
Am I right?

Last Edited: Sat. Oct 23, 2010 - 07:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are reading the ADC both in the ISR and in the main loop...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

yes, so does it means that ADC converts and at the same time USART sending the data?

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

It means that you read a value from the ADC, in the main loop, that you never use and just throw away..

Correctly set up you can have the ADC do a conversion at the same time that the USART is sending data - but the code above does not do that.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Hello, im starting to learn how to use AVR, so, please go easy on me.

Here´s the problem:

I copied the last code from the tutorial ( the one that uses the "interrupt") and built it on AVR studio.
everything went ok.

So, i simulated it at AVR Simulator IDE, and then, i faced two problems.

1- lets say that when i start to simulate, the F0 pin is high, then the G0 pin goes high, and E2 stays low. all rigth. If the F0 pin starts at low, the opposite situations happens, like desired.
BUT, if i change the state of the pin F0 at the middle of the simulation, the situation of pins G0 and E2 dont change. Its like the program is only cheking the state of pin F0 one time, at the beggining of the simulattion.

2-Well, in problem number 1, i used logic states in the input pin F0. but its an analog to digital converter, so i want to use the analog entry right? But how can i do it at AVR Simulator IDE? I mean, i change it to analog mode, and slide the bar, but i cant see any changes.
For example, if i put the oscilloscope at pin F0, and change the values fo the input slidding the analog bar, i can´t see any changes at oscilloscope. I read somewehre that the osciloscope only shows logic states, but if i put the analog value at max, shoudnt the oscilloscope change to high? (it is always at zero, when i use analog entrys).

The combination of error 1 and 2, makes me unabble to see the ADC happening.

Im sorry for english errors, and for stupid questions, but im new at this, and need some help.

Thx guys.

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

Sorry for double post.

Ok, i was able to make it work at ATtiny45.

I realized that i cant make free running work, and i have no idea why.
Thing is, at free running mode ADSC never gets clear rigth?
well, it doesnt work for me. after frist conversion ADSC goes low (in free running mode), and i have to "manually" set it again.
anyone have a clue for that?

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

Show us the code you used to initialize the ADC.

Regards,
Steve A.

The Board helps those that help themselves.

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

Here it is

#include 
#include  

int main(void)
{
  DDRB |= (1 << 1);  //PINB.1 OUTPUT
  DDRB |= (1 << 2);  //PINB.2 OUTPUT
  //configurando o ADC
   ADCSRA |= (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 6 - 166.66KHz sample rate @ 1MHz
   ADMUX &= ~(1 << REFS0);  
   ADMUX &= ~(1 << REFS1);  //REFERENCE VOLTAGE-->VCC; UNNECESSARY
   ADMUX &= ~(1 << MUX0);
   ADMUX &= ~(1 << MUX1);
   ADMUX &= ~(1 << MUX2);
   ADMUX &= ~(1 << MUX3);  //ANALOG INPUT AT PINB.5, MUX 0,1,2,3 EQUALS ZERO; UNNECESSARY.
   ADMUX |= (1 << ADLAR);  //  8 BIT RESOLUTON.

   ADCSRA |= (1<<ADATE);  // "AUTO TRIGGER ENABLE"   
   ADCSRB &= ~(1 <<ADTS0);
   ADCSRB &= ~(1 <<ADTS1);
   ADCSRB &= ~(1 <<ADTS2); //FREE RUNING; UNNECESSARY.

   ADCSRA |= (1 << ADIE);  // Enable ADC Interrupt --> BEFORE sei().
   sei();                  //ACTIVATE GLOBAL INTERRUPT

   ADCSRA |= (1 << ADEN);  // ACTIVATE ADC
   ADCSRA |= (1 << ADSC);  // STARTS ADC

while (1)  // ETERNAL LOOP.
 { 
 }

}

ISR(ADC_vect) //INTERRUPT FUNCTION
 {
 if(ADCH < 50)
      {
         PORTB |= (1 << 1); // Turn on LED1
         PORTB &= ~(1 << 2); // Turn off LED2
      }
      else
      {
         PORTB &= ~(1 << 1); // Turn off LED1
         PORTB |= (1 << 2); // Turn on LED2
      }	  
 }   

when i check at AVR Studio, ADSC goes low after frist conversion.
please tell me what im doing wrong =(

Pages

Topic locked