Moinsen,
ich betreibe hier ein MSP in Kombination mit einem Propeller.
Der Propeller spricht den MSP per SPI an und schickt ihm Befehle.
Aktuell soll er bei dem Eingang von 0x20 die Dauer von einer Periode
messen.
Dazu wird ein irq bei steigender Flanke ausgelöst und der Timerwert
gespeichert.
Dieses wird 6mal gemacht und dann als Mittelwert verschickt.
Frequenz wird per NE555 erzeugt und liegt bei 1200 Hz.
Das Signal sieht am Oszi auch gut aus.
Der Timer-Wert liegt bei ca. 98 und das stimmt nicht, er müsste bei
ca.900 liegen.
anbei mal der Code - ich schätze ich habe mir irgendwo mit den IRQ
verhaspelt ich finde es nur nicht.
1
/*
2
* Clockfrequenz:
3
* Timer mit SMCLK im Contmodus
4
* Spi sende 16 bit als 2x8bit; LSB_First und aktiviere dann erneut rx-IRQ
5
* ADC GND - Vreff = VCC
6
Warte auf SPI Input
7
- je nach rx-Bit
8
0x01: Starte ADC mit A0
9
0x20: Starte IRQ auf P2.0 bei low2high, bei auslösen der irq speicher TAR, messer 6 IRQ und bilde dann Durchschnitt der Differenzen und schicke per SPI
10
0x40: Starte IRQ auf P2.1 bei low2high, bei auslösen der irq speicher TAR, messer 6 IRQ und bilde dann Durchschnitt der Differenzen und schicke per SPI
Achso, jetzt habe ich es verstanden.
Vergiss die zwei letzten Posts mit den Mittelwerten.
Zum Überprüfen der Timereinstellungen kannst du SMCLK auf einen Pin
ausgeben. SMCLK müsste ja eine Frequenz von 1 MHz haben.
Außerdem kannst du einen Pin auf High setzen, sobald die ISR gestartet
wird. Am Oszi kannst du dann sehen, wann bzw ob die ISR aufgerufen wird.
Ich konnte jetzt keinen Fehler sehen.
1. Ein Überlauf von TA0R könnte auftreten, während du deine Werte
speicherst (und das ist garnicht mal so unwahrscheinlich, ist doch die
Differenz von Messwert 1 bis Messwert 6 = 5000 TA0R
2. Ein Signal von 1200Hz würde bei 1MHz: 833 Cycles bedeuten, die der
Timer zwischendrin den Counter erhöht.
3. Auch könnte ich mir vorstellen, dass du mit deinem IRQ zu langsam
bist, schau mal ins Disassembly wie viel Zyklen deine Port-ISR braucht.
Ich würde dort ausschließlich TAR samplen, den Rest in der main
erledigen. Auf volatile Variablen achten.
4. Auch ist int ein dehnbarer Begriff, ich weiß nicht wie breit er auf
dem MSP ist, inkludiere inttypes.h und nutze uint16_t für deine
Variablen, dann entspricht das der Bitbreite von TA0R.
An der reinen Initialisierung der Interrupts sehe ich keine Probleme
gerade.
SB schrieb:> 1. Ein Überlauf von TA0R könnte auftreten, während du deine Werte> speicherst (und das ist garnicht mal so unwahrscheinlich, ist doch die> Differenz von Messwert 1 bis Messwert 6 = 5000 TA0R
1 Überlauf würde durch unsigned Rechnereei automatisch berücksichtigt,
da braucht man dann nichts tun. Es kommt automatisch das Richtig raus.
Solange es sich also nur um 1 Überlauf handelt würde es reichen die
entsprechenden Variablen unsigned zu machen um diesen Punkt abzuhaken.
(Das ist doch ein 16 Bit Timer, oder nicht?)
Danke für die Verschiedenen Antworten, hier erstmal die Lösung:
In dem Port IRQ, wird leider nicht der Richtige IRQ wieder zurück
gesetzt:
Statt
1
}
2
*P1IFG*&=~BIT0;// P2.0 IFG cleared
3
}
4
//P2.0
muss es natürlich
1
}
2
*P2IFG*&=~BIT0;// P2.0 IFG cleared
3
}
4
//P2.0
sein.
Zu dem Rest:
Die Mittelwertbildung ist so natürlich Blödsinn, da ich mir aber die
einzelnen Cases angeschaut habe und die immer gleichmässig ware, habe
ich das als nächstes Problem verschoben :)
Überlauf wurde ja schon geklärt, werde die Variablen unsigned machen.
Hat das eigentlich irgendwelche Nachteile - ausser wenn ich wirklich
negative Zahlen bräuchte?
Das mit den SMCLK und IRQ nach aussen zu legen ist echt ne super Idee,
war zwar jetzt nicht nötig, aber danke! Werde ich das nächste Mal sicher
gebrauchen können.
Ich werde versuchen die IRQ auszudünnen, um speicher und Rechenzeit zu
sparen.
mfg
Zeus Mclane schrieb:> Die Mittelwertbildung ist so natürlich Blödsinn,
Würde ich so nicht sagen.
Dadurch, dass du die Zählerstände speicherst, hast du damit automatisch
eine Aufsummierung. Wenn du die Differenzen aufsummieren würdest, würde
auch nichts anderes rauskommen. Natürlich nur, solange es keinen
arithmetischen Ovberflow gibt.
> Überlauf wurde ja schon geklärt, werde die Variablen unsigned machen.> Hat das eigentlich irgendwelche Nachteile - ausser wenn ich wirklich> negative Zahlen bräuchte?
Nein. Ganz im Gegenteil: Wenn du von vorne herein weißt, dass etwas nur
positiv sein kann, dann SOLLST du unsigned nehmen. Zum einen gewinnst du
dadurch ein 'Zähl'bit mehr, zum anderen eröffnest du dem Compiler
Optimierungsmöglichkeiten.
Bei einem unsigned Wert kann man Divisionen durch 2-er Potenzen (bzw.
die Umkehrung: Multiplikationen) durch Schiebeoperationen ersetzen. Bei
signed Werten funktioniert das aber nicht: negative Werte werden dann in
die falsche Richtung abgeschnitten. -3 / 2 ergibt nun mal den C-Regeln
nach -1 (echte Division) und nicht -2 (1 mal rechts Schieben).
@Karl Heinz Buchegger
ok, du hast Recht, durch die Aufsummierung erhalte ich natürlich nichts
Anderes. Aber ich kann Speicher Sparen, in dem ich nur den ersten und
letzten Wert speicher und diesen dann teile.
Macht also auch sinn Mittelwert aus n werten zu bilden um mittels
bit-shift schneller zu teilen. Also zum Beispiel 5 Werte damit man 4
Differenzen hat ?!
Zeus Mclane schrieb:> Macht also auch sinn Mittelwert aus n werten zu bilden um mittels> bit-shift schneller zu teilen.
Nur der Vollständigkeit halber: Da fehlt was. Nämlich der Satzteil:
wobei n-1 eine 2-er Potenz ( 1, 2, 4, 8, 16, 32, ...) sein soll.
Ist das nicht der Fall, kannst du (besser gesagt der Compiler) auch
keinen Bitshift einsetzen.
Das soll jetzt bedeuten:
Wenn du Zahlen willkürlich benutzen darfst, dann sind 2-er Potenzen
meistens eine gute Wahl.
Kümmere DU (als Programmierer) dich darum, die richtigen Datentypen zu
benutzen. Und wenn du dividieren willst oder musst, dann schreib auch
Division. Wenn es da einen Trick gibt, dann kennt ihn dein Compiler (der
kennt mit Sicherheit mehr derartige Tricks als du). Das ist nichts was
dir groß Kopfzerbrechen machen muss.