Hallo,
ich braeuchte mal die Hilfe von euch MSP Experten.
Mein Programm soll folgendes machen:
TimerA loest TimerB aus, die TimerRoutineB schaltet dann einen Ausgang1
an und der AD Wandler holt 5Werte die dann gemittelt werden. Danach wird
Ausgang1 abgeschaltet, Ausgang2 eingeschalet und wieder Werte mit dem
AD-Wanlder eingelesen. So war zumindest mein Plan :)
Wenn ich mir mit dem Debugger meine Variablen anschaue, stelle ich fest,
dass die nur max. 3 Messwerte in den jeweiligen Array
(Messwerte_LED1[n_mw]) geschrieben werden und der Zaehler "n_mw" sich
gar nicht ruehrt bei 0 bleibt.
Kann jemand den Fehler erkennen?
Vielen Dank
Bernd
P.S Fuer weitere Verbesserungsforschlaege etc. bin ich ebenfalls offen,
beschaeftige mich noch nicht so lange mit der Programmierung..
Hallo,
hab nur mal so drübergesehen:
1) Meines wissens nach musst du nach jeder Conversion das ENC bit
toggeln
2) Willst du nicht eine sequenz von Kanälen samplen??? -> Sample Mode
wecheln zu 'Sequence of Channels' und das 'EOS - End of Sequence' Bit
setzen.
3) Das Interrupt Enable Bit der Timer ist nicht gesetzt!!!.
Zudem würde ich die globalen Variablen mal als 'volatile' deklarieren,
damit der Compiler diese nicht optimieren kann.
mfg alex
Hallo Alex,
vielen Dank fuer deine Hilfe. Die Variablen habe ich jetzt auf
'volatile' umgestellt.
Die Timer Interrupt Bits habe ich so gesetzt:
1
2
TACCTL0|=CCIE;
3
TBCCTL0|=CCIE;
Wie genau toggel ich das ENC Bit?
Das samplen einer Sequenz bringt mir leider nichts, da ich vor dem
Auslesen eines anderen Kanals den DAC noch einen anderen werden geben
muss etc.
Hallo,
ich weiß nicht welches Device du verwendest, normalerweise musst du noch
die Interrupt Enable Bits im Control Register der Timer Setzen.
Also TACTL, TBCTL bzw. teste mal ob deine Interrupt behandelt werden.
mfg
Die Timer arbeiten wunderbar, jedoch zaehlt der Zaehler "n_mw" nicht
hoch und die werte des ADC werden auch nicht richtig in die Arrays
uebernommen. Komischerweise wird in den Array (Messwerte_LED0) nach dem
ersten Durchlauf 3 Werte eingetragen, nach jedem weiteren durchlauf,
veraendern sich diese dann. Ich weiss einfach nicht mehr weiter, woran
koennte es liegen?
Der Zaehler laeuft endlich, schuld war ein Semikolon was dort nicht
hingehoerte..
Das Programm laeuft soweit auch, bis zur Abfrage von ADC12MEM2. Habe ich
dort etwas falsch initalisiert? Kann sich das mal jemand von euch
Experten angucken?
Vielen Dank
Bernd
Das einzige, was ausserhalb der Spezifikationen läuft, ist der ADC12CLK.
Wenn ich das richtig interpretiere, dann benutzt Du ACLK (=32,768kHz)
als Clock für den ADC12?!
Der braucht aber lt. Datenblatt mind. 450kHz um korrekt zu
funktionieren.
Vielleicht liegt da der Fehler...
... aber was genau geht denn jetzt nicht?
Hallo Stefan,
nach dem Sprung in die adc_isr lese ich zwei ADC-Register aus (ADC12MEM0
oder ADC12MEM2). Das Abarbeiten des ADC12MEM0 funzt noch funderbar, doch
noch auslesen des ADCMEM2 geht alles kreuz und quer (der Array wird
vollstaendig gefuellt)
Ich kann es mir nur so erklaeren, dass ADC12MEM0 nicht richtig
intialisiert wird.
Bernd
Ich glaube Dein ganzes Timing stimmt hinten und vorne nicht!
Es ist bei solchen verschachtelten IRQ's immer gut, mal ein Blatt Papier
und einen Stift zu nehmen und sich das Timing aufzumalen:
1.) Timer A braucht 15,625ms pro Durchlauf (512/32768Hz) = 64Hz und
nicht 1000Hz!
2.) Timer B braucht 144/32768Hz = 4,39ms
D.h. in der timerb_isr() können nur 3 Messungen gemacht werden, bevor
timera_isr() erneut angesprungen wird, und nicht 5! Ist das gewollt?
Ich vermute mal, da überholt sich Dein Programm selbst und kommt ausser
Tritt!
Ausserdem solltest Du immer über eine Zweierpotenz an Messwerten mitteln
(2,4,8,...). Dann vereinfacht sich die Division zu einer
Shift-Operation, die wesentlich schneller ausgeführt wird, als die
Divisionsroutine, die Dein Compiler für /5 einsetzen muss!
Möglicherweise ist diese langsame Division auch ein Grund für den
Fehler!
An der Init für ADC12MEM sehe ich jetzt nichts auszusetzen!
Also nach etwas genauerem Drübergucken habe ich doch noch'n Fehler
gefunden:
Du verwendest single channel-single conversion für den ADC12. D.h. aber
mit jedem Setzen von ADC12SC wird immer ADC12MEM0 gewandelt, zu ...MEM2
kommst Du nie, da Du es nie auswählst, denn CSTARTASSx steht immer auf
0x00.
Du solltest darüber nachdenken, den sequence-of-channels zu verwenden.
Mit jedem ADC12SC also MEM0 bis MEM2 sampeln. Der ADC12CLK muss
natürlich schnell genug sein, dass alle Wandlungen innerhalb einer
timerb_isr-Periode fertiggestellt werden können!
Hallo Stefan,
zunaechst erstmal vielen Dank fuer deine Unterstuetzung!
Die Timer habe ich korrigiert, Timer A arbeitet weiterhin mit 64Hz und
TimerB mit 333Hz, die Anzahl der Abtastungen habe ich auf 4 reduziert.
Darauf haette ich auch wirklich selbst kommen muessen.
Den ADC initialiere ich nun wie folgt:
Dabei stosse ich aber auf folgendes Problem. Nachdem das erste Mal ein
Sprung in die ADC ISR erfolgt ist, wird ADC12MEM0 ausgelesen und in den
Array "Messwerte_LED0[n_mw]" gelegt. Beim naechsten Sprung in die ISR
werden alle 3 Arrays mit "-0xFE00FF" voll geschrieben und es passiert
nichts mehr.
Hast du eine Ahnung was das sein kann?
Bernd
Du musst auf jeden Fall beim letzten Channel das EOS-Bit setzen, sonst
wandelt der ADC12 alle 16 Kanäle durch!
Also:
1
ADC12MCTL0=SREF_0+INCH_2;//ADC12MEM0, A2
2
ADC12MCTL1=SREF_0+INCH_3;//ADC12MEM0, A3
3
ADC12MCTL2=SREF_0+INCH_4+EOS;//ADC12MEM0, A4, letzter Kanal, danach stop
Ausserdem solltest Du "sicherheitshalber" nur einen IRQ freigeben,
denn Du wandelst ja eine Sequenz mit 3 Kanälen! Wenn Du mehrere frei
gibst, dann bekommst Du pro Sequenz auch mehrere IRQ's, obwohl du nur
einen haben willst!
1
ADC12IE=ADC12IE2;// der letzte Kanal, wird auch zuletzt gewandelt
Durch
1
ADC12IFG=0x0000;
sollte das zwar verhindert werden, aber man weiß ja nie (soll ja auch
Bugs geben...)
Den ADC12CLK hast Du auf mind. 450kHz erhöht?
Wie kann ich den ADC12CLK auf min. 450kHz erhoehen? Ich habe im
Datenblatt des MSP nichts finden koennen, dass der so hoch sein muss.
Das EOS-Bit habe ich gesetzt, jedoch immer noch der gleiche Fehler. Nach
dem zweiten Sprung in die ISR werden Felder aller drei Array mit
"-0xFE00FF" beschrieben.
Bernd
>Wie kann ich den ADC12CLK auf min. 450kHz erhoehen?
Entweder den internen Clock des ADC12 benutzen, oder MCLK bzw. SMCLK als
Source benutzen (solange MCLK bzw. SMCLK innerhalb der geforderten
Spezifikation sind)
Ich habe es jetzt mit ADC12OSC und MCLK probiert. Mit ADC120SC wird die
ADC ISR gar nicht mehr ausgeloest. Ich weiss einfach nicht mehr weiter,
kann es auch ein Fehler des Debuggers sein, dass die zu ueberwachenden
Variablen nicht richtig ausgelesen werden?
Im Anhang befindet sich der aktuelle Quelltext..
Bernd
Im ADC12CTL0 Register fehlt auf jeden Fall noch das MSC Bit, sonst macht
der keine Mehfachen Wandlungen hintereinander. Dann musst du mal im User
Guide schauen, ob das Sample-Timing hinhaut bei dir, dass du wirklich
mit Sampeln schneller fertig bist, wie dein Timer.
Ein funktionierender Beispielcode:
1
ADC12CTL0=ADC12ON+SHT0_DIV32+SHT1_DIV32+MSC+REFON+REF2_5V;// Turn on and set up ADC12
2
Wait(30000);
3
ADC12CTL1=SHP+CONSEQ_1+ADC12SSEL_1;// Use sampling timer
4
ADC12MCTL0=SREF_1+INCH_0;//ext. Ref, Kanal 0, ext. Spannung
5
ADC12MCTL1=SREF_1+INCH_11;// VCC/2
6
ADC12MCTL2=SREF_1+INCH_10+EOS;//temp-diode, ende sequenz
jetzt sieht es schon mal besser aus... alle 3 Arrays werden befuellt,
doch wenn der letzte Werte des 3 Array geschrieben wird, werden alle
Felder aller drei Arrays auf "0xFF03FF03" gesetzt.
Mach mal alle Variablen auf Volatile. Vielleicht klappts dann. Ich denke
mal, die Variablen verlieren nach dem letzten Schreiben ihre Gültigkeit,
da muss ein volatile vor alle Arrays. Schließlich machst du sonst nix
damit, da legt der Compiler die auf den Arbeitsregistern an (soweit
möglich).
Wo ist denn jetzt der Unterschied zum letzten Programmcode? Ich seh das
MSC-Bit immer noch nicht gesetzt im ADC12CTL0. Außerdem solltest du nur
beim letzten der 3 Eingangskanäle den Interrupt setzen lassen, sonst
verhaspelt sich der Controller ja, wenn du nach jedem Kanal den IRQ
bekommst.
ADC12IE müsste dann auf 0x04, damit du nach dem 3. Kanal (nachdem
ADC12MEM2 geschrieben wurde) einen Int bekommst.
@Christian und Stefan
Endlich laueft es so wie es soll! Vielen Dank an euch beide und an
dieses grossartige Forum. Gerade fuer einen Anfaenger wie mich, gebt ihr
einfach super Tips.
Bernd
P.S meine naechsten Fragen kommen bestimmt bald :)