| Author |
Message |
|
|
Posted: Mar 21, 2011 - 02:45 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
Hi guys!
I have a problem with the A/D.I wrote a program that takes an input 0-5v and gives out a PWM 10%-90% duty cycle.The result where the led was shining with a cerain brightness thought i was adjusting the input voltage with a pontesiometer.So i took the progam piece by piece.
I wrote a simple program for the A/D and the outout response(PB3,ADCH,ADCL) was zero,nothing.
The code is here with comments if anyone can see any mistakes please let me know..
etc:i'm using AVR studio 4 and AVR mega 16
thanks
Code:
#include<avr/io.h>
#include<stdlib.h>
int main(void)
{
int i;
DDRA=0xFE; //set A0 input
DDRB|=_BV(PB3); //set B3 output
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
//enableand prescaleprescale
ADMUX=0x40; //use A0 input AVcc at Aref pin
ADCSRA=(1<<ADSC); //start conversion
for(i=1;i<20;i++) //do 19 times
{
PORTA^=(1<<0); //toggle input
if (~ADCSRA&(1<<ADSC)); //check the conversion
{
ADCSRA=(1<<ADSC)|(1<<ADEN); //start a new one
}
}
return 0;
}
|
|
|
| |
|
|
|
|
|
Posted: Mar 21, 2011 - 02:50 PM |
|


Joined: Apr 16, 2001
Posts: 3522
Location: Phoenix, Arizona
|
|
| Where in this code are you reading back ADCH/ADCL? |
|
|
| |
|
|
|
|
|
Posted: Mar 21, 2011 - 03:14 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
return 0;
Where do you think you are returning to? |
|
|
| |
|
|
|
|
|
Posted: Mar 21, 2011 - 03:23 PM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
|
Quote:
//do 19 times
And ONLY 19 times. After that your program ends.
Code:
ADCSRA=(1<<ADSC)|(1<<ADEN); //start a new one
But also overwrite your ADPSx bits so that the conversion becomes faster than the ADC can handle.
Quote:
//use A0 input AVcc at Aref pin
Not sure what this comment means. You can set AVCC as the reference, or AREF as the reference. There is no option to set AVCC at the AREF pin. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 21, 2011 - 03:24 PM |
|


Joined: Jul 18, 2005
Posts: 62304
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Code:
ADCSRA=(1<<ADSC)|(1<<ADEN); //start a new one
//++ and lose previous setting of ADPS bits !!
|
_________________
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 06:39 AM |
|

Joined: Aug 29, 2010
Posts: 291
Location: Dharamshala, India
|
|
[url]I wrote a simple program for the A/D and the outout response(PB3,ADCH,ADCL) was zero,nothing. [/url]put the code where are you taking the response. I cannot see you reading ADC --- 10 bit value.
Also check your circuit connection.
Put an while(1) at the end of the programe. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:09 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
dksmall wrote:
Where in this code are you reading back ADCH/ADCL?
so i have to store it somewhere like this:
DDRB=0xFF;
value=ADCW;
PORTB=value/4; //1024/4=256 10bit to 8 bit
//or
PORTB=ADCW/4;[code] |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:11 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
theusch wrote:
Quote:
return 0;
Where do you think you are returning to?
most of the examples i've seen have return 0;
so i thought it was standard procedure,thanks i'll look in to it |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:18 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Koshchi wrote:
Quote:
//do 19 times
And ONLY 19 times. After that your program ends.
Code:
ADCSRA=(1<<ADSC)|(1<<ADEN); //start a new one
But also overwrite your ADPSx bits so that the conversion becomes faster than the ADC can handle.
Quote:
//use A0 input AVcc at Aref pin
Not sure what this comment means. You can set AVCC as the reference, or AREF as the reference. There is no option to set AVCC at the AREF pin.
with this command i dont overwrite gotcha.
ADCSRA|=(1<<ADSC)|(1<<ADEN);
sorry there i mean Vcc at the A/D refrence voltage (5v)
thanks for the reply |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:23 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
katochd46 wrote:
[url]I wrote a simple program for the A/D and the outout response(PB3,ADCH,ADCL) was zero,nothing. [/url]put the code where are you taking the response. I cannot see you reading ADC --- 10 bit value.
Also check your circuit connection.
Put an while(1) at the end of the programe.
I'll check it tomorow because my teacher has the board
thanks for reply |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:26 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
| thanks guys for the replys,i'll get it working and post it.(i did it 19 times because i wanted to test the program from the AVR studio) |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:47 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Code:
#include<avr/io.h>
#include<stdlib.h>
#include<util/delay.h>
int main(void)
{
DDRA=0xFE; //set A0 input
DDRB=0xFF; //set B output
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
//enable and prescale
ADMUX=0x40; //use A0 input,Vcc at Aref pin
ADCSRA=(1<<ADSC); //start conversion
for(;;) //do forever
{
PORTA^=(1<<0); //toggle input
_delay_ms(50);
PORTB=ADCW/4; //take result from conversion
if (~ADCSRA&(1<<ADSC)); //check the conversion
{
ADCSRA|=(1<<ADSC)|(1<<ADEN); //start a new one
}
}
}
Is this correct?
sorry for asking because i can't test it untill tomorow |
Last edited by thodoris46 on Mar 22, 2011 - 02:22 PM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 01:52 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
Is this correct?
Quote:
I cannot see you reading ADC --- 10 bit value.
|
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 02:21 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
|
|
|
|
Posted: Mar 22, 2011 - 02:56 PM |
|


