Hallo,
ich hab ein Problem damit, mehrere A/D-Wandler gleichzeitig zu
verwenden.
Habe gelesen, dass man das ADMUX nur umschalten sollte, wenn die Messung
fertig ist, also hab ich das versucht folgendermaßen zu lösen:
ad_con ist der gewählte Pin. Bisher möchte ich erstmal nur zwischen 2
Pins umschalten, aber das soll noch auf mehrere erweitert werden können.
Hier verwende ich jetzt Eingang ADC2 und ADC3.
Das Problem ist, es scheint, als würde der µC gar nicht in die zweite
Verzweigung gehen, er schaltet also gar nicht um. Ich frage mich nur
warum, da beim Beenden der Messung der ADIF Pin ja auf 1 geschalten wird
und somit ad_con 1 hochgezählt werden sollte.
Ich rätsel da gerade ein bisschen rum, da ich nicht genau weiß, wie man
das am besten macht. So eine richtige Lösung habe ich beim Googeln nicht
gefunden, nur Ansätze wie es gehen könnte.
Hi
> if (ADIF == 1)
Wenn du ADIF nicht wieder manuell löschst (Beschreiben mit einer 1)
bleibt es nach der ersten Messung immer auf 1. Allerdings ist es besser
du überprüfst ADSC. Das wird nach der Messung wieder Null.
MfG Spess
Hi, die gröbsten Schnitzer: ADIF ist eine Konstante, die sich nie
ändert, also wird deine if-Bedingung nie wahr.
Du willst wahrscheinlich die entsprechende Bitposition in ADCSRA
abfragen.
Das ginge über "if ( ADCSRA & ( 1 << ADIF ) )
Aber auch dann ist dein code noch falsch. Du musst nach dem Start einer
Wandlung warten, bis das ADIF-Bit 1 wird, erst dann ist das Ergebnis
deiner Wandlung fertig. Und danach musst du das ADIF-Bit löschen, indem
du eine 1 reinschreibst. Also fürs erste:
spess53 schrieb:> Hi>>> if (ADIF == 1)>> Wenn du ADIF nicht wieder manuell löschst (Beschreiben mit einer 1)> bleibt es nach der ersten Messung immer auf 1. Allerdings ist es besser> du überprüfst ADSC. Das wird nach der Messung wieder Null.>> MfG Spess
Im AVR-GCC Tutorial steht, dass ADIF automatisch wieder gelöscht wird,
sobald lesend auf das Inhaltsregister des ADC zugegriffen wird.
@Rainer B:
Was bedeutet denn
1
while((ADCSRA&(1<<ADIF))==0);
?
Ich kenne while nur als Schleife mit while (Bedingung {Anweisungen;}
So hab ich das Konstrukt noch nie gesehen.
Laut dem AVR-GCC Tutorial ist ADIF aber keine Konstante, sondern wie
schon gesagt, steht dort, das Bit wird automatisch wieder gelöscht, wenn
lesend auf das Inhaltsregister zugegriffen wird und das tue ich ja mit
Robotico schrieb:> Was bedeutet dennwhile ( ( ADCSRA & ( 1 << ADIF )) == 0) ; ?> Ich kenne while nur als Schleife mit while (Bedingung {Anweisungen;}> So hab ich das Konstrukt noch nie gesehen.
Sowas sieht man bei µC täglich. Warum sollte das keine Bedingung sein?
Robotico schrieb:> Laut dem AVR-GCC Tutorial ist ADIF aber keine Konstante
"ADIF" ist als konstante im header definiert. Diese konstante sagt
welches bit im ADCSRA das Interrupt Flag ist: In diesem ist es das 4.
Bit.
( ADCSRA & ( 1 << ADIF ))
Ist dann (1 << ADIF)=0b00010000 oder 0, je nachdem ob das Flag gesetzt
ist oder nicht. Der Ausdruck ist also TRUE, wenn das Flag gesetzt ist
und FALSE wenn nicht.
Uwe S. schrieb:> Hallo Robotico,>> deine Annahme ist falsch, im Datenblatt des AVR m168 steht:> Bit 4 – ADIF: ADC interrupt flag> This bit is set when an ADC conversion completes and the Data Registers> are updated. The> ADC Conversion Complete Interrupt is executed if the ADIE bit and the> I-bit in SREG are set.> ADIF is cleared by hardware when executing the corresponding interrupt> handling vector.> Alter-natively, ADIF is cleared by writing a logical one to the flag.> Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt> can be disabled.> This also applies if the SBI and CBI instructions are used.
Ah okay, dann steht es im Tut aber etwas anders.
Okay alles klar, danke. Ich werds dann mal so testen.
TriHexagon schrieb:> Robotico schrieb:>> Was bedeutet dennwhile ( ( ADCSRA & ( 1 << ADIF )) == 0) ; ?>> Ich kenne while nur als Schleife mit while (Bedingung {Anweisungen;}>> So hab ich das Konstrukt noch nie gesehen.>> Sowas sieht man bei µC täglich. Warum sollte das keine Bedingung sein?
Ich sag doch nicht, dass es keine Bedingung ist. Es ist nur keine
Anweisung da. So ganz versteh ich das Konstrukt noch nicht.
Die Lösung von Rainer B. scheint auch nicht so ganz zu funktionieren.
Ich stehe gerade ehrlich gesagt ein bisschen auf dem Schlauch und ich
weiß auch nicht so genau, nach was ich suchen soll.
Also mir ist klar, dass erstmal eine Messung fertig abgeschlossen sein
muss, bevor man das ADMUX Register auf den anderen Pin umstellt. Aber
wie ich das abfrage genau, ist mir unklar und ich weiß leider auch
nicht, was dieses while-Konstrukt aussagt.
Robotico schrieb:> und ich weiß leider auch> nicht, was dieses while-Konstrukt aussagt.
das ist das gleiche wie
1
((ADCSRA&(1<<ADIF))==0)
2
{
3
4
}
Ist das jetzt klarer? Es wird der Code in den Klammern ausgeführt, der
hinter dem while(..) steht. In diesem Fall wird nichts ausgeführt, da
nichts drin steht. Der Sinn ist, einfach nur zu warten, bis sich ADIF
geändert hat.
Vereinfacht schreibt man das dann so:
1
((ADCSRA&(1<<ADIF))==0);
oder gebräuchlicher so:
1
(!(ADCSRA&(1<<ADIF)));
> Die Lösung von Rainer B. scheint auch nicht so ganz zu funktionieren.
Da wird das ADIF ja auch nicht gelöscht.
Normalerweise fragt man ohnehin das ADSC-Flag ab.
Man setzt das ADSC und startet die Wandlung:
1
ADCSRA|=(1<<ADSC);
2
//dann wartet man bis die Wandlung fertig ist:
3
while(ADCSRA&(1<<ADSC));
4
//Und kann jetzt das ADC auslesen und den Kanal wechseln.
Bei diesem Flag braucht man sich nicht um das Löschen zu kümmern.
>Ah okay, dann steht es im Tut aber etwas anders.> Laut dem AVR-GCC Tutorial ist ADIF aber keine Konstante, sondern wie> schon gesagt, steht dort, das Bit wird automatisch wieder gelöscht, wenn> lesend auf das Inhaltsregister zugegriffen wird und das tue ich ja mit
Das stand bis eben tatsächlich so da drin. Ich habe mir erlaubt, das
rauszuschmeissen,
mfg.
Rainer B. schrieb:> Thomas Eckmann schrieb:>> Da wird das ADIF ja auch nicht gelöscht.> Hi, was macht denn deiner Meinung nach diese Anweisung
Jetzt komm mir nicht so blöd. Das habe ich übersehen.
mfg.
Thomas Eckmann schrieb:> das ist das gleiche wie(( ADCSRA & ( 1 << ADIF)) == 0)> {>> }>> Ist das jetzt klarer? Es wird der Code in den Klammern ausgeführt, der> hinter dem while(..) steht. In diesem Fall wird nichts ausgeführt, da> nichts drin steht. Der Sinn ist, einfach nur zu warten, bis sich ADIF> geändert hat.
Ja logisch, so leuchtets mir ein.
Danke!
Rainer B. schrieb:> Poste mal deinen gerade aktuellen Code
Es funktioniert jetzt. Hatte leider auch einen "Hardwarefehler", bzw.
habe einen Pin auf der Platine nicht richtig verbunden gehabt, so lagen
an dem einen Trimmwiderstand nicht 0 und 5 Volt an, sondern 0 und
nichts. Logisch, dass der eine Kanal dann nichts brauchbares ausgibt.
Hab es jetzt nach dem Lösungsvorschlag von Thomas Eckmann gemacht:
Thomas Eckmann schrieb:> ADCSRA |= (1 << ADSC);> //dann wartet man bis die Wandlung fertig ist:> while(ADCSRA & (1 << ADSC));> //Und kann jetzt das ADC auslesen und den Kanal wechseln.
Hier mein Code:
Kann sicherlich noch optimiert werden!
Es handelt sich übrigens um einen Joystick (aus PS2 Controller), den ich
auswerten möchte. Der ist ganz simpel mit jeweils einem Trimmwiderstand
in X- und Y-Achse realisiert.
Danke an alle für die Hilfe!
Thomas Eckmann schrieb:> Das stand bis eben tatsächlich so da drin. Ich habe mir erlaubt, das> rauszuschmeissen,
Danke! Ist doch schön, wenn dabei noch Fehler verbessert werden.
Robotico schrieb:> Kann sicherlich noch optimiert werden!
Du meinst verbessert.
ZB. mit den Funktionen aus dem AVR-GCC_Tutorial.
Dann schreibt sich dein Code als
1
voidlcd_puti(uint8_tcol,uint8_trow,uint16_tvalue)
2
{
3
charbuff[15];
4
sprintf(buff,"%5d",value);
5
6
lcd_setcursor(col,row);
7
lcd_string(buff);
8
}
9
10
intmain(void)
11
{
12
lcd_init();
13
lcd_setcursor(0,1);
14
lcd_string("X:");
15
lcd_setcursor(0,2);
16
lcd_string("Y:");
17
18
uint16_tadc_x;
19
uint16_tadc_y;
20
21
ADC_init();
22
23
while(1)
24
{
25
adc_x=ADC_read(2);
26
adc_y=ADC_read(3);
27
28
lcd_puti(3,1,adc_x);
29
lcd_puti(3,2,adc_y);
30
}
31
}
... und da kann man nicht mehr meckern, dass man ihn nicht lesen könnte.
Ja das stimmt, ist deutlich übersichtlicher!
Wobei ich sowieso gerade nur am Testen und Ausprobieren bin und die
Programme bisher noch nicht sehr länglich werden, da ist es auch so noch
überschaubar.
Wenns nötig wird, werde ich natürlich in Funktionen zusammenfassen.