Moin,
ich arbeite mit einem MSP430FG4618 und möchte an 3 Pins jeweils ein
Rechtecksignal ausgeben. Diese sollen am Ende jeweils um 120°
Phasenverschoben sein.
Begonnen habe ich mit der Erzeugung eines Rechtecksignals.
Dazu habe ich den TimerB mit dem TimerClock ACLK definiert und ihn im
Continousmode gestartet.
Das Capture/Compare Register 0 verwende ich, um ein Rechtecksignal zu
erzeugen, was letztendlich auf Pin 5.1 ausgegeben wird.
Das klappt auch wunderbar.
Nun habe ich in meiner Unerfahrenheit einfach mal ein zweites Register
... Capture/Compare Register 1 ebenfalls mit einem Wert "32768"
beschrieben.
Das sorgt nun aber dafür, dass mein gesamtes Programm immer wieder von
vorne gestartet wird. Und zwar in dem Intervall, wie ich es über das
CCR1 definiert habe. Bei 32768 ist das 1 sec.
Kann mir nochmal jemand erklären, WARUM man für die Register das CCIE
setzt?
Ob mit dem Ausdruck TBCCTL0 = CCIE; das CCIE nur für das CCR0 gesetzt
wird, oder für alle CC-Register?
Und wie sorge ich dafür, dass das Taktsignal mit welches über TBCCR1
definiert ist, auf einen anderen PIN als P5.1 ausgegeben wird und nicht
ständig mein Programm neustartet bzw. von vorne abarbeitet?
Hoffe auf hilfreiche Hinweise.
Stefan.
CCIE aktiviert den Interrupt-Request für das jeweilige CCR.
Wenn du schon das zweite CCR mit Interrupts benutzt, solltest du dafür
auch den Interrupt-Handler definieren. Sonst springt die CPU ins
nirgendwo und das kann dann wie ein Reset wirken.
greg schrieb:> CCIE aktiviert den Interrupt-Request für das jeweilige CCR.>> Wenn du schon das zweite CCR mit Interrupts benutzt, solltest du dafür> auch den Interrupt-Handler definieren.
Was bedeutet das, "Interrupt-Handler"?
Meinst du eine Interrupt-Service-Routine?
Für das CCR1 klappt das dann sogar :)
Nun muss da noch ein 3. ran ... Allerdings gibt es keine Definition mehr
für
"#pragma vector=TIMERB2_VECTOR"
Und beide Signale laufen nun auch mit einer unterschiedlichen Frequenz.
Wie kann man beide Frequenzen aneinander anpassen? Nur über das
jeweilige Register? Oder muss ich noch TB1CTL definieren?
Eine alternative für 3 Rechtecksignale habe ich auch in den Beispielen
von TI gefunden. Das ist die msp430x46x_tb_10.c. Das sieht schonmal sehr
gut aus. Die Dutycycle hab ich schon so verändert, dass alle drei
Signale eine PWM von 50% ausgeben. Nun stellt sich nur noch die Frage,
ob man jeweils ein Signal um 120° Phasenverschieben kann? Und wenn ja,
wie man das macht :)
Jedes Register beinhaltet den gleichen Wert und gibt somit zur selben
Zeit seinen überlauf. Irgendwie müsste man dafür sorgen, dass bei dem
einen TCCR später angefangen wird mit zählen, als bei dem anderen. Und
das geht doch eigentlich nur, mit einem anderen Takt, oder?
Oder würde es auch mit einem Delay oder einer Whileschleife klappen?
Stefan M. schrieb:> Was bedeutet das, "Interrupt-Handler"?> Meinst du eine Interrupt-Service-Routine?>
Ja. Interrupt-Handler klingt IMO nicht ganz so hölzern. ;)
>> Nun muss da noch ein 3. ran ... Allerdings gibt es keine Definition mehr> für> "#pragma vector=TIMERB2_VECTOR">
Die Vektoren für die CCRs sind teilweise multiplexed, siehe Datasheet.
Du musst innerhalb deines Handlers dann bestimmen, welche Quelle der
Interrupt hatte.
> Und beide Signale laufen nun auch mit einer unterschiedlichen Frequenz.> Wie kann man beide Frequenzen aneinander anpassen? Nur über das> jeweilige Register? Oder muss ich noch TB1CTL definieren?>
Naja, die Frequenz justierst du doch selber, je nachdem wie du das
CC-Register verstellst... was meinst du damit?
> Eine alternative für 3 Rechtecksignale habe ich auch in den Beispielen> von TI gefunden. Das ist die msp430x46x_tb_10.c. Das sieht schonmal sehr> gut aus. Die Dutycycle hab ich schon so verändert, dass alle drei> Signale eine PWM von 50% ausgeben. Nun stellt sich nur noch die Frage,> ob man jeweils ein Signal um 120° Phasenverschieben kann? Und wenn ja,> wie man das macht :)>
Da musst du die richtigen Startbedingungen schaffen. Schalte den Timer
ab, setze das Timerregister und die CC-Register (jeweils um 120°
verschoben), schalte die IRQs ein und dann lasse den Timer loslaufen.
Gehen wir mal davon aus, du hast eine Periodenlänge von 6000
Timerzyklen.
6000 / 3 = 2000. Also kannst du bspw. den Timer auf 0xFFFF setzen und
die CCRs auf 0, 2000, 4000. In den Interrupt-Handlern inkrementierst du
die CCRs dann immer um 3000, um 50% duty cycle zu erreichen.
> Naja, die Frequenz justierst du doch selber, je nachdem wie du das> CC-Register verstellst... was meinst du damit?
Meine genau das ;)
> Da musst du die richtigen Startbedingungen schaffen. Schalte den Timer> ab, setze das Timerregister und die CC-Register (jeweils um 120°> verschoben), schalte die IRQs ein und dann lasse den Timer loslaufen.
Meinst du mit IRQ's einschalten TBCCTL0 = CCIE oder würde es auch mit
einem general interrupt gehene? Hm, glaube die Frage kann ich mir selbst
beantworten. mit einem GIE würde ja die Zuordnung zu den einzelnen
Registern fehlen :D
> Gehen wir mal davon aus, du hast eine Periodenlänge von 6000> Timerzyklen.> 6000 / 3 = 2000. Also kannst du bspw. den Timer auf 0xFFFF setzen und> die CCRs auf 0, 2000, 4000. In den Interrupt-Handlern inkrementierst du> die CCRs dann immer um 3000, um 50% duty cycle zu erreichen.
Ich benötige dann ja 3 ISR für den TimerB. Wie genau ist so eine Routine
denn aufgebaut und kann man die in der Headerdatei selber noch weitere
"nachdefinieren"?
Hier mal als Beispiel zur Erklärung für mich:
>// Timer B0 interrupt service routine>#pragma vector=TIMERB0_VECTOR>__interrupt void Timer_B (void)>{> P5OUT ^= 0x02; // Toggle P5.1> TBCCR0 +=500;>}
Also, welcher Teil bestimmt die Interruptzugehörigkeit?
ich würde ja jetzt einfach auf die folgende Zeile tippen:
>__interrupt void Timer_B (void)
Timer_B gibt es doch aber nur einmal. Das Interrupt vom RegisterX ist
doch entscheidend, oder?
Und wenn ich jetzt zum Beispiel TBCCTL0 = CCIE setze und TBCCTL1 = CCIE
...
woher weiß ich, oder wie bestimme ich in der ISR, das der registrierte
Interrupt von CCR0 kommt und nicht von CCR1?
Im Anhang mein bisheriger Fortschritt :D
Timer gestoppt, Timerregister0 gesetzt.
Den 120° Versatz habe ich noch nicht in die Register geschrieben, da mir
ja noch die IRQ's und die ISR's fehlen.
Also wenn ich das richtig verstanden habe, sollte das ganze so gehen.
Alle TimerB-Interupts gehen in die selbe Interrupt-Routine oder Handler
wie man will, dort ist es deine Aufgabe festzustellen, welcher Interrupt
es genau ist.
Es gibt für den Timer das TBIFG und den jeweiligen TBCCRx die jeweilige
Kombination zeigt genau an um welchen Interrupt es sich handelt, sprich
um welches C&C-Register. Da wir alle faul sind hat Ti aber das TBIV
register erfunden hier wird in 3 Bit reingeschreiben welcher Interrupt
ausgelöst wurde (Im User Manual unter Timer_B Interrupt Vector Register;
zumindest bei meiner Family).
Damit benötigst du nur einen ISR bzw. es gibt nur einen ISR und in
diesem stellst du dann wiederum fest, welches C&C ausgelöst hat.
Um einen anderen Ausgang zu belegen musst du ihn einfach Toggeln und ihn
vorher natürlich als Output definieren.
Fabian Hof schrieb:> Also wenn ich das richtig verstanden habe, sollte das ganze so gehen.> Alle TimerB-Interupts gehen in die selbe Interrupt-Routine [...]> dort ist es deine Aufgabe festzustellen, welcher Interrupt es genau ist.
Das zu hören freut mich schon mal, denn alle 3 Pins gleichzeitig togglen
kann ich ja. Und in eine ISR zu springen, hab ich ja auch schon
geschafft :D
> Es gibt für den Timer das TBIFG und den jeweiligen TBCCRx [...]TBIV> register [...]
Von diesem Flag und diesem Register habe ich schon gelesen in der
Dokumentation. Da ich aber bis eben noch so darauf fixiert war, die
ganze Problematik in mehreren ISR's zu verwirklichen, bin ich dieser
Sache noch nicht weiter nachgegangen.
Vielen Dank für deine Hilfe. Manchmal muss man die Dinge eben aus einer
anderen Sicht betrachten, um voran zu kommen :)
Mal sehen ob ich das morgen dann auf die Reihe bekomme. Für heute bin
ich erstmal bedient. Mein Compiler stürzt ständig ab -.-
Soooo,
hier mal ein Update. Allerdings noch nicht vollendet.
Alle PINS wurden Initialisiert und die CCR's ebenfalls gesetzt.
Allerdings glaube ich zu ahnen warum das ganze noch nicht so
funktioniert wie ich will.
Wie ihr seht, sind in der ISR die PINS P2.3 und P3.4 eigentlich
deaktiviert. Bzw. werden sie in der Routine nicht zum toggln angeregt.
Jedoch hab ich dennoch ein PWM Signal auf diesen PINS.
Hängt das mit der Pin-Initialisierung zusammen PxSEL ?
Damit wird doch die Funktion des PINs aktiviert, oder? Naja, steht
jedenfalls so im Datenblatt.
Aber wenn ich das PxSEL nicht setze, dann habe ich kein Signal am
Ausgang.
Hat da jemand vielleicht noch mal eine nette Umschreibung dieser
Problematik, wie ich meine PINs initialisieren muss, damit ich in der
ISR dann auch mittels TBIV des jeweilige CCRx Signal wählen kann.
Am Ende will ich das ja noch verschieben.
Und außerdem steht im Datenblatt auch, dass beim setzen des PxSEL = 1,
das Interrupt für diesen PIN deaktiviert wird. Dann könnte ich doch
eigentlich gar nicht mit so einer Initialisierung in die ISR hüpfen,
oder?
Also kann ich das PxSEL drin lassen :)?
Ich versuch das gleich mal mit dem Codebrocken von Fabian.
Ach und -->
> bei jeder hi/lo oder hi/lo
oder meinst du lo/hi bzw. lo/hi g
>> Damit springt er bei jeder> hi/lo oder hi/lo habs nicht im Kopf in den ISR.
Hm, also CM_2 ist wie du sagtest,
1
captureonfallingedge
Das heißt, dass er bei jeder fallenden Flanke ein TAIV auslöst?
Oder zwingt ihn das nur in die ISR?
Und was genau bezweckst du mit P1DIR &=~ 0x02; ? Ich weiß das die Tilde
negiert. Also aus ~01b = 10b macht.
Ich hatte meine Ports ja mit P1DIR |= 0x02; definiert.
Also er schmeißt den ISR und setzt das TAIV, sollte beides imemr
zusammen geschehen, anerst würde es zumindest für mich keinen Sinn
machen.
Richtig ~ negiert, &= ist das logische UND. Damit wir BIT1 mit 0 UND
verbunden somit wird BIT1 0. Ich will damit nur sicher gehen das der PIN
als Eingang definiert ist.
Ich würde an deiner Stelle meinen Code eins zu eins für TimerB
übernehmen und schauen ob du in den ISR kommst, klappt das, kannst du
dich um den Rest kümmern.
Ach so, der PIN muss als Eingang geschaltet sein. Aber wieso?
Bisher habe ich meine Signal doch aus diesen PINS erhalten.
Das erklärt natürlich, warum ich mit deinem Code erstmal kein
Ausgangssignal mehr an den PIN's sehe ^^
Bis hier hin, hab ich das nun mal alles mit deinem Code definiert.
Aber an welchen PIN's soll ich nun mein TOGGLE abgreifen?
Irgendein anderen. Zum Beispiel P5.1?
Dann hüpft man sozusagen in die ISR und sagt dort
Ich muss noch einmal in Worte fassen was mein Code von oben macht. Ich
hab das gefühl wir reden aneinander vorbei.
Mein Code macht folgendes:
Sobald an TA0 eine hi/lo Flanke kommt springt er in den ISR.
Dort kannst du machen was du willst.
Wenn ich dich jetzt richtig verstehe, willst du dein ISR auslösen, wenn
der TIMER B auf einen bestimmten Wert gezhält hat. Das unterscheidet
sich von meinem Code erheblich. Steht aber ganz genau in den TI
Beispielen.
Also wenn ich mir den Rest von oben noch einmal durchlese merk ich das
ich dir total falschen Code gegeben habe.
__bis_SR_register(LPM0_bits+GIE);// Enter LPM0 w/ interrupt
35
}
36
37
// Timer A0 interrupt service routine
38
#pragma vector=TIMERA0_VECTOR
39
__interruptvoidTimer_A(void)
40
{
41
P1OUT^=0x01;// Toggle P1.0
42
TACCR0+=50000;// Add Offset to TACCR0
43
}
Das TI Beispiel kann dann alles was du brauchst, du musst dir zusätzlich
noch überlegen wie du die 120° Phasenverschiebung sauber hinbekommst,
gerade wann die Interrupts ausegelöst werden müssen und die wie die
Zählerstände berechnet werden. Bei mir will es gerade nicht in den Kopf
das Mittagessen liegt mir wohl schwer im Magen.
Ja, sag ich doch ^^ Irgendwie stimmt das als Eingang nicht.
Aber diese falsch Information hat mich dazu getrieben, mehr in dem
Userguide zu lesen um auch mehr über das TBIV zu erfahren.
Der Unterschied bei ContinousMode und Upmode ist doch nur der, dass im
UpMode BIS zu dem Wert im CCR gezählt wird und dann beginnt der Timer
von 0. Und im ContinousMode, würde er den Interrupt bei erreichen des
CCRx_Wertes auslösen und dann einfach weiterzählen. Hier muss man also
in der ISR dann einen Offset einfügen, damit er den Zählabstand von 0
bis CCR einhält.
Sehe ich das richtig? Eigentlich logisch -g-
Allerdings habe ich noch Probleme, beim Verständnis des Offsets.
Vor der ISR wird TCCR0 = 5000;
1
TCCR0=5000;// CCR setzen
2
.
3
.
4
.
5
// ISR TIMERB VECTOR------------
6
voidTIMERB(void)
7
{
8
//mach was//
9
TBCCR0+=5000;// Add Offset
10
}
Der Timer zählt bis 5000, springt in die ISR, macht was, und wird dann
um 5000 addiert. Dann stünde er doch bei 10000 und zählt munter eine
Runde rum, oder nicht? Das kann natürlich nicht sein, dann am Oszi sehe
ich ja, dass es funktioniert und sich die Frequenz steigt erhöht, je
kleiner ich den Wert für mein CCR setze.
Und nun noch zu dem eigentlichen Problem:
-----------------------------------------
> ... du musst dir zusätzlich> noch überlegen wie du die 120° Phasenverschiebung sauber hinbekommst,> gerade wann die Interrupts ausegelöst werden müssen und die wie die> Zählerstände berechnet werden. Bei mir will es gerade nicht in den Kopf> das Mittagessen liegt mir wohl schwer im Magen.
Für die Phasenverschiebung habe ich noch keine Lösung. Aber ich denke,
ich muss eh erstmal genau herausfinden, wie ich die TBIV's unterscheide.
Wenn ich nur ein TBIV abfrage, klappt das und er toggelt mir den Pin,
den ich angebe. Wenn ich aber mehrere TBIV's abfrage, klappt es nicht.
(siehe Code im Anhang msp430xG46x_tb_TBIV.c)
Dann ist je nach dem Wert in dem jeweiligen CCR der zugeordnete PIN
aktiv.
Daraus würde ich nun schlussfolgern, dass die Zählweise des Timers nicht
so stattfindet, wie ich mir das vorstelle. Eigentlich erhalte ich ein
Interrupt, wenn der Timer das CCR0 register erreicht, hüpft in die ISR
toggelt P5.1 und fügt den Offset zu CCR0. Anschließend prüft er, ob das
TBIV von CCR1 gesetzt ist --> ist es nicht, dann prüft er ob TBIV von
CCR2 gesetzt ist --> ist es nicht, also wieder raus.
Nun die Frage, zählt der Timer weiter? Oder beginnt er wieder bei 0.
Wenn er wieder bei 0 anfängt, erreicht er doch nie den Wert von TBCCR1,
da dieser ja höher ist, als der vom TBCCR0.
In msp430xG46_tb_TBIV_funzt.c frage ich nur ein TBIV ab und erhalte hier
auch bei Signal an den entsprechenden PIN's.
P5 toggelt bei jedem Sprung in die ISR und für jeden Interrupt von TCCR1
erhalte ich einen Toggel an P2.2
Ich freue mich über jegliche Anregungen und Diskussion :)
Ok, versuchen wir mal Licht in den Offsetjungle zu bringen.
Offset heißt doch einfach das es ist eine Verschiebung der Gerade nach
oben. D.h. sie fängt nicht bei NULL an zu zählen sondern bei 5000. Mehr
steckt nicht dahinter.
In deinem Beispiel heißt Offset aber einfach nur Draufsetzen und
spiegelt somit deine halbe Periodendauer wieder.
Wir nehmen an. Du bist im ContMode bei 0, bei 1Mhz. Startest das
Programm.
CCR0=5000. Er zählt bis 5000 > Toggle + CCR0=5000+5000. Er zählt bis
10000 > Toggle + 10000+5000 .... usw. das heißt deine halbe Periodedauer
sind 5ms, deine ganze 10ms also 100Hz. Das ganze wird an P5.1
ausgegeben.
Damit ist deine Erklärung auch logisch, je kleiner ich CCR0 mache desto
schneller toggelt P5.1 und das heißt die Frequenz steigt.
Bei CCR1 und CCR2 das gleiche, nur das hier die Perioden anderst sind
und die Pins an dennen es ausgegeben wird.
Frage:
Das mit den verschiedenen TBIV klappt so wie es beschrieben ist?
Also die IF-Abfragen?
Versuch mal das TBIV irgendwie anzuzeigen so das du immer die jeweiligen
Werte darin siehst.
Als ich dein Code von oben einfach auf TimerA umgemünzt habe, ging alles
wunderbar, sprich es müssen unterschiedliche TAIV gekommen sein sonst
würde man nicht in die if´s kommen.
Leider bin ich nur noch 10 min im Geschäft, werd morgen noch einmal
schauen ob ich dahinter komm.
Gerade nerft mich mal wieder Eclipse.
Have a nice Day
Hi,
jetzt ist der Groschen gefallen. Das ernüchternde ist, dass ich mir das
so vor ein / zwei Monaten schonmal selbst erarbeitet habe. Aber
scheinbar war ich nun so verbissen darauf ein Lösung für meine
Phasenverschiebung zu finden, dass ich da völlig auf dem Schlauch stand.
Ich sollte wohl auch einfach etwas strukturierter an die Sache heran
gehen ^^
Kleine Schritte, Step by Step.
> Frage:> Das mit den verschiedenen TBIV klappt so wie es beschrieben ist?> Also die IF-Abfragen?
Leider klappt es nicht mit der TBIV Abfrage. Ich habe beim herumspielen
festgestellt, dass er die Ports in der ISR immer toggelt, egal welchen
Wert ich im TBIV abfrage.
Ich hab mir nochmal ein Beispielprog. genommen und nochmal mit ganz
wenig Code von vorne angefangen.
TimerB betrieben mit ACLK gibt mir eine Frequenz von 1/2 Hz aus. Also 1
Toggle pro Sekunde. In der ISR frage ich dann ab, ob der Interrupt vom
TBCCR0 ausgelöst wurde, wenn nicht, ob es vom TBCCR1 ausgelöst wurde.
Da das TBCCR1 einen halb so großen Wert beinhaltet wie TBCCR0, müsste
mein Signal vom TBCCR1 also doppelt so schnell sein. Beide Signal haben
aber die gleiche Frequenz :( Somit funktioniert es noch nicht.
Zur erläuterung hier ein Ausschnitt aus meinem Userguide:
Was ich auch nicht so recht verstehe...in der angehängten Datei soll in
der ISR eigentlich nur der PIN 2.2 getoggelt werden. Jedoch toggelt der
PIN 5.1 in der gleichen Frequenz, obwohl ich ihn in der ISR überhaupt
nicht anspreche. Und das TBCCR0 liegt eigentlich am PIN 2.1
Wie kann das sein?
Fabian Hof schrieb:> Versuch mal das TBIV irgendwie anzuzeigen so das du immer die jeweiligen> Werte darin siehst.
Meinst du über die Schrittweise Ausführung des Compilers ... da kann ich
mir den Inhalt der Register ja anzeigen lassen. Auch ob das CCIFG des
jeweiligen Registers (TBCCRx) gesetzt ist.
> Als ich dein Code von oben einfach auf TimerA umgemünzt habe, ging alles> wunderbar, sprich es müssen unterschiedliche TAIV gekommen sein sonst> würde man nicht in die if´s kommen.
Hast du dabei auch die ISR Bezeichnung geändert? Ich hab das versucht
mal nachzumachen, alles auf TimerA geändert und dann hatte ich plötzlich
die doppelte Frequenz. Bis mir dann aufgefallen ist, dass meine ISR
immer noch Timer_B0 hieß und mein Signal sozusagen ohne die ISR erzeugt
wurde.
Das erklärt auch dieses Problem:
> [es] soll in der ISR eigentlich nur der PIN 2.2 getoggelt werden. Jedoch> toggelt der PIN 5.1 in der gleichen Frequenz, obwohl ich ihn in der ISR> überhaupt nicht anspreche.
1
// Wait for xtal to stabilize
2
do
3
{
4
IFG1&=~OFIFG;// Clear OSCFault flag
5
for(i=0x47FF;i>0;i--);// Time for flag to set
6
}
7
while((IFG1&OFIFG));// OSCFault flag still set?
Mit diesem Code werden alle PIN's getoggelt, die man als Ausgang
definiert hat. Hatte nämlich noch mehr PIN's mit LED's als Ausgang
definiert und festgestellt, dass immer alle in der gleichen Frequenz
blinken.
Was genau jetzt im Mikrocontroller geschieht, kann ich noch nicht sagen.
Dazu muss ich erst nochmal den Userguide studieren.
Hm, ich habe gerade mein board wieder initialisiert, mein CCE gestartet
und das gleiche Progg übertragen, bei dem alle definierten Ports wegen
der While-Schleife im selben Takt blinken. Und jetzt blinkt nur ein PIN
... ohne ISR. Wieso blinken die anderen jetzt nicht :( ich krieg noch
die KRISE -,.-
Fabian Hof schrieb:> Versuch mal das TBIV irgendwie anzuzeigen so das du immer die jeweiligen> Werte darin siehst.
Moin,
im Anhang hab ich nochmal ein Codeschnipsel, mit dem ich gerade versuche
das TBIV zu unterscheiden. In der rechten Bildhälfte kann ich mir bei
einer step-by-step Programmausführung den Wert von TBIV jeweils anzeigen
lassen.
Die farbigen Punkte in der ISR stehen jeweils für die LED an dem PIN.
So wie der Code da steht, blinkt die rote und gelbe LED wechselseitig.
Also rot = an und gelb = aus anschließend rot = aus und gelb = an.
Die Ursache liegt wahrscheinlich darin, dass mit der Richtungsdefinition
P2OUT |=0x02; für die gelbe LED, diese sofort einschaltet.
Die grüne LED leuchtet niemals. Bei genauerer Betrachtung meines
ausführenden Codes im Step-by-Step-Mode, wird die ISR nur bei einem
TBIV(wert) = 0x00 betreten. Das TBIV nimmt zwar auch den Wert 0x02 an,
doch die ISR wird dabei nicht betreten.
Die Frage ist, weshalb nicht? Liegt das vielleicht an den Prioritäten
der Registerflags?
Und dann ist da noch eine Verständnisfrage. Was im Grunde an die
Prioritäten anknüpft.
Mein TBCCR0 CCIFG (TBIV0 sozusagen) hat die höchste Priorität.
Wenn mein TBCCR0 nun einen geringeren Wert als TBCCR1 beinhalten würde,
würde dann überhaupt jemals das Flag für TBCCR1 gesetzt werden?
Denn mein Timer zählt doch im UpMode jeweils bis zu meinem Registerwert
TBCCR0 und beginnt dann wieder bei 0. Wenn TBCCR1 dann einen höheren
Wert besitzt, würde der doch nie erreicht werden?!
Andererseits hab ich das Gefühl dass ich bei dieser Überlegung schon
wieder irgendwas nicht beachte, denn eigentlich wäre sowas doch
unpraktisch, oder?
Moin,
Stefan Marx schrieb:> Denn mein Timer zählt doch im UpMode jeweils bis zu meinem Registerwert> TBCCR0 und beginnt dann wieder bei 0. Wenn TBCCR1 dann einen höheren> Wert besitzt, würde der doch nie erreicht werden?!> Andererseits hab ich das Gefühl dass ich bei dieser Überlegung schon> wieder irgendwas nicht beachte, denn eigentlich wäre sowas doch> unpraktisch, oder?
Wenn man sich das ganze als Rennstrecke vorstellt, sprich du hast einen
Rundkurs der 32768m lang ist und an jedem CCRx stellst du ein Zeitmesser
auf.
Im ContMode fährst du Runde für Runde.
Im UpMode baust du aber eine Abkürzung ein(ok, die ist nicht 0m lang,
aber sagen wir sie ist theoretisch 0m lang) sagen wir bei 20000m, dann
heißt das doch, du befährst die Strecke von 20000m-32768m nicht. Wie
soll da die Zeit gemessen werden?
Stefan Marx schrieb:> Die grüne LED leuchtet niemals. Bei genauerer Betrachtung meines> ausführenden Codes im Step-by-Step-Mode, wird die ISR nur bei einem> TBIV(wert) = 0x00 betreten. Das TBIV nimmt zwar auch den Wert 0x02 an,> doch die ISR wird dabei nicht betreten.
Ich frag mich gerade wieso TBIV=0x02; sein kann. Tu hast TCCR2=x
auskommentiert, da dürfte kein ISR ausgelöst werden. Beziehungsweise, es
wird ja keiner ausgelöst, aber TBIV sollte dann wohl auch nicht
eingetragen sein.
Anmerkung:
TCCR0 kann man nicht abfragen(mein Verständnis) zumindest nicht im TBIV.
Siehe deine Tabelle vom 24.
Also im Anhang habe ich Code der bei mir so funktioniert, gerade eben
getestet. Er benutzt das CCR0, das auf CCR1 umzustricken sollte keine
Probleme bereiten. Außerdem muss beachtet werden das CCR0 nicht
abgefragt werden können. Das heißt also, dass der auszuführende Code im
Nein-Teil einer if sitzen muss. if (0x02) Esle if(0x04) else (CCR0)
Hi Fabian,
also deine Erläuterungen sind echt Klasse :)
Man erreicht den Abschnitt somit nie zwischen 20.000m und 32.768m.
Das erklärt auch, weshalb ich mich also an den ContMode halten muss.
> Ich frag mich gerade wieso TBIV=0x02; sein kann.
Weil dieser Wert für das TBCCR1 CCIFG steht. Also zu dem TBCCR1 gehört
;)
Das man TBCCR0 eigentlich nicht abfragen kann, da es da ja eigentlich
keinen Wert im TBIV gibt hab ich auch der Tabelle entnommen.
Den Wert 0 gibt es ja dennoch im TBIV. So das ich diesen dann halt
abgefragt habe. Logischerweise ohne zugehörigkeit zum TBCCR0. Was mir
erst jetzt klar geworden ist. Gut das wir darüber geredet haben g
Ich werde mich gegen Mittag nochmal ran setzen. Bis dahin muss ich
erstmal Labeln :(
Sooo,
wieder dem Ziel ein Schritt näher :)
Erst hatte ich die Abfrage
1
if(TBIV==0x02bzw0x04)
alles in der ISR vom TimerB0. Ein Interrupt durch die entsprechenen
Register TBCCR1 oder TBCCR2 führte mich nie in die ISR von diesem Timer,
sondern wurde einfach ignoriert. Dabei ging ich davon aus, dass jeder
Interrupt vom TimerB oder dessen Register mich in die ISR TimerB0
bringen wird.
Dem ist aber nicht so. Die ISR TimerBO reagiert nur auf Interrupts vom
TCCR0. Erst als ich die Abfrage für das TBIV von TBCCR1 und TBCCR2 in
die ISR TimerB1 verschoben habe, reagierte mein Programm auch auf deren
Interrupt. So explizit habe ich das allerdings nicht im Userguide
gefunden, sondern durch einen Freund erfahren. Oder kann mir da jemand
gegenteiliges berichten?
Nun besteht aber noch ein Problem. Dazu habe ich die PNG-Files 01- bis
03- TBIV0x04 mit angehängt. Wenn ich einen Interrupt vom TBCCR1 erhalte,
wird mein TBIV = 0x02 gesetzt. --> Sprung in ISR TimerB1 --> ABFRAGE
1
if(TBIV==0x02)
... positiv, also betritt er die if Schleife und löscht gleichzeitig
das TBIV --> toggle PIN und wieder raus.
Wenn ich einen Interrupt vom TBCCR2 erhalte, wird mein TBIV = 0x04
gesetzt. --> Sprung in ISR TimerB1 --> ABFRAGE
1
if(TBIV==0x02)
... negativ, also sprung zu
1
elseif(TBIV==0x04)
ABER gleichzeitig löscht er das TBIV --> ABFRAGE
1
elseif(TBIV==0x04)
--> negativ, da TBIV ja eben auf 0x00 zurückgesetzt wurde.
Laut Userguide wird das Interrupt nach der Bedienung durch die ISR
gelöscht bzw. zurückgesetzt. Also somit auch das TBIV. Frage: Ab wann
gilt denn ein Interrupt als bedient?
Nach dieser Erfahrung hier, nachdem es die ISR betritt, also nach der
ersten geschweiften Klammer.
Denkst du eine Switch Case Anweisung löst das Problem?
Morgen,
also wenn ich das richtig sehe(siehe Anhang) muss man ein switch
verwenden. Es scheint mir, das eine Abfrage des TBIV es automatisch
zurücksetzt, sagen kann ich das aber nicht mit Sicherheit, hab ich noch
nie gebraucht.
Im Anhang ist ein Code-Beispiel von TI was glaube ich genau deinen
Ansprüchen gerecht wird. Dabei kannst du dir sogar die unterschiedlichen
ISR sparen.
Moin moin,
heute ist ein guter Tag. Denn es ist endlich vollbracht :)
Die If-Abfragen habe ich durch eine Switch-Case-Abfrage ersetzt. Damit
kann jeder Wert im TBIV bearbeitet werden ;) Also, dass konnte man
vorher auch, aber bei der zweiten "else"-Abfrage war das Bit ja meist
schon zurückgesetzt.
Alternativ könnte man sicherlich den Inhalt vom TBIV in eine Variable
übertragen, die dann in der if-Abfrage überprüft wird.
Die Phasenverschiebung der 3 Signale konnte ich so realisieren, wie Greg
das im 4. Beitrag beschrieben hat :)
Jetzt muss noch die Periode für alle 3 Signale flexibel gemacht werden,
so dass man bei Betätigung von Taste 1, diese erhöht und bei Betätigung
von Taste 2, erniedrigt wird.
Entsprechende Codeschnipsel habe ich dafür schon ;)
Was mich noch interessieren würde ist, wie man kleine Unterprogramme in
extra c-files packt? Und ab wann man das machen sollte? Momentan ist das
nur Spielerei, aber es interessiert mich halt ^^
Servuz,
na dann sag ich mal gut Ding will weile haben.
Also zum auslagern brauchst du nur ein C-File und ein passendes H-File.
Wie das geht findet man im Netzt zur genüge.
Es lohnt sich vor allem dann, wenn du Funktionen benutzt, die in vielen
Files aufgerufen werden. Oder sehr viel Hirnschmalz drin steckt, viele
LOC oder du mit einem Aufruf viel erschlagen kannst.
Wiem an sich halt so eine Lib vorstellt.
Eine Frage hab ich allerdings noch.
Deine Rechtecke sind immer symmetrisch? Also kein PWM Signal?
Fabian Hof schrieb:> Eine Frage hab ich allerdings noch.> Deine Rechtecke sind immer symmetrisch? Also kein PWM Signal?
In diesem Fall sind sie symmetrisch. Ich will einen 3 Phasenmotor
ansteuern. Das hab ich erst auf elektronischen Wege versucht und mir
diesen dabei zerschossen. Hätte ich mal noch ein paar Dioden mit in die
Schaltung gehangen ^^
Naja, und um den dort verwendeten Treiberbaustein besser zu verstehen
wollte ich die Hallsignale des Motors simulieren. Diese sind immer
symmetrisch und variieren nur in ihrer Frequenz.
In einem späteren Schritt, werde ich versuchen aus diesem Code ein PWM
zu erzeugen.
Hier mal noch ein Update mit ein paar extra features :)
Beim starten des Programms wird ein Signal wiedergegeben. Startsound
sozusagen. Beim betätigen der Tasten wird ebenfalls ein Sound
wiedergegeben. Taster 1 sorgt für ein Ansinken der Signalfrequenz und
Taster 2 für ein ansteigen. Wird der jeweilige Minimal- oder Maximalwert
erreicht, ertönt ein Fehlersignal.
Dummerweise stimmt der Phasenversatz nach Betätigung der Taster nicht
mehr.
Ich bin mir nicht sicher woran das liegt. Meine TBCCRx Register fülle
ich durch Variablen, die ich vorher definiert habe.
1
2
TB0=1219;
3
TB1=TB0/3;
4
TB2=TB0/3*2;
5
TB3=TB0-1;
Die Register fülle ich dann einfach mit
1
TBCCR1=TB1;
Wird ein Taster gedrückt, verändere ich den Wert im TB0 mit:
1
TB0+=122;
Meine obere Grenze für TB0 ist 1214 und die niedrigste 360.
Der Phasenversatz soll zwischen TB1 bis 3 jeweils um ein drittel
betragen.
Was könnte die Ursache sein, dass dieses Verhältnis nicht eingehalten
wird?