Hallo, ich arbeite an einem Projekt, wo mit einem MSP430F2274 u.a. eine
Phasenanschnittsteuerung (Einquadrantensteller) realisiert werden. Die
Hardware ist schon fertig, desshalb gibt es da nichts mehr zu verändern.
Zum Programmieren haben wir TIs Code Composer Studio v4.2.4 und
SpiBiWire zum flashen und debuggen. Der MCLK und SMCLK sind auf 1MHz
eingestellt. Programmiert wird in C.
Die Voraussetzungen sind folgende:
Am Port 4.4-4.7 sowie Port 2.0-2.2 hängt ein Textdisplay. An den Ports
2.3, 2.4, 3.6 und 3.7 ließt der A/D-Wandler Werte ein, wobei an 3.7 über
ein Poti der Zündwinkel alpha eingestellt wird. Die Zündimpulse für die
Thyristoren werden an Port 4.0-4.3 ausgegeben, dabei sind 4.0/4.3 bei
positivem Sinus an bzw. 4.1/4.2 bei negativem Sinus an.
Am Port1 ist eine 4x4-Matrix-Tastatur angeschlossen, mit der man durch
ein Bedienmenü navigiert. Bei Tastendruck wird der Interrupt von Port1
und dessen ISR aktiv. Sobald man im entsprechenden Betriebsmenu ist,
wird der Port1-Interrupt ausgeschalten und es ist keine eingabe mehr
möglich, was so gewollt ist.
In der Endloseschleife in main() werden die 4 A/D-Kanäle ausgelesen und
auf dem Display dargestellt.
An Port 2.5 kommt eine netzsynchrone Rechteckspannung an, die bei
positiver Sinushalbwelle LOW und bei negativer Sinushalbwelle HIGH
ergibt. Entsprechend wird von mir in der Port2-ISR, das Interrupt Edge
Select Flag getoggelt, ebenso wird dies hier in eine globale Variable
geschrieben. um die Spannungsnulldurchgäng der Netzspannung zu erfassen.
Zwischen den Interrupts liegen exakt 10ms (50Hz = 20ms, davon jede
HALBwelle also 10ms).
In der P2-ISR wird dann vom A/D-Wandler das alpha abgefragt und in die
Verzögerungszeit umgerechnet, diese Wert weise ich dem
Capture/Compare-Register0 vom Timer A (TACCR0) zu, der Timer läuft los.
P2-ISR ist zuende und es geht ins Hauptprogramm (LCD beschreiben).
Bei alpha=90° muss nach 5ms+Offset der TimerA0-Interrupt kommen und in
dessen ISR werden die Tyristor-Ports 4.0/4.3 bzw. 4.1/4.2 auf OUT
gesetzt und nach einem delay nach 500µs wieder gelöscht.
Alpha<10 bzw. >170 starten den Timer nicht und es die Zündsignale
bleiben aus. Damit die TimerA0-ISR immer fertig ist, wenn Port 2.5 den
Interrupt zum Flankenwechsel bekommt.
Soweit die Theorie.
Leider kommt der µC irgendwie mit dem Timer nicht zurecht und verursacht
ein RESET, wobei alles von vorne beginnt.
In der Initialisierung wird
1
voidtimerA_Init(void)
2
{
3
TACCR0=0x0000;
4
TACTL=TASSEL_2+ID_0+MC_1;
5
}
aufgerufen. Die P2-ISR und die TimerA0_ISR sind:
1
#pragma vector=PORT2_VECTOR
2
__interruptvoidP2_ISR(void)
3
{
4
P2IFG&=~BIT5;
5
port2_irf();
6
}
7
8
UCHARport2_irf(void)
9
{
10
volatileUINTalphaADC,alpha_time1;
11
volatileconstfloatalfl=9.765625;
12
alphaADC=0;
13
alpha_time2=0;
14
15
if(P2IES&BIT5)
16
{
17
thy14out=1;
18
}
19
else
20
{
21
thy14out=0;
22
}
23
P2IES^=BIT5;
24
25
if(menuvar&F_m1m)
26
{
27
alphaADC=adc_get_value(3);
28
if((alphaADC>=57)&&(alphaADC<972))
29
{
30
alpha_time1=(UINT)((float)(1022-alphaADC)*alfl);
31
TACTL|=TAIE;
32
TACCTL0=CCIE;
33
TACCR0=alpha_time1;
34
}
35
else
36
{
37
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
38
TACCTL0&=~CCIE;
39
TACTL&=~TAIE;
40
TACCR0=0x0000;
41
P2IFG&=~BIT5;
42
return0;
43
}
44
}
45
46
return1;
47
}
48
49
50
#pragma vector=TIMERA0_VECTOR
51
__interruptvoidTimer_A0_ISR(void)
52
{
53
TACTL&=~TAIE;
54
//TACTL &= ~TAIFG;
55
//TACCTL0 &= ~CCIFG;
56
//TACCR0 = 0x0000;
57
timerA0_irf();
58
}
59
60
voidtimerA0_irf(void)
61
{
62
63
if((thyon==0)&&(thy14out==1))
64
{
65
P4OUT|=BIT0+BIT3;
66
thyon=1;
67
delay_us(500);
68
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
69
}
70
elseif((thyon==0)&&(thy14out==0))
71
{
72
P4OUT|=BIT1+BIT2;
73
thyon=1;
74
delay_us(500);
75
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
76
}
77
78
}
Ob ich die oben ich die auskommentierten Zeilen wieder aktiviere oder
nicht, spielt keine Rolle, der RESET finde trotzdem statt.
Meine Vermutung ist, dass der Stack-Pointer irgendwie durcheinanderkommt
und dann die Reißleine zieht.
Ein Koriosum für mich ist, das es mit folgender Programmierung zu laufen
scheint, wenn auch nicht ganz sauber(manche Zündimpulse sind
gelegentlich verschoben, trotz konstantem alpha).
1
#pragma vector=PORT2_VECTOR
2
__interruptvoidP2_ISR(void)
3
{
4
port2_irf();
5
}
6
7
UCHARport2_irf(void)
8
{
9
volatileUINTalphaADC,alpha_time1;
10
volatileconstfloatalfl=9.765625;
11
alphaADC=0;
12
alpha_time2=0;
13
14
if(P2IES&BIT5)
15
{
16
thy14out=1;
17
}
18
else
19
{
20
thy14out=0;
21
}
22
P2IES^=BIT5;
23
if(menuvar&F_m1m)
24
{
25
alphaADC=adc_get_value(3);
26
if((alphaADC>=57)&&(alphaADC<972))
27
{
28
alpha_time1=(UINT)((float)(1022-alphaADC)*alfl);
29
30
31
TACCTL1=CCIE;
32
TACTL|=TAIE;
33
TACCTL0=CCIE;
34
TACCR1=alpha_time1;
35
TACCR0=alpha_time1+500;
36
}
37
else
38
{
39
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
40
TACCTL1&=~CCIE;
41
TACCTL0&=~CCIE;
42
TACTL&=~TAIE;
43
TACCR0=0x0000;
44
TACCR1=0x0000;
45
P2IFG&=~BIT5;
46
return0;
47
}
48
}
49
return1;
50
}
51
52
53
#pragma vector=TIMERA1_VECTOR
54
__interruptvoidTimer_A1(void)
55
{
56
TACTL&=~TAIFG;
57
TACCTL0&=~CCIFG;
58
timerA1_irf();
59
}
60
61
voidtimerA1_irf(void)
62
{
63
switch(TAIV)
64
{
65
case2:
66
if((thyon==0)&&(thy14out==1))
67
{
68
P4OUT|=BIT0+BIT3;
69
thyon=1;
70
delay_us(500);
71
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
72
TACCR0=0x0000;
73
}
74
elseif((thyon==0)&&(thy14out==0))
75
{
76
P4OUT|=BIT1+BIT2;
77
thyon=1;
78
delay_us(500);
79
P4OUT&=~(BIT0+BIT1+BIT2+BIT3);
80
TACCR0=0x0000;
81
}
82
break;
83
case4:
84
break;
85
case10:
86
break;
87
}
88
}
89
90
91
#pragma vector=TIMERA0_VECTOR
92
__interruptvoidTimer_A0_ISR(void)
93
{
94
//bleibt hier leer
95
}
D.h. hier läuft der Timer bis zum CCR1-Event, der µC macht in der
TimerA1-ISR was er soll, löscht dann aber das Endziel. Nach außen
scheint alles dann in Ordnung.
Ursprünglich sollte nach alpha_time1+500µs also in der TimerA0-ISR die
Zündimpulse wieder gelöscht werden, was auch nur unzuverlässig geklappt
hat. Die Zündimpulsbreite (ZIB) hat permanent geschwankt, nur das
delay_us(500) hat die ZIB "stabilisiert" auf kosten freier 500µs
Rechenrechenzeit also 5% vom 10ms-Intervall.
Funktioniert
> Der MCLK und SMCLK sind auf 1MHz> eingestellt.
mit einem "busy wait" von ...
> Bei alpha=90° muss nach 5ms+Offset der TimerA0-Interrupt kommen und in> dessen ISR werden die Tyristor-Ports 4.0/4.3 bzw. 4.1/4.2 auf OUT> gesetzt und nach einem delay nach 500µs wieder gelöscht.
... 500µs in der ISR? Ich würde die "busy delay" durch eine kleine
"state machine" in der Timer-ISR ersetzen.
Das mag Ansichtssache sein, aber die andere ISR ist m. E. auch etwas
überfrachtet. Da gehört "floating point" nicht unbedingt rein, vor allem
angesichts der Taktfrequenz. Auch das Auslesen des ADCs.
Wofür ist "volatile const" gut?
Und das erste "volatile" in der port2_irf?
Den Timer-Interrupt würde ich erst dann aktivieren, wenn die anderen
Register vorher beschrieben wurden.
Wenn ich das richtig sehe, aktivierst Du zwei Timer-Interrupts: Eine mit
CCIE, die andere mit TAIE (overflow). Wie sieht die dazu gehörende ISR
aus?
Roland H. schrieb:> Funktioniert>>> Der MCLK und SMCLK sind auf 1MHz>> eingestellt.>> mit einem "busy wait" von ...>>> Bei alpha=90° muss nach 5ms+Offset der TimerA0-Interrupt kommen und in>> dessen ISR werden die Tyristor-Ports 4.0/4.3 bzw. 4.1/4.2 auf OUT>> gesetzt und nach einem delay nach 500µs wieder gelöscht.>> ... 500µs in der ISR? Ich würde die "busy delay" durch eine kleine> "state machine" in der Timer-ISR ersetzen.>> Das mag Ansichtssache sein, aber die andere ISR ist m. E. auch etwas> überfrachtet. Da gehört "floating point" nicht unbedingt rein, vor allem> angesichts der Taktfrequenz. Auch das Auslesen des ADCs.>> Wofür ist "volatile const" gut?> Und das erste "volatile" in der port2_irf?>> Den Timer-Interrupt würde ich erst dann aktivieren, wenn die anderen> Register vorher beschrieben wurden.>> Wenn ich das richtig sehe, aktivierst Du zwei Timer-Interrupts: Eine mit> CCIE, die andere mit TAIE (overflow). Wie sieht die dazu gehörende ISR> aus?
Danke erstmal für die Anwort.
Die "volatiles" habe ich nur reingeschrieben, weil ich beim debuggen
festgestellt habe, Wetzuweisungen wie
1
alphaADC=0;
2
alpha_time2=0;
in der P2-ISR nicht funktionierten. Nach den Zeilen waren die Variablen
eben nicht Null, mit volatile aber schon.
Gleiches gilt für die
1
constfloatalfl=9.765625;
, Wert blieb war nicht der zugewiesene.
Das delay in der Timer-ISR wollte ich ja, wie im 2. Beitrag (unten)
beschrieben, durch die Nutzung von CCR1=alpha_time (Thyristoren ein) und
CCR0=alpha_time+500 (Thyristoren aus) lösen. Aber auf dem Oszilloskop
war der Abstand zwischen der steigen und der fallenden Flanke an den
oben erwähnten Thyristor-Ports keine konstanten 500µs. Die Zündimpulse
"zitterten". Keine Ahnung warum.
Zu den Fließkommazahlen in der P2-ISR: Irgendwie muss ich ja aus dem
A/D-Wert für alpha die Zeitverzögerung berechnen und das geht nicht mit
ganzen Zahlen. Weil 180° 10ms=10000µs entsprechen. Die Subtraktion macht
0 A/D-digit = 180° bzw. 1024 = 0°, d.h. Poti nach links kleine Drehzahl,
Poti nach recht große Drehzahl. Ich bekomme bei 150° am Poti vom
A/D-Wandler einen Wert von 853, bei 30° = 171 usw. und multipliziere
dann mit
10000µs/1024digit = 9.765625 = alfl, dadurch bekomme ich die genaue Zeit
die ich den Teimer übergebe. Nur mit Integer geht das nicht, denke ich
zumindest.
Wenn ich TAIE nicht aktiviere komme ich doch nie in die TimerA0_ISR,
weil diese ja im Up-Mode auf CCR0 triggert. Ein TAIV-Ereignis für CCR0
gibt es ja nicht.
Roland H. schrieb:>...>> ... 500µs in der ISR? Ich würde die "busy delay" durch eine kleine> "state machine" in der Timer-ISR ersetzen.>
Welche Zustand soll ich denn auswerten, wenn ein Ereignis exakt 500µs
nach einem anderen eintreten soll, außer durch ein weiteren
Timerinterrupt?
Aufbauend auf dem Quellcode aus meinem zweiten Beitrag oben, also mit
TimerA1_ISR und TimerA0_ISR:
Wie gerade oben beschrieben klappt das nicht in Hardware. Mit dem "Oszi"
erkenne ich, das die Zündimpulse zwar einigermaßen extakt beginnen, aber
enden tun sie nie konstant nach der gleichen Zeit.
Hab' mir Deinen Code jetzt nicht genau angeschaut.
Hatte jedoch mal ein ähnliches Problem, das ich nur dadurch in den Griff
bekommen habe, indem ich den Port-IRQ (Trigger auf 50Hz) in der ISR
sperren musste, da durch diverse Störungen beim Zünden des Thyristors
die ISR gleich wieder angesprungen wurde.
Bei Lust und Laune kannst Dir das ja mal anschauen:
Beitrag "MSP430 NiCd-Ladegerät mit -dU"
> Wenn ich TAIE nicht aktiviere komme ich doch nie in die TimerA0_ISR,> weil diese ja im Up-Mode auf CCR0 triggert. Ein TAIV-Ereignis für CCR0> gibt es ja nicht.
Doch. Eben nur mit CCIE. Das genügt. Es sind zwei verschiedene
Interrupts, welche in derselben ISR landen.
Entferne: TACTL |= TAIE;
In der Timer-ISR: Statt //TACCTL0 &= ~CCIFG;
-> sinngemäß: TACCTL0 &= ~CCIE;
In der ISR wird dann nach dem CC-Interupt der "overflow interrupt"
abgeschaltet. D. h. beim nächsten CC-Interrupt wird diese ISR wieder
betreten, welche dann u. U. noch in der delay() hängt.
> Zu den Fließkommazahlen in der P2-ISR: Irgendwie muss ich ja aus dem> A/D-Wert für alpha die Zeitverzögerung berechnen und das geht nicht mit> ganzen Zahlen.
Schon. Aber nicht in der ISR, sondern in main(). In der ISR die Eingabe
des Users festhalten, und dann alles in main auswerten (float + ADC).
Spielt hier aber vermutlich keine Rolle.
> Welche Zustand soll ich denn auswerten, wenn ein Ereignis exakt 500µs> nach einem anderen eintreten soll, außer durch ein weiteren> Timerinterrupt?
Die Lösung hast Du eben selbst im Nachsatz beschrieben. Als Status
genügt eine bool.
Es gab ein Verständnisproblem meinerseits. Ich hatte schon das TACTL |=
TAIE; gelöscht bevor ich die letzten Beiträge oben gelesen hatte. Das
RESET-Problem ist erstmal weg.
Ich füttere jetzt wieder das TACCR1 mit alphatime und TACCR0 mit
alpha_time+500:
In der TimerA1-ISR werden die Thyristoren gezündet und TACCTL1 &= ~CCIE
sowie TACCR1 = 0x0000 gesetzt und in der TimerA0-ISR werden die
Thyristoren wieder gelöscht und TACCTL1 &= ~CCIE sowie TACCR0 = 0x0000
gesetzt.
Leider zucken die Zündimpulse auf dem "Oszi" vorallem im mittleren
Bereich (alpha ca. 90°) stark und ungleichmäßig hin und her. Dies gilt
für die steigenden Flanken (TimerA1-ISR) als auch bei fallenden Flanken
(TimerA0-ISR).
Wenn ich in der Endlosschleife der main() (LCD beschreiben mit einigen
delays) alles auskommentiere wird das Zittern wesentlich ruhiger, ist
aber nicht ganz weg.
Wie kann denn die Hauptschleife die ISRs verzögern, wenn dort die
Interrupts nie gesperrt werden?
Ein weiterer Punkt von "batchman":
Die A/D-Wandlerabfrage und Berechnung der Verzögerungszeit von der
P2-ISR in die Hauptschleife zu verlegen.
Das ist ein Riesenproblem, weil ich nach jedem Nulldurchgang des Netzes
als dem Interrupt auf Port 2.5 immer die neuesten Werte vom A/D-Wandler
brauche, um darauf zu reagieren zu können.
In den hier einfachen Phasenanschnittsmodus mag dein Vorschlag noch in
Ordnung sein, aber ich muss noch zwei weitere Betriebsmodi
programmieren. Einen mit PI-Regler und einen mit PI-Regler und
unterlagerter Stromregelung. D.h. Drehzahl und Strom, die ADC-Kanal 4
und 6 aufgenommen werden, haben unmittelbaren Einfluss auf alpha und der
Verzögerungszeiten, die in TACCR1 und TACCR0 geschrieben werden müssen.
> Leider zucken die Zündimpulse auf dem "Oszi" vorallem im mittleren> Bereich (alpha ca. 90°) stark und ungleichmäßig hin und her. Dies gilt> für die steigenden Flanken (TimerA1-ISR) als auch bei fallenden Flanken> (TimerA0-ISR).
Ich verstehe es fachlich (= Motoransteuerung) nicht. Ich kann es nur von
der SW her beurteilen.
Ich bleibe bei meiner Einschätzung: M. A. nach ist es für 1 MHz Takt "zu
viel" in den ISRs. Insbesondere mit "float", ADC und delays. Das ist
nicht viel Luft. Hat Deine CPU einen NVIC?
Ich werde mich nicht durch die Menusteuerung wühlen: Ist dafür gesorgt,
dass diese "entprellt" ist?
> Wenn ich in der Endlosschleife der main() (LCD beschreiben mit einigen> delays) alles auskommentiere wird das Zittern wesentlich ruhiger, ist> aber nicht ganz weg.
Wundert mich nicht bei 1 MHz und 500µs delay in einer der ISRs.
Welche Interrupts sind denn nun alle aktiv? Damit meine ich auch
diejenigen, die versehentlich aktiv sind. Wäre nicht das erste Mal ...
> Wie kann denn die Hauptschleife die ISRs verzögern, wenn dort die> Interrupts nie gesperrt werden?
Wie sind die "delays" in main() implementiert? Zeige mal bitte den
Quelltext der delay-Funktionen.
> Ich verstehe es fachlich (= Motoransteuerung) nicht. Ich kann es nur von> der SW her beurteilen.
An der Schaltung hängt noch kein Motor, sondern erstmal nur "Potis", die
quasi die Ist-Drehzahl und die Ist-Strostärke simulieren, damit der
A/D-Wandler einen brauchbaren Wert bekommt. Im aktuellen Betriebsmodus
ist aber nur das Stellpoti für alpha interessant. Un wenn ich von
Zündimpulsen schreibe, dann meine ich die High-Signale, die an den Ports
4.0-4.3 ausgegeben werden. Die Zündimpulsbreite heißt dann die Zeit vom
Einschalten bis zum Ausschalten der Signale, die ja idealerweise 500µs
lang sein sollte.
> Hat Deine CPU einen NVIC?
Ich kenne die Abkürzung "NVIC" nicht, gibts dafür einen anderen Begriff?
> Ich werde mich nicht durch die Menusteuerung wühlen: Ist dafür gesorgt,> dass diese "entprellt" ist?
Das man eine Menüsteuerung entprellen muss wusste ich nicht, aber die
Tastatur ist entprellt. Der Port1 an dem die Tastatur hängt ist nach der
Betriebsmodiauswahl, also wärend des eigentlichen Betriebs gesperrt.
Port 1 hat in der IRQ-Tabelle sowieso die niedrigste Priorität.
> Wie sind die "delays" in main() implementiert? Zeige mal bitte den> Quelltext der delay-Funktionen.
Da gibt es keinen Quellcode. __delay_cycles() ist eine
Intrinsic-Funktion des Compilers in CCSv4, die sich nach dem MCLK also
Master Clock richtet.
An dem µC ist ein 8MHz-Quarz angeschlossen und mit
1
BCSCTL2=SELM_3+DIVM_3+SELS+DIVS_3;
wurde MCLK = SMCLK = ACLK/8 = 8MHz/8 = 1MHz festgelegt.
__delay_cycles(1) entsprechen also exakt 1µs und __cycle_delay(1000) =
1ms usw., was ich auch messtechnisch nachgeprüft habe.
Ich habe jetzt mal etwas anderes probiert. Indem ich die Berechnung aus
der P2-ISR rausgenommen habe und statt dessen ein array erzeugt mit
[1024][2] Dimensionen. Leider braucht sowas viel Speicher, aber ich bin
damit ja erst bei rund 10kB von 32kB möglichen.
Jede Zeile steht dabei für einen Stellenwert das 10Bit-ADC. In Spalte 1
sind die Zeiten für den Timer und in Spalte 2 die alpha zum Anzeigen für
das LCD eingetragen. Es wird also nichts mehr gerechnet, sondern nur
noch der Wert assoziert.
1
TACCR1=alpha_table[adc_get_value(ALPHA)][0];
2
TACCR0=alpha_table[adc_get_value(ALPHA)][0]+500;
Mit leerer Endlosschleife in der main() ist aber immernoch ein leichtes
Zucken zu erkennen. Ich befürchte fast, dass das am "Oszi" (Triggerung)
bzw. an den Messleitungen liegen könnte.
>> Hat Deine CPU einen NVIC?>> Ich kenne die Abkürzung "NVIC" nicht, gibts dafür einen anderen Begriff?
"Nested [vectored] interrupt controller"
> Das man eine Menüsteuerung entprellen muss wusste ich nicht
Die Frage ist, ob irgendwelche zusätzlichen Interrupts entstehen.
>> Wie sind die "delays" in main() implementiert? Zeige mal bitte den>> Quelltext der delay-Funktionen.>> Da gibt es keinen Quellcode.
Dann halt Assembler ...
> An dem µC ist ein 8MHz-Quarz
Dann nimm' mal die 8 MHz und teste nochmals. Da ist schon manches
Problem "verschwunden".
Ich tippe weiterhin darauf, dass die Zeit in den ISRs zu lang ist, und
evtl. Interrupts verloren gehen.
> Ich habe jetzt mal etwas anderes probiert. Indem ich die Berechnung aus> der P2-ISR rausgenommen habe und statt dessen ein array erzeugt mit> [1024][2] Dimensionen.
Aha. Soso. Oh, Du wirst noch viel ändern müssen ...
Testweise float entfernen, und ADC mit dummy-Werte (= Konstante).
Wenn es dann im Oszi nicht mehr "zuckt", liegt's vermutlich an der
Rechen-Last (sofern alle busy-delays daraus entfernt wurden). Ansonsten
vielleicht am Messaufbau.
Roland H. schrieb:>>> Hat Deine CPU einen NVIC?>>>> Ich kenne die Abkürzung "NVIC" nicht, gibts dafür einen anderen Begriff?>> "Nested [vectored] interrupt controller"
Nein so langsame µC wie der MSP430 haben keinen NIC, die flotten ARMs
haben welche laut google-Suche.
>> Da gibt es keinen Quellcode.>> Dann halt Assembler ...
Texas Instruments MSP430 Optimizing C/C++ Compiler v 3.3 User's Guide
http://www.ti.com/lit/ug/slau132e/slau132e.pdf
S.115
"6.7.2 The __delay_cycle Intrinsic
The __delay_cycles intrinsic inserts code to consume precisely the
number of specified cycles with no side effects. The number of cycles
delayed must be a compile-time constant."
Mehr kenne ich auch nicht, aber es funktioniert.
>> An dem µC ist ein 8MHz-Quarz>> Dann nimm' mal die 8 MHz und teste nochmals. Da ist schon manches> Problem "verschwunden".
Das dauert erstmal, dafür muss ich das Array überarbeiten.
>> Ich habe jetzt mal etwas anderes probiert. Indem ich die Berechnung aus>> der P2-ISR rausgenommen habe und statt dessen ein array erzeugt mit>> [1024][2] Dimensionen.>> Aha. Soso. Oh, Du wirst noch viel ändern müssen ...
Den Speicher voller riesiger Arrays zu laden, ist aber auch nicht die
Lösung, wenn es ein bis zwei Berechnungen auch tun.
Norman Freitag schrieb:> Den Speicher voller riesiger Arrays zu laden, ist aber auch nicht die> Lösung, wenn es ein bis zwei Berechnungen auch tun.
Zwischen Wunsch und Wirklichkeit zu unterscheiden, bedeutet Wissen!
Wie schon mehrfach angedeutet, ist der Takt zu gering, um die
rechenintesiven Ausdrücke zu verarbeiten. Also hast du die Wahl, einen
anderen Algorithmus, einen höheren Takt, oder anderen µC zu wählen.
Ich habe die Probleme weitgehend gelöst. Das Zittern der Zündsignale ist
auf ein Minimum reduziert. Das Minimum meist +/- 8-12µs mit ein paar
seltenen Ausreißern von bis zu 67µs.
Das größte Problem waren in der Hauptschleife, das gegenseitige
Aussperre der LCD-Signale und der Thyristor-Zündsignale auf dem Port4,
da ja, wie oben beschrieben Zündsignale auf dem Low-Nibble und LCD auf
dem High-Nibble liegen. Wenn nun ein Interrupt an einer sehr ungünstigen
Stelle der LCD-Routine ausgelöst wurde, dann wurde auf Port4 letzlich
etwas Falsches ausgegeben.
Eine andere Ursache für Störungen der beiden Timer-ISR ist bedingt durch
die Abfrage des A/D-Wandlers. Hier kam es in regelmäßigen Abständen zum
aussetzen von ganzen Zündsignalen, obwohl der A/W-Wandler keinen
Intterupt bemüht.
Meine Lösung:
P2.5 detektiert Flankenwechsel ==> P2-ISR ==> P2IES toggle BIT5
==> frage A/W-Wandler ab ==> berechne Zeitverzögerung
==> füttere CCR1 und CCR0 ==> CCR1 erreicht
==> Timer_x1-ISR Zündimpulse auf ein ==> Timer_x0-ISR Zündimpulse aus
==> zurück zum Hauptprogramm (Anzeigewerte berechnen ==> LCD
beschreiben)
Wenn ich den MCLK auf 2MHz setze, kann ich bei 500µs Zündimpulsbreite
(CCR0-CCR1) im Intervall von alpha=9°-170° sauber arbeiten (bei
MCLK=1MHz sind es nur alpha=18-170°). Das genügt mir so.
Theoretisch sind bei MCLK=16MHz und kürzeren Zündimpulsen (300µs)
wahrscheinlich sogar alpha=1°-174° möglich.