Joined: Sep 04, 2002
Posts: 21261
Location: Orlando Florida
|
|
| A c program running on a computer with an operating system like linux or windows loads the binary from disk to ram, then 'calls' it like a subroutine, and when it returns, there is a returned value 'ok' or 'error' or something. This is why main is supposed to return an int, and why there should be a return 0 or something at the end of main. On a microcontroller with no operating system, the bit about load the program and call it doesnt happen, so there isnt really a call, so main shouldnt return. No where to return to. But Richard Stallman wrote the free c compiler that everyone and his uncle tries to shoehorn into every new computer and microcontroller, so you have to sort of know how the compiler expects things to be. |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 03:04 PM |
|

Joined: Mar 09, 2011
Posts: 44
|
|
|
bobgardner wrote:
A c program running on a computer with an operating system like linux or windows loads the binary from disk to ram, then 'calls' it like a subroutine, and when it returns, there is a returned value 'ok' or 'error' or something. This is why main is supposed to return an int, and why there should be a return 0 or something at the end of main. On a microcontroller with no operating system, the bit about load the program and call it doesnt happen, so there isnt really a call, so main shouldnt return. No where to return to. But Richard Stallman wrote the free c compiler that everyone and his uncle tries to shoehorn into every new computer and microcontroller, so you have to sort of know how the compiler expects things to be.
Thanks for this comment! Now I understand what it means return 0 or more. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 03:08 PM |
|

Joined: Mar 09, 2011
Posts: 44
|
|
|
thodoris46 wrote:
katochd46 wrote:
[url]I wrote a simple program for the A/D and the outout response(PB3,ADCH,ADCL) was zero,nothing. [/url]put the code where are you taking the response. I cannot see you reading ADC --- 10 bit value.
Also check your circuit connection.
Put an while(1) at the end of the programe.
I'll check it tomorow because my teacher has the board
thanks for reply
You still haven't inserted the
Code:
while(1);//loop (for as long as power on)
{
}
can you please post the final working code for the sake of spreading information and ideas. I learn from them. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 03:34 PM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
|
Quote:
You still haven't inserted the
Code:
while(1);//loop (for as long as power on)
{
}
Yes he has, under the guise of a for( ; ; ).
Code:
PORTB=ADCW/4; //take result from conversion
if (~ADCSRA&(1<<ADSC)); //check the conversion
{
ADCSRA|=(1<<ADSC)|(1<<ADEN); //start a new one
}
Why are you getting the result before you checked to see that the conversion is complete? Since you have a 50ms delay just before, it likely is, but as soon as you take out that delay your code will fail. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 04:39 PM |
|

