Hallo, ich weiss, dass es zu dem Thema ADC hier ne Menge Beiträge gibt,
aber deren Inhalt hat mich leider nicht weitergebracht.
Kurz zur Hardware & Software:
MSP430F1612
IAR Emb. Workbench 3.21A
Sprache: C
Jetz mein Problem:
Ich habe ein Beispiel zum ADC12 von TI genommen, ausprobiert und es geht
soweit ganz gut. Ich kann jatzt die angelegte Spannung an einem Pin
erfassen, wandeln und weiterverarbeiten.
Im Beispiel (fet140_adc12_02.c) wird der ADC A0 genommen...also P6.0.
Schön und gut, aber wenn ich versuche, den A1, also P6.1 zu nehmen, dann
geht es nicht.
Ich habe an A0 eine Spannung dran, und an A1 eine andere Spannung.
Jetzt dachte ich, dass wenn ich P6SEL |= 0x02 mache, dann wird
automatisch der Kanal gewählt, für den am Port die Zweitfunktion (ADC)
aktiviert ist.
Aber er nimmt trotzdem den A0.
Hier erstmal kurz der Code
1
voidmain()
2
{
3
WDTCTL=WDTPW+WDTHOLD;// Stop watchdog timer
4
P6SEL|=0x03;// Enable A/D channel A0 und A1; P6.0 & P6.1
5
ADC12CTL0=ADC12ON+SHT0_2+REFON+REF2_5V;// ADC12ON --> schaltet ad-wandler ein
6
// SHT0_2 --> clocks für sample-time
7
// REFON --> interne referenz an
8
// REF2_5 --> referenz auf 2.5V
9
ADC12CTL1=SHP;// Use sampling timer
10
ADC12MCTL0=SREF_1;// Vr+=Vref+
11
12
wait(3600);// wartezeit, damit referenzspannung steht...
13
14
ADC12CTL0|=ENC;// Enable conversions
15
16
for(;;)
17
{
18
// ersten kanal einlesen...
19
ADC12CTL0|=ADC12SC;// ADC12 starten
20
while((ADC12IFG&BIT0)==0);// solange, wie interruptflag (IFG) nicht
21
// gesetzt wurde...wandle
22
adcwert=ADC12MEM0;
23
adcwert_mV=(float)(((float)ADC12MEM0/4096.0)*2500.0);// Wert in mV
24
25
// zweiten kanal einlesen
26
// --> hier muss noch der kanal umgeschalten werden...aber wie??
27
ADC12CTL0|=ADC12SC;// ADC12 starten
28
while((ADC12IFG&BIT0)==0);// solange, wie interruptflag (IFG) nicht
29
// gesetzt wurde...wandle
30
adcwert1=ADC12MEM0;
31
adcwert_mV1=(float)(((float)ADC12MEM0/4096.0)*2500.0);// Wert in mV
32
33
_NOP();
34
}
35
}// ende main
Wenn ich jetzt statt
ADC12MCTL0 = SREF_1;
ADC12MCTL0 = SREF_1 + INCH_1;
mache, dann nimmt er nur A1.
Was ich aber dann eigentlich machen möchte, ist dass ich erst A0 wandle,
und dann danach A1.
Ich möchte single conversion machen. Ich weiß, dass es sicher auch mit
einer Sequenz geht, aber das möchte ich erstmal nicht machen.
Das Wandlungsergebnis landet ja immer in MEM0. Kann ja auch...
Er soll nur nach dem Wandeln den A0 auf A1 umschalten. Das muss doch
gehen, oder?
Wie stell ich das am besten an? Hat einer einen entscheidenden Tipp?
Oder WAS muss ich genau machen, damit er mir NUR nen A1 wandelt? Die
Sache mit P6SEL |= 0x02; geht ja irgendwie nicht...
Danke
mathias
while((ADC12IFG&BIT0)==0);// solange, wie interruptflag (IFG) nicht
musst du BIT0 auf BIT1 ändern, wenn du nach der Wandlung von Channel 1
statt 0 die Daten haben willst.
Das geht aber nur, wenn du eine einmalige Sequenz startest, und beim
Init folgendes machst:
1
ADC12MCTL0=SREF_1+INCH_0;
2
ADC12MCTL1=SREF_1+INCH_1+EOS;
Dann Startet der Sequenzer die Messung bei Channel 0, Ergebnis geht in
ADC12MEM0, dann wandelt er Channel 1, Ergenis in ADC12MEM1, da dort dann
das EOS (End of Sequence) Bit gesetzt ist, hält er an, und startet erst
wieder, wenn du das SC bit setzt.
Danke Dir erstmal, aber das ist die Sache mit der Sequenz, die ich
erstmal nicht machen wollte...
Es muss doch auch möglich sein, die Wandlung einzeln zu machen...
Also quasi:
ADC12 starten --> A0 wandeln --> wegen mir ADC12 stoppen... --> ADC12
neu konfigurieren --> ADC12 starten --> A1 wandeln... --> zurück zum
Anfang...
Naja, ich werde morgen doch mal die Sache mit der Sequenz
versuchen..AUSSER, es hat jemand doch noch nen Tipp für mich, wie ich es
ohne hinbekomme...
(ob die Sache jetzt Sinn macht, sei erstmal dahingestellt ;-) )
danke
mathias
Na gut, so von hinten durch die Brust ins Auge geht natürlich auch.
Musst dann immer das ADC12MCTL0 anpassen, das Ergebnis landet immer in
ADC12MEM0 dann.
Und immer wenn du das SC Bit setzt, wird wieder ein Wert gewandelt.
Die Frage für mich ist, WIE ich das am besten mache? Ich hab schon
soviele Sachen rumprobiert...mit den ADC12MCTLx - Regsitern...bin noch
auf keinen grünen Zweig gekommen...
Das das Ergebnis immer in ADC12MEM0 landet ist mir klar. Kann ja auch...
Aber an welcher Stelle muss ich denn WIE das ADC12MCTL0 anpassen?
Es hat irgendwas mit INCH_0 oder INCH_1 zu tun, aber was und wie?
danke
Ich kanns momentan nicht testen, aber es müsste so gehn:
1
ADC12MCTL0=INCH_0+SREF_1;// P6.0
2
ADC12CTL0|=ADC12SC;// ADC12 starten
3
4
while((ADC12IFG&BIT0)==0);// Warte auf Wandlungsende
5
adcwert=ADC12MEM0;// Wandlungsergebnis
6
7
//Auswertung
8
9
ADC12MCTL0=INCH_1+SREF_1;// P6.1
10
ADC12CTL0|=ADC12SC;// ADC12 starten
11
while((ADC12IFG&BIT0)==0);// Warte auf Wandlungsende
12
adcwert1=ADC12MEM0;// Wandlungsergebnis
Die INCH-Bits geben an, welcher Kanal gesampelt werden soll (P6.0 bis 7,
Temp, VCC/2, Ref-Spannung....)
Jedes ADC12-Memory Register kann jeden Kanal sampeln.
Eventuell musst du das ENC Bit nach der Wandlung vor dem Umschalten des
Kanals zurücksetzen.
Ich danke Dir Christian!
Ich dächte, ich hätte es gestern Abend schon mal so gehabt, aber
wahrscheinlich hat da ne Kleinigkeit gefehlt!
Hier nochmal mein jetziger Code, der so funktioniert, wie ich es
wollte...
1
voidmain()
2
{
3
WDTCTL=WDTPW+WDTHOLD;// Stop watchdog timer
4
P6SEL|=0x03;// Enable A/D channel A0 und A1; P6.0 & P6.1
5
ADC12CTL0=ADC12ON+SHT0_2+REFON+REF2_5V;// ADC12ON --> schaltet ad-wandler ein
6
// SHT0_2 --> clocks für sample-time
7
// REFON --> interne referenz an
8
// REF2_5 --> referenz auf 2.5V
9
ADC12CTL1=SHP;// Use sampling timer
10
wait(3600);// wartezeit, damit referenzspannung steht...
11
12
for(;;)
13
{
14
// kanal 1 wandeln
15
ADC12MCTL0=INCH_0+SREF_1;// P6.0
16
ADC12CTL0|=ENC+ADC12SC;// ADC12 starten
17
18
while((ADC12IFG&BIT0)==0);// warte auf wandlungsende
19
adcwert=ADC12MEM0;// wandlerwerte in adcwert
20
adcwert_mV=(float)(((float)ADC12MEM0/4096.0)*2500.0);// wert in mV
21
22
ADC12CTL0&=~ENC;// ADC12 stoppen
23
24
// kanal 2 wandeln
25
ADC12MCTL0=INCH_1+SREF_1;// P6.1
26
ADC12CTL0|=ENC+ADC12SC;// ADC12 starten
27
28
while((ADC12IFG&BIT0)==0);// warte auf wandlungsende
29
adcwert1=ADC12MEM0;// wandlerwerte in adcwert1
30
adcwert_mV1=(float)(((float)ADC12MEM0/4096.0)*2500.0);// wert in mV
31
32
ADC12CTL0&=~ENC;// ADC12 stoppen
33
34
_NOP();
35
}
36
}// ende main
Erst wird der erste Kanal gewandelt, dann der ADC12 abgeschalten.
Dann wird der zweite Kanal gewandelt und danach wieder der ADC12
abgeschalten. Das ganze in einer Endlosschleife.
Wie gesagt, über den Sinn DIESER Methode lässt sich sicher streiten! ;-)
mathias