Ich habe ein Problem mit dem ADC10 meines MSP430.
Und zwar möchte ich die Kanäle A0 bis A3 (also 4 Stück) auslesen, um
dann weiterzuverarbeiten.
Aber irgendwie habe ich glaube ich mit dem DTC ein Problem damit, dass
er nach jeder Konversion den Wert vom ADC10MEM in den ADC10SA speichern
soll.
Den Code habe ich mehr oder weniger von TI, nur halt auf meine
Applikation angepasst.
Könnt ihr mir da weiterhelfen?
Hier mein Code und im Anhang der von TI.
1
#include<msp430x22x2.h> // Header Datei des verwendeten uC
2
3
// #include <system.h> // Definition des Systems -> Hier: PC
>dass er nach jeder Konversion den Wert vom ADC10MEM in den ADC10SA>speichern soll.
Vorsicht! Er speichert den Wert nicht in ADC10SA, sondern in die
Speicherstelle dessen ADRESSE in ADC10SA steht. Das ist also ein
Pointer.
Lösung äre also z.B. (ungetestet!)
Aber es funktioniert nicht. Wenn ich debugge und dann der schritt mit
dem ADC10SA kommt dann bleibt er einfach stehen danach.
Ich verstehe auch nicht, ob die ersten drei Zeilen von obigem code so
überhaupt stimmen und wo ich dann wirklich meine 4 AD-Werte habe (am
anfang oder am schluss).
Ich habe es mit ein bisschen rumprobieren in den Registern ADC10CTL0 und
ADC10CTL1 geschafft, dass er die 4 AD Werte (A0 bis A3) in die
Buffervariable ADC10_Buffer speichert.
Aber wirklich normal funktioniert es nicht, denn die LED kann ich ausser
im aller ersten Debug durchgang nicht mehr einschalten, d.h. er bleibt
nach einem durchgang bei der ersten if-Schleife hängen und wenn ich dann
F10 drücke für einen nächsten Schritt, macht er das nicht und ich muss
mit break abbrechen. Dann aber hat er wieder neue AD-Werte geladen.
Also irgendetwas ist immer noch nicht so ganz funktionstüchtig.
Er soll die main schleife ja immer wieder wiederholen, so dass ich z.B.
die LED jederzeit ein und aus schalten kann.
Am besten sollte er die Konversion starten, damit man dann noch anderes
machen kann (noch nicht implementiert) und am Anfang der funktion werden
die ad-werte abgefragt.
Hier noch der aktuelle c-code:
1
/* Includes */
2
#include<msp430x22x2.h> // Header Datei des verwendeten uC
Er bleibt also bei "if (TasterGet())" stehen? Das dürfte dann wohl daran
liegen das er nicht mehr aus dem LPM raus kommt. Allerdings sehe ich auf
anhieb jetzt nicht woran es liegt.
Ich habe zwar noch nie DTC benutzt, aber wenn ich mir den User-Guide so
anschaue, denke ich, Du hast zwei dicke Probleme in Deinem Code:
1.) Du verwendest den 16MHz Clock ohne Vorteiler für den ADC10.
Der ADC10 verträgt aber nur max. 6,3MHz! Alles darüber kann sich
in undefiniertem Verhalten wiederspiegeln!
2.) Du willst die ADC-Wandlung jeweils "per Hand" in Deiner for-Schleife
starten:
1
ADC10CTL0|=ADC10SC+ENC;
In Deiner ADC-Initialisierung setzt Du aber MSC (in CTL0) und
die repeated-sequence-of-channels (CONSEQ_3 in CTL1).
Damit läuft der ADC eigentlich immer durch, bis Du irgendwann mal
wieder ENC=0 setzt. Sicher kein gewolltes Verhalten?!
Außerdem solltest Du Dir die magic numbers abgewöhnen:
1
...
2
ADC10CTL1=0x3016;
3
...
und statt dessen die im Headerfile definierten Bit-Masken benutzten.
Ist zum einen weniger Fehleranfällig und auch leichter zu lesen und zu
interpretieren!
Hallo
Ich habe es noch immer noch hingekriegt.
Die Control Register habe ich jetzt mal mit den Masken eingestellt und
einen ADC10CLK Vorteiler habe ich mal auf "/3" gesetzt.
Das mit dem MSC bit und dem CONSEQ_1 bzw. CONSEQ_3 habe ich alles mal
durchprobiert aber er bleibt immer noch irgendwie hängen.
Hier nochmals der C-Code: Ich hoffe, dass ich es mit eurer Hilfe doch
noch hinkriegen werde.
1
/* Includes */
2
#include<msp430x22x2.h> // Header Datei des verwendeten uC
Arrrgghhh....
Hätte ich auch früher sehen können!!!
Du benutzt MCLK als Clock für den ADC10.
Sobald Du aber in LPM0 gehst, wird die CPU und damit auch MCLK
deaktiviert!
Das kann nicht funktionieren!
Nehm den SMCLK oder den internen ADC10OSC!
Also ich verwende ja den DTC mit 16 MHz.
Macht das keinen Unterschied, ob ich MCLK oder SMCLK verwende?
Ich hatte vorhin das mit dem LMP0 einfach auskommentiert und es
funktionierte.
Zurzeit habe ich den MSC aktiviert und CONSEQ_3, ohne das hat es nicht
funktioniert. Ist das schon richtig so?
Ich möchte es ja so handhaben, dass ich am Anfang von main die AD-Werte
hole (siehe ADC10_Calc) und dann den AD-Wandler starte und dann noch
andere Dinge mache (hier mal das mit dem Taster und LED, später kommt da
anderes).
Ist das so wie ich es jetzt implementiert habe richtig oder stimmt da
mit der Reihenfolge oder so noch was nicht?
Muss ich denn LMP0 und Interrupt eigentlich benützen, weil ich warte ja
sowieso bis die Konversion fertig ist bevor ich mit einer neuen starte?
Ich hoffe du kannst mir auch noch bei den letzten Unklarheiten helfen,
vielen Dank bis jetzt schonmal.
>Muss ich denn LMP0 und Interrupt eigentlich benützen, weil ich warte ja>sowieso bis die Konversion fertig ist bevor ich mit einer neuen starte?
Nein musst du nicht. Es ist alles auch immer ohne Interrupt möglich.
>Also ich verwende ja den DTC mit 16 MHz.>Macht das keinen Unterschied, ob ich MCLK oder SMCLK verwende?
Der ADC10 will nur einen Clock innerhalb der Spezifikation haben, wo der
herkommt ist wurscht.... ausser Du nimmst z.B. MCLK und schaltest MCLK
dann ab ;-)
>Ich hatte vorhin das mit dem LMP0 einfach auskommentiert und es>funktionierte.
Klar, damit hast Du ja MCLK nicht deaktiviert!
>Zurzeit habe ich den MSC aktiviert und CONSEQ_3, ohne das hat es nicht>funktioniert. Ist das schon richtig so?
Von der Funktionsweise schon, aber nur weil Du
1
ADC10CTL0&=~ENC;
eingefügt hast!
Von der Logik her würde ich CONSEQ_1 nehmen, denn Du willst ja A0-A3
einmal sampeln. Eine neue Sequenz startest Du ja jedesmal manuell und
nicht automatisch:
1
ADC10CTL0|=ENC+ADC10SC;// Starte AD-Konversion
Dann kannst Du Dir auch das Rücksetzten von ENC sparen.
Also so etwa:
1
// ADC10CTL0 &= ~ENC;
2
while(ADC10CTL1&BUSY);// Warte wenn ADC10 core aktive ist
3
ADC10SA=(unsignedint)&ADC10_Buffer[0];// Data buffer start
Ich würde mir an Deiner Stelle im Übrigen mal das "Design" überdenken.
Deine Konstruktion steht und fällt mit TasterGet().
Wenn TasterGet() sehr schnell erledigt ist, kann es sein, dass Du Deine
for(;;) erneut aufrufst und die Buffer sicherst, obwohl vielleicht noch
gar nicht alle ADC-Werte gesampelt wurden!
Vielleicht hilft es schon
1
while(ADC10CTL1&BUSY);// Warte wenn ADC10 core aktive ist
ganz an den Anfang der for(;;) zu platzieren ?!
Wobei ich mir nicht 100%ig sicher bin, ob BUSY während der gesamten
Sequenz gesetzt bleibt, oder nur während jeder einzelnen Wandlung. Der
User-Guide sagt "...Sequence, sample or conversion is active...". Dann
sollte es schon gehen, eigentlich...