| Author |
Message |
|
|
Posted: Jun 04, 2011 - 02:20 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
Hi all, I want to read a multiple ADC input without using interrupt.CPU running at 8 Mhz
I use this sub:
Code:
uint16_t Read_ADC (uint8_t ch) {
ADMUX = (1<<REFS0); //AVCC as ADC Voltage Reference
ADCSRA = (1<<ADEN) | (1<< ADPS2); //enable ADC, prescale 16
ch = ch&0b00000111;
ADMUX |= ch;
ADCSRA |= (1<<ADSC);
while (!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
return ADC;
}
read the input value and in main:
Code:
int main() {
DDRB = 0xFF;
uint16_t ADC_result = 0;
int i;
USART_init();
adc_Init();
while (1) {
for (i = 0; i < 3; i++) { //start the scan...
ADC_result = Read_ADC(i); //and read the result
switch (i) { ...then i use the value to do something
.........
But nothing happens.
However if I remove the for loop and
Code:
ADC_result = Read_ADC(0);
i can read the ADC value.
Any suggestion?
thank you |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2011 - 02:23 PM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| Not enough context. Show more of the code and explain "nothing happens" and how you are observing that. |
_________________
|
| |
|
|
|
|
|
Posted: Jun 04, 2011 - 02:48 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
By now i just want to read a voltage on ADC0 and ADC1 and turn on/off a led.
Code:
nt main() {
DDRB = 0xFF;
uint16_t ADC_result = 0;
int i;
USART_init();
adc_Init();
while (1) {
for (i = 1; i < 3; i++) {
ADC_result = Read_ADC(i);
switch (i) {
case 1:
if (ADC_result < 120) {
PORTB = 0x01;
}
else if (ADC_result > 150) {
PORTB = 0x00;
}
case 2:
if (ADC_result < 120) {
PORTB = 0x01;
}
else if (ADC_result > 150) {
PORTB = 0x00;
}
}
}
}
return 0;
}
no led is turned on/off
Thank |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2011 - 05:06 PM |
|

Joined: Nov 17, 2004
Posts: 13853
Location: Vancouver, BC
|
|
|
Quote:
By now i just want to read a voltage on ADC0 and ADC1 and turn on/off a led.
Code:
for (i = 1; i < 3; i++) {
ADC_result = Read_ADC(i);
But this reads ACD1 and ADC2. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Jun 04, 2011 - 07:11 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
@koshch
you're right... But not working at all
Code:
for (i=0; i 2; i++)
i'll try another solution... |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2011 - 08:43 PM |
|

Joined: Aug 07, 2007
Posts: 1478
Location: Czech
|
|
|
|
|
|
|
Posted: Jun 04, 2011 - 08:58 PM |
|

Joined: Aug 07, 2007
Posts: 1478
Location: Czech
|
|
|
|
|
|
|
Posted: Jun 27, 2011 - 10:19 AM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
Thank you all...
Ok... Reading other posts it is better to use interrupt.
So that's my way:
Code:
/*
ATmega16 @ 8 Mhz
PORTA as ADC
PORTB leds
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
volatile uint8_t adc_result[8];
volatile uint8_t input = 0; // both var. volatite because shared by main and ISR ...clawson FAQ #1
void ADC_init(void);
int main(void) {
DDRB = 0xFF; // PORTB as Out
ADC_init(); //init ADC
sei(); // enable all interrupts
ADCSRA |= (1 << ADSC); // first ADC conversion
while (1) {
if (adc_result[0] > 150) {
PORTB = 0x01;
} else if (adc_result[0] < 150) {
PORTB = 0x00;
}
if (adc_result[1] > 150) {
PORTB = 0x02;
} else if (adc_result[1] < 150) {
PORTB = 0x00;
}
}
return 0;
}
ISR( ADC_vect ) {
adc_result[input] = ADCH; // input 0, first result, 8 bits
if (input < 8)
input++;
else
input = 0;
ADMUX |= input; // next input
ADCSRA |= ( 1 << ADSC ); // next conversion
}
void ADC_init() {
ADMUX |= (1 << ADLAR) | (1 << REFS0); // left adj. and AVcc as reference
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2); // Enable ADC, interrupt, prescaler 16
}
...but I can't see any led on.  |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 10:41 AM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
ADMUX |= input; // next input
You never clear the previous channel setting. Suggest you use:
Code:
ADMUX = (1 << ADLAR) | (1 << REFS0) | channel;
|
_________________
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 11:11 AM |
|

Joined: Nov 28, 2004
Posts: 3553
Location: San Diego, Ca
|
|
Also, one time code should be done... once . Put
Code:
ADMUX = (1<<REFS0); //AVCC as ADC Voltage Reference
ADCSRA = (1<<ADEN) | (1<< ADPS2); //enable ADC, prescale 16
in your adc_init() ( which you already did, so no need to repeat the same stuff ). It's just a waste of time / memory to do it the way you did .
Your code with the switch is not right, time to open your C book and look at that. |
_________________ 1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 07:35 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
Hello, when I start debuging the changed code
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
volatile uint8_t adc_result[8];
volatile uint8_t input = 0; // both var. volatite because shared by main and ISR ...clawson FAQ #1
int main(void) {
DDRB = 0xFF; // PORTB as Out
ADMUX |= (1 << ADLAR) | (1 << REFS0); // left adj. and AVcc as reference
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2); // Enable ADC, interrupt, prescaler 16
sei(); // enable all interrupts
ADCSRA |= (1 << ADSC); // first ADC conversion
while (1) {
if (adc_result[0] > 120) {
PORTB = 0x01;
} else if (adc_result[0] < 120) {
PORTB = 0x00;
}
if (adc_result[1] > 120) {
PORTB = 0x02;
} else if (adc_result[1] < 120) {
PORTB = 0x00;
}
}
return 0;
}
ISR( ADC_vect ) {
adc_result[input] = ADCH; // input 0, first result, 8 bits
if (input < 8)
input++;
else
input = 0;
ADMUX |= (input & 0x07); // next input and mask the bits
ADCSRA |= ( 1 << ADSC ); // next conversion
}
I can see in the I/O view no ADSC setted by
Code:
ADCSRA |= (1 << ADSC); // first ADC conversion
instruction
I think code is correct but I can't check where is my error or what I can't understand.
Thank you |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 07:41 PM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
I start debuging
Simulator or real hardware debugging? |
_________________
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 07:46 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
...real hardware debugging. I test hardware too and things work... i think it's a programming issue..
Thank you very much for reply. |
|
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 07:59 PM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
ADMUX |= (input & 0x07); // next input and mask the bits
This is not right - you are NOT clearing the previous channel selection - presumably you did not understand my previous answer? |
_________________
|
| |
|
|
|
|
|
Posted: Jun 27, 2011 - 10:43 PM |
|

Joined: Nov 28, 2004
Posts: 3553
Location: San Diego, Ca
|
|
I doubt that you put a breakpoint and then single-stepped into the ADSC being set, because you didn't see it , but you didn't say the ISR DIDN'T fire , OR that you didn't get adc_values . If you run the debugger at full speed, there's plenty you'll miss, if that's what you're doing .
Anyway, you're bouncing all around with these code versions and it's not a good move to go from non-working code to a more complex non-working version ( ISR ).
How are ALL your MCU adc pins connected and which debugger do you use ? Put adc_result in the watch window and breakpoint after it should get a value in the ISR .
You don't see any LEDs on, but only superman could since it would be too fast for you to see . You have no delays for when it's on / off . |
_________________ 1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
|
| |
|
|
|
|
|
Posted: Jun 29, 2011 - 02:27 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
to clear the previus channel:
Code:
ISR( ADC_vect ) {
for (input=0; input <8; input++) {
input = ADMUX;
input &= 0x07;
adc_result[input] = ADCH;
ADMUX++;
ADCSRA |= (1 << ADSC); // next ADC conversion
}
ADMUX &= 0xF0;
}
Now if a simulator debug i can see ADSC setted, in real debug with avr dragon no ADSC is setted  |
|
|
| |
|
|
|
|
|
Posted: Jun 29, 2011 - 02:29 PM |
|


Joined: Jul 18, 2005
Posts: 62371
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| Your code makes no sense whatsoever?!? |
_________________
|
| |
|
|
|
|
|
Posted: Jun 29, 2011 - 02:37 PM |
|

Joined: Dec 28, 2008
Posts: 47
Location: Italy
|
|
|
Quote:
Your code makes no sense whatsoever?!?
...Ok I give it up... |
|
|
| |
|
|
|
|
|
Posted: Jun 29, 2011 - 03:14 PM |
|

Joined: Dec 30, 2004
Posts: 8789
Location: Melbourne,Australia
|
|
| Go back to your original code and fix the problems. Have you read the datasheet onthe part you're using? It is all pretty simple, but you're making some fundamental mistakes. |
|
|
| |
|
|
|
|
|
Posted: Jun 29, 2011 - 04:05 PM |
|


Joined: Mar 27, 2002
Posts: 18599
Location: Lund, Sweden
|
|
In your latest code, what is the point with doing
Code:
ADMUX++;
?
Youre at the end of the loop, just about to iterate and increment input which will then be assigned to ADMUX. |
|
|
| |
|
|
|
|
|