Joined: Mar 09, 2011
Posts: 44
|
|
| [quote="Koshchi"]
Quote:
You still haven't inserted the
Code:
while(1);//loop (for as long as power on)
{
}
Yes he has, under the guise of a for( ; ; ).
sorry I overlooked it. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 10:32 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
bobgardner wrote:
A c program running on a computer with an operating system like linux or windows loads the binary from disk to ram, then 'calls' it like a subroutine, and when it returns, there is a returned value 'ok' or 'error' or something. This is why main is supposed to return an int, and why there should be a return 0 or something at the end of main. On a microcontroller with no operating system, the bit about load the program and call it doesnt happen, so there isnt really a call, so main shouldnt return. No where to return to. But Richard Stallman wrote the free c compiler that everyone and his uncle tries to shoehorn into every new computer and microcontroller, so you have to sort of know how the compiler expects things to be.
very good comment thank you |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 10:39 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Koshchi wrote:
Quote:
You still haven't inserted the
Code:
while(1);//loop (for as long as power on)
{
}
Yes he has, under the guise of a for( ; ; ).
Code:
PORTB=ADCW/4; //take result from conversion
if (~ADCSRA&(1<<ADSC)); //check the conversion
{
ADCSRA|=(1<<ADSC)|(1<<ADEN); //start a new one
}
Why are you getting the result before you checked to see that the conversion is complete? Since you have a 50ms delay just before, it likely is, but as soon as you take out that delay your code will fail.
by putting the delay i am making sure that the conversion is complete because a conversion needs max 15 clock cycles,i put a 50ms delay to be sure.
Although you are right i dont think it's a problem.. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 10:45 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Code:
#include<avr/io.h>
#include<stdlib.h>
int main(void)
{
DDRA=0xFE; //set A0 input
DDRB=0xFF; //set B output
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);
//enable and prescale
ADMUX=(1<<REFS0)|(1<<ADLAR);
//use A0 input,Vcc at Aref pin,left adj.result
ADCSRA=(1<<ADSC); //start conversion
for(;;) //do forever
{
PORTA^=(1<<0); //toggle input
if (!(ADCSRA&(1<<ADSC))) //check the conversion
{
PORTB=ADCH; //take result from conversion
ADCSRA|=(1<<ADSC)|(1<<ADEN); //start a new one
}
}
return 0;
}
|
Last edited by thodoris46 on Mar 24, 2011 - 03:51 PM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 10:54 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
if (~ADCSRA&(1<<ADSC));
That is utter nonsense.
1) What is that bitwise complement ~ doing in there?
2) With no parentheses, do you have the C operator precedence table memorized?
3) Tell us more about what happens with the semi-colon ; at the end of that line. |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 10:56 PM |
|


Joined: Sep 04, 2002
Posts: 21261
Location: Orlando Florida
|
|
| My opinion, based on several decades of experience writing programs that get sold in gizmos, is make a subroutine/function to read an a/d channel, return the value. Write a subroutine to check for keyboard hit and return a boolean. Write a subroutine to get the char from the uart and return it. Write a subroutine to send a char to the uart. None of this inline stuff in main. One might consider that main is a loop of subroutine calls. Check for char waiting. If true, get the char. If its an X call function y. |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Mar 22, 2011 - 11:38 PM |
|

Joined: Oct 29, 2006
Posts: 2651
|
|
|
bobgardner wrote:
On a microcontroller with no operating system, the bit about load the program and call it doesnt happen, so there isnt really a call, so main shouldnt return. No where to return to. But Richard Stallman wrote the free c compiler that everyone and his uncle tries to shoehorn into every new computer and microcontroller, so you have to sort of know how the compiler expects things to be.
To me, it seems a wonder of the world.
I'm amazed that it exists at all.
Actually, main is not required to return an int.
IIRC main is not required at all in a
freestanding environment, e.g. an AVR.
We don't use --freestanding because it removes
much knowledge of the C library from the compiler.
IIRC it would not be allowed to replace
an memcpy( ) with equivalent inline code.
To me, the rule seems overly strict.
Why not let the compiler assume that anything
declared in a system header file having the same name
as a standard C function is a standard C function?
That said, I think one could compile the file with
main with --freestanding and compile the rest hosted. |
_________________ Michael Hennebry
Iluvatar is the better part of Valar.
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 11:54 AM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
theusch wrote:
Quote:
if (~ADCSRA&(1<<ADSC));
That is utter nonsense.
1) What is that bitwise complement ~ doing in there?
2) With no parentheses, do you have the C operator precedence table memorized?
3) Tell us more about what happens with the semi-colon ; at the end of that line.
sorry i'be more careful next time,i had many mistakes in my code..
i changed it to
if (!(ADCSRA&(1<<ADSC))) |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 12:25 PM |
|


