PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ADC will nicht Kanal umschalten



Christoph2
19.09.2009, 14:37
Hallo!

Ich schreibe gerade ein Programm, das die Lichtstärke und die Luftfeuchtigkeit misst uns sie auf einem Display anzeigt.

Es funktioniert problemlos, wenn man nur eine der beiden größen ausliest. Sobald ich aber beide hintereinander auslese und anzeige, funktioniert es aber nichtmehr. Er zeigt dann für beide größen den selben Wert an, den er von einem eingang ermittelt.

Der verwendete Controller ist ein Mega8 mit 4 Mhz. Die ADC-Pins sind auf Port C. An die ADC-Pins 0 und 1 habe ich je ein Poti angeschlossen.

Hier ist mein code:


#include <avr/io.h>
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <avr/pgmspace.h>


#include <pwm.h>
#include <lcd.h>
#include <i2cmaster.h>
#include <uart.h>

uint16_t adc(uint8_t);
void lcd_var16(uint16_t);

int main(void)
{
DDRB |= (1<<1) | (1<<2) | (1<<4); // B1, B2, B4 auf Ausgang

DDRC=0x00;


uint16_t lichtstaerke_a;
uint16_t feuchtigkeit;

lcd_init(LCD_DISP_ON);

while(1) // Beginn der Hauptschleife
{

lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("Hallo Welt");


lichtstaerke_a = adc(0);
lcd_gotoxy(15,0);
lcd_var16(lichtstaerke_a);


feuchtigkeit = adc(1);
lcd_gotoxy(15,1);
lcd_var16(feuchtigkeit);

_delay_ms(300);


} // Ende der Hauptschleife (Endlosschleife)


return 0;
}


//################################################## ##############################################


uint16_t adc(uint8_t mux)
{
uint8_t i;
uint16_t result;

ADMUX |= (mux & 0b00000111); // Kanal waehlen

ADMUX &= ~(1<<REFS0);
ADMUX |=(1<<REFS1);


//Frequenzvorteiler setzen auf 32 und ADC aktivieren

ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
ADCSRA &=~ (1<<ADPS1);

// Dummy-readout
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) )
{ ; // auf Abschluss der Konvertierung warten
}

result = ADCW;

//----------------------------------------------------------------------------

// Eigentliche Messung - Mittelwert aus 2 aufeinanderfolgenden Wandlungen

result = 0;

for( i=0; i<4; i++ )
{ ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{; // auf Abschluss der Konvertierung warten
}

result += ADCW; // Wandlungsergebnisse aufaddieren
}

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

result /= 4; // Summe durch 10 teilen = arithm. Mittelwert

return result;
}


//################################################## ##############################################


void lcd_var16(uint16_t var)
{
char buffer[5]; // array für Zeichen definieren
uint8_t i;

for(i=0; i<5; i++)
{ buffer[i]=0;
}

itoa(var, buffer, 10); // int in einen String umwandeln (zur Basis 10 -> dezimal)

lcd_puts(buffer); // char ausgeben

}

An der Ausgabe am Display und der umwandlung ing->string kann es nicht liegen, wenn ich nämlich statt adc(0); und adc(1); zwei zahlen hinschreibe, stehen auch die richtigen zahlen am Display.

Mir ist außerdem aufgefallen, dass nach einem reset ganz kurz die beiden richtigen werte am display aufblitzen, danach nimmt der zweite wert aber automatisch den wert des anderen adc wertes an und beide haben den selben wert...

Kann es sein dass man bei der Umschaltung zwischen den ADC Kanälen irgendetwas beachten muss?

lg Christoph

cmock
19.09.2009, 15:08
du setzt REFS1:0 auf 10, und das ist lt datenblatt "reserved"...

Christoph2
19.09.2009, 15:21
aja an der referenzspannung hab ich rumexperimentiert... vorher hatte ich sie auf 0:0, jetzt habe ich 0:1 probiert, hat auch nicht geklappt...

radbruch
19.09.2009, 15:28
Hallo

Müsste man nicht erst den alten Kanal zurücksetzen?

ADMUX &= ~0b00000111; // alten Kanal loeschen
ADMUX |= (mux & 0b00000111); // Kanal waehlen

Nachdem Kanal 1 gewählt wurde wird sonst Bit0 in ADMUX nie mehr gelöscht.

Gruß

mic

Christoph2
19.09.2009, 15:56
juhuuu super danke das wars!!!

Danke!!!

lg Christoph