Joined: Jul 18, 2005
Posts: 62304
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
if (!(ADCSRA&(1<<ADSC)))
Are you sure you want to do that. The more usual sequence is:
Code:
// wait for ADSC bit to go from 1 to 0 to show end of conversion
while(ADCSRA&(1<<ADSC));
Also if you are going to throw away two bits with "ADCW/4" then why not simply use ADLAR ? |
_________________
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 01:33 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Quote:
Also if you are going to throw away two bits with "ADCW/4" then why not simply use ADLAR ?
I'm not throing them away i'm prescaling the value to 8 bit.
like if we had
1100001111=783 10 bit
783/4=195,75=11000011 8bit |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 02:03 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
My opinion, based on several decades of experience writing programs that get sold in gizmos, is make a subroutine/function to ...
And the smallest AVR you've ever seen is a Mega32. That's hardly even a >>micro<< controller. (Macro-controller?)
But as you know I'm a heretic on this. Yes, I use functions when I feel they are useful. But not just for the sake of keeping the main loop small--mine is huge in my biggest apps, mostly because of an extensive menu system and display panel build with lots of states.
Anyway, a real app will have interrupt-driven USART for sure. And probably ADC and timers. So my getchar() really peeks into a buffer; I don't have my AVR sit there tapping its toe waiting for an ADC conversion to start and complete.
With the above, I feel I pack a lot into a Mega48. My suspicion is that my program ends up tighter than the full modular approach but I've got no hard data on that.
As the app gets larger, into that Mega32 class, I indeed will build in a lot more structure from the beginning, in that my head can't hold all the details of the whole app anymore. |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 03:49 PM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
|
Quote:
1) What is that bitwise complement ~ doing in there?
2) With no parentheses, do you have the C operator precedence table memorized?
The following two "if" statements are equivalent:
Code:
if (~ADCSRA & (1 << ADSC))
...
if (!(ADCSRA & (1 << ADSC))
The "~" and the"&" have the same precedence, so the "~" will be done first.
Quote:
Are you sure you want to do that.
Once the errant semicolon was removed and the read of ADCW was moved to inside the "if", there is really nothing wrong with the code since the "if" is wrapped in an infinite loop. The "if" will be continually be evaluated. Any time the "if" evaluates to true, the value will be read and the next conversion started. It even has the advantage over "the more usual sequence" in that it does not block and allows other code to be run during the conversion.
Just because the solution is different from the norm doesn't make it "utter nonsense" or wrong (though obviously the semicolon was incorrect). |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 03:54 PM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
|
Quote:
I'm not throing them away i'm prescaling the value to 8 bit.
Since after the pre-scale you no longer have the two bits, you are, in fact, throwing them away (and no, you don't get 195.75, you get 195). And the easiest way to pre-scale/throw away those bits is to use the ADLAR bit as Cliff suggested. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 04:04 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
The "~" and the"&" have the same precedence, so the "~" will be done first.
??? http://www.difranco.net/cop2220/op-prec.htm And different associativity as well.
I knew/know that ~ has high precedence, but the way OP is whacking at these expressions I'd feel better seeing parentheses (and get in the habit).
(BTW my compiler generates better code for the ! version than the ~ version, both with ADCSRA low and high addresses.) |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 07:06 PM |
|

Joined: Nov 17, 2004
Posts: 13840
Location: Vancouver, BC
|
|
The fact remains that the code is perfectly correct.
Quote:
(BTW my compiler generates better code for the ! version than the ~ version, both with ADCSRA low and high addresses.)
Irrelevant. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 23, 2011 - 07:32 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
The fact remains that the code is perfectly correct.
The fact remains that the operators do not have the same precedence or associativity.
The fact remains that while I'm a veteran C coder and "pretty much" know the precedence, without the parens I had to pull up a table and work through it. I don't want to do that on a daily basis, so I order parens in bulk quantity. |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 03:47 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Koshchi wrote:
Quote:
I'm not throing them away i'm prescaling the value to 8 bit.
Since after the pre-scale you no longer have the two bits, you are, in fact, throwing them away (and no, you don't get 195.75, you get 195). And the easiest way to pre-scale/throw away those bits is to use the ADLAR bit as Cliff suggested.
Maybe there's something i'm not getting but the manual says:By default, the result is presented right adjusted, but can optionally be presented left adjusted by setting the ADLAR bit in ADMUX.If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read ADCH.
so if we adjust the ADLAR the first 8 bits go to the ADCH the other 2 to ADCL which we ignore.And it has the same result by dividing the number by 4.You are right guys i did the math jusy now...
Thanks guys,i'll change it |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:06 PM |
|


Joined: Sep 04, 2002
Posts: 21261
Location: Orlando Florida
|
|
| Doing an 8 bit conversion takes 2 a/d clks less than a 10 bit conversion, which usually takes 13 clks at 200kHz (5usec per bit 65usec per sample). The 8 bit conversion should take 55usec. Use that extra 10usec wisely! (15.3kHz sample rate vs 18.2kHz) |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:08 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
Doing an 8 bit conversion takes 2 a/d clks less than a 10 bit conversion,
OK, Bob--tell me how to do an "8 bit conversion" on an AVR8? [Hint: there is no such thing, and there are no saved ADC clock cycles.] |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:10 PM |
|


Joined: Sep 04, 2002
Posts: 21261
Location: Orlando Florida
|
|
| Huh? Doesnt setting the ADLAR short cycle the successive approximation at 8 bits? |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:18 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
Huh? Doesnt setting the ADLAR short cycle the successive approximation at 8 bits?
No, Bob. It is just as it says, and was also said earlier in this thread. "LAR" is "left-adjusted result". |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:26 PM |
|


Joined: Sep 04, 2002
Posts: 21261
Location: Orlando Florida
|
|
| OK, I guess the converter is always going to try for 10 bits, but in the example calc I gave (65usec for 10bit, 55usec for 8bit), you could start conv, read after 55usec, then restart conv, and be confident you were getting an 8 bit result. I think. |
_________________ Imagecraft compiler user
|
| |
|
|
|
|
|
Posted: Mar 24, 2011 - 04:32 PM |
|


Joined: Jul 18, 2005
Posts: 62304
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
then restart conv
How do you do that? You set ADSC and it remains set until a conversion completes. Setting it to 1 again part way through is not going to have any effect? I guess your best hope is to pick F_CPU and the ADPS bits so that the ADC clock runs at 10/8 * 200kHz (ie just a bit too fast) then wait for a complete conversion but knowing the bottom two bits are inaccurate as they will be discarded by the ADLAR anyway. |
_________________
|
| |
|
|
|
|
|
Posted: Mar 25, 2011 - 02:28 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
clawson wrote:
Quote:
then restart conv
How do you do that? You set ADSC and it remains set until a conversion completes. Setting it to 1 again part way through is not going to have any effect? I guess your best hope is to pick F_CPU and the ADPS bits so that the ADC clock runs at 10/8 * 200kHz (ie just a bit too fast) then wait for a complete conversion but knowing the bottom two bits are inaccurate as they will be discarded by the ADLAR anyway.
You're talking about the ADEN or ADSC.Because you have to set them again to star a new conversion it's not free running mode.(i'm not sure about the ADEN,but setting it again i guess it does no harm). |
|
|
| |
|
|
|
|
|
Posted: Mar 25, 2011 - 03:29 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
I wrote a program conecting the A/D and Timer 0.They both take clock source from CPU 1Mhz,the A/D prescales with 4 and timer0 prescales with 64 so the timing is:
F_A/D=250Khz T_A/D=4μsec T(conversion)=4*15=60μsec
F_timer=15,6Khz T_timer=64,1μsec
-4*15:are the clock cycles needed to do a conversion and prepare for a new one
-when a period of the timer is finished(64,1μsec)the A/D will have the value ready to place it in OCR0,the timer restarts counting it will output a pulse when compare match is made,in the same time a conversion starts because it's triggered by the previous overflow of the timer.and goes on...
here is the code:
Code:
#include<stdlib.h>
#include<avr/io.h>
int main(void)
{
int value;
DDRB=0xFF; //outout
DDRA=0xFE; //input
TCCR0=0x7B; //Fast Pwm,inverting mode,prescale
ADCSRA=(1<<ADEN)|(1<<ADPS1); //enable,prescale
ADMUX=(1<<REFS0)|(1<<ADLAR); //refrence,left adj.
ADCSRA=(1<<ADSC); //do a dummy read out
while(!(ADCSRA&0x01)); //wait for dummy
SFIOR=(1<<ADTS2); //trigger source(overflow)
ADCSRA|=(1<<ADATE); //enable auto trigger
for(;;)
{
value=ADCH;
if((value<27)|(value>229)) //check for 10%~90%
{
//do nothing
else
OCR0=value;
}
}
return 0;
}
-i'm using mega 16,so the output bit for timer 0 is PB3
-i want the 10%~90% of the input.
please have a look and tell me what you think,thanks |
Last edited by thodoris46 on Mar 25, 2011 - 05:47 PM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Mar 25, 2011 - 04:52 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
please have a look and tell me what you think,thanks
I'm losing track of the purpose of the whole exercise. Auto trigger seems like overkill for this simple app.
1) AFAIK the above won't work as expected. You have to clear the trigger interrupt flag before it will trigger again.
1a) A "normal" way do this is to watch for the A/D complete either with an ISR or the flag, and then clear the trigger flag and the ADC flag if needed.
2) Why have the auto trigger setup every time though the main loop?
3) ADATE is set before the SFIOR bit(s). So you have initiated an auto-trigger with an arbitrary trigger source. In that case, when does a new value written to SFIOR take effect? I don't really care to analyze this--it is easy enough to just do the operations in an order that does not raise the question.
4) You are grabbing a new value every time through the loop and applying it. There is only going to be a new reading like every 100 times through the loop. After going through all the timing calculations--what is the point? Perhaps you have a reason to do all this. Why not just start a conversion, wait for it to complete, and apply the new value? |
|
|
| |
|
|
|
|
|
Posted: Mar 25, 2011 - 05:43 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
theusch wrote:
Quote:
please have a look and tell me what you think,thanks
I'm losing track of the purpose of the whole exercise. Auto trigger seems like overkill for this simple app.
1) AFAIK the above won't work as expected. You have to clear the trigger interrupt flag before it will trigger again.
1a) A "normal" way do this is to watch for the A/D complete either with an ISR or the flag, and then clear the trigger flag and the ADC flag if needed.
2) Why have the auto trigger setup every time though the main loop?
3) ADATE is set before the SFIOR bit(s). So you have initiated an auto-trigger with an arbitrary trigger source. In that case, when does a new value written to SFIOR take effect? I don't really care to analyze this--it is easy enough to just do the operations in an order that does not raise the question.
4) You are grabbing a new value every time through the loop and applying it. There is only going to be a new reading like every 100 times through the loop. After going through all the timing calculations--what is the point? Perhaps you have a reason to do all this. Why not just start a conversion, wait for it to complete, and apply the new value?
1)I'll place the interupts tomorow,i didn't now it needed to clear the flag
2)I took it outside the loop
3)you're right i thought the order was defrent,fixed it
4)i'll replace the for loop with a while loop and put the interrupt flag check inside the while,so the loop runs when it has too
thank you,i'll fix it tomorow |
|
|
| |
|
|
|
|
|
Posted: Mar 27, 2011 - 07:16 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Quote:
thank you,i'll fix it tomorow
Code:
#include<stdlib.h>
#include<avr/io.h>
int main(void)
{
int value;
DDRB=0xFF; //outout
DDRA=0xFE; //input
TCCR0=0x78; //Fast Pwm,inverting mode
ADCSRA=(1<<ADEN)|(1<<ADPS1); //enable,prescale
ADMUX=(1<<REFS0)|(1<<ADLAR); //refrence,left adj.
ADCSRA=(1<<ADSC); //do a dummy read out
while(!(ADCSRA&0x01)); //wait for dummy
SFIOR=(1<<ADTS2); //trigger source(overflow)
ADCSRA|=(1<<ADATE); //enable auto trigger
TCCR0|=(1<<CS01)|(1<<CS00); //prescale(timer on)
//when it overflows A/D is enabled things start to hapen
for(;;)
{
while(ADCSRA&&(1<<ADIF)); //while flag is set(conversion complete)
{
value=ADCH;
ADCSRA|=!(1<<ADIF); //clear flag
if((value<27)|(value>229)) //check for 10%~90%
{
//do nothing
else
{
OCR0=value;
}
}
}
}
return 0;
}
any comments are useful to me thanks![/code] |
Last edited by thodoris46 on Mar 28, 2011 - 01:34 PM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Mar 27, 2011 - 07:24 PM |
|


Joined: Jul 18, 2005
Posts: 62304
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
Your indentation style makes that almost impossible to follow. The whole point is that each time you use { you indent and each time you use } you outdent so the start/end of any statement block can easily be seen. Others may find this easier to follow:
Code:
#include<stdlib.h>
#include<avr/io.h>
#include<avr/interrupt.h>
int main(void)
{
int value;
//enable global interupts
DDRB=0xFF; //outout
DDRA=0xFE; //input
TCCR0=0x78; //Fast Pwm,inverting mode
ADCSRA=(1<<ADEN)|(1<<ADPS1); //enable,prescale
ADMUX=(1<<REFS0)|(1<<ADLAR); //refrence,left adj.
ADCSRA=(1<<ADSC); //do a dummy read out
while(!(ADCSRA&0x01)); //wait for dummy
SFIOR=(1<<ADTS2); //trigger source(overflow)
ADCSRA|=(1<<ADATE); //enable auto trigger
TCCR0|=(1<<CS01)|(1<<CS00); //prescale(timer on)
//when it overflows A/D is enabled things start to hapen
for(;;)
{
while(ADCSRA&&(1<<ADIF)); //while flag is set(conversion complete)
{
value=ADCH;
ADCSRA|=!(1<<ADIF); //clear flag
if((value<27)|(value>229)) //check for 10%~90%
{
//do nothing
else
OCR0=value;
}
}
}
return 0;
}
As I did that one of your problems became immediately obvious. You have an unbalanced "else" in the middle. I'm astonished your C compiler did not complain.
EDIT: thought as much - I lifted the unedited code from your post and passed it to avr-gcc. It said:
Code:
test.c: In function 'main':
test.c:39: error: expected '}' before 'else'
test.c: At top level:
test.c:45: error: expected identifier or '(' before 'return'
test.c:46: error: expected identifier or '(' before '}' token
make: *** [test.o] Error 1
So what's the point in asking for comments on code that won't even compile. I'd start by asking the C compiler if IT can see anything wrong first!
EDIT2: by the way I didn't read it in detail yet but this line is clearly wrong:
Code:
ADCSRA|=!(1<<ADIF); //clear flag
(I've never understood the attraction of using ADIF anyway, when ADSC does the job just as well and auto-clears) |
_________________
|
| |
|
|
|
|
|
Posted: Mar 28, 2011 - 01:29 PM |
|

Joined: Mar 02, 2011
Posts: 23
|
|
|
Quote:
(I've never understood the attraction of using ADIF anyway, when ADSC does the job just as well and auto-clears)
I used the ADSC to do a dummy read out(because 1st conversion needs 25 clock cycles)
I'm using auto trigger that's why i have to clear the flag.
You're right about compiling i have a problem intalling the program so i can't compile at home,i compile them when i go to my university lab.. |
|
|
| |
|
|
|
|
|