Hallo,
XC8 compiler PIC18F46Q71.
Ich steuere ein MOSFET jede 10 ms im Timer Interrupt an.
Es kommt zeitweise zur falschen Ansteuerung im mode=2 (Zeile mit
//Fehler).
Gemessen mit Oszilloskop.
Habe dann den code geändert (2 Zeilen ohne Fehler)
Nach der Änderung keine Fehler mehr.
Aber ich verstehe den Grund nicht.
Oder kann es sein, dass in dieser Zeile
mode = slave_in[3] & 0x07;
der Interrupt zuschlägt und dann die Variable mode einen falschen Wert
bekommt.
1 | volatile unsigned char mode; // Modus Ansteuerung MOSFET
| 2 |
| 3 | // Tabelle MOSFET Taktung------------------
| 4 | const char signal[8][12] = {
| 5 | {0,0,0,0,0,0,0,0,0,0,0,0}, // Mode 0 = Aus
| 6 | {1,1,1,1,1,1,1,1,1,1,1,1}, // Mode 1 = 200% U-Nenn 2xÜbererregung
| 7 | {1,0,1,0,1,0,1,0,1,0,1,0}, // Mode 2 = 100% U-Nenn Halbwelle
| 8 | {1,0,0,1,0,0,1,0,0,1,0,0}, // Mode 3 = 75% U-Nenn
| 9 | {1,0,0,0,1,0,0,0,1,0,0,0}, // Mode 4 = 50% U-Nenn
| 10 | {1,0,0,0,0,0,1,0,0,0,0,0}, // Mode 5 = 34% U-Nenn
| 11 | {1,0,0,0,0,0,0,0,0,0,0,0}, // Mode 6 = 17% U-Nenn
| 12 | {1,1,0,0,1,1,0,0,1,1,0,0} // Mode 7 = 100% U-Nenn Vollwelle
| 13 | };
| 14 |
| 15 | int main(void)
| 16 | {
| 17 |
| 18 | while (1)
| 19 | {
| 20 | mode = slave_in[3] & 0x07; // Neuen Wert vom Master
| 21 |
| 22 | // BYP_SCO1_LAT = (mode>1); // Fehler
| 23 | if (mode>1) BYP_SCO1_LAT =1; // kein Fehler
| 24 | else BYP_SCO1_LAT =0;
| 25 | }
| 26 | }
| 27 |
| 28 |
| 29 | // Im Timer Interrupt jede 10 ms:
| 30 |
| 31 | // Nächsten Wert für Takt IGBT aus Array holen
| 32 | MCU_SW1_LAT = signal[mode][pulse_pos];
| 33 | pulse_pos++; // Nächster Wert aus Array
| 34 | if (pulse_pos == 12) pulse_pos = 0; // Array Ende, dann von Anfang
|
Nun das eine ist ein Read-Modify-Write auf BYP_SCO1_LAT (nicht atomar),
Das andere sind 2 Zuweisungen ohne vorheriges Lesen (atomar).
RMW-Zugriffe auf IO-Bits können Seiteneffekte auf andere Bits im selben
Byteregister haben.
Beitrag #7897433 wurde von einem Moderator gelöscht.
Peter D. schrieb:
> auf andere Bits im selben
> Byteregister haben.
Könnte sein. Beide liegen im selben Port:
Dirk F. schrieb:
> Ich steuere ein MOSFET jede 10 ms im Timer Interrupt an.
> Es kommt zeitweise zur falschen Ansteuerung im mode=2 (Zeile mit
> //Fehler).
> Gemessen mit Oszilloskop.
Wie sieht denn der Fehler aus?
> Habe dann den code geändert (2 Zeilen ohne Fehler)
Syntaktisch korrekt, aber die Formatierung sollte man nicht so machen.
Das sit schlecht lesbar und damit fehleranfällig. Wenn, dann so.
1 | if (mode>1) BYP_SCO1_LAT =1; else BYP_SCO1_LAT =0;
|
oder so
1 | if (mode>1) {
| 2 | BYP_SCO1_LAT =1;
| 3 | } else {
| 4 | BYP_SCO1_LAT =0;
| 5 | }
|
> Nach der Änderung keine Fehler mehr.
> Aber ich verstehe den Grund nicht.
Ich vermute, daß die Sequenz komplett atomar sein muss, damit sich deine
Logik nicht verklemmt. Denn mode wird auch in deiner ISR verwendet. Eher
so.
1 | cli(); // Interrupts sperren, muss an PIC angepasst werden
| 2 | mode = slave_in[3] & 0x07; // Neuen Wert vom Master
| 3 |
| 4 | // BYP_SCO1_LAT = (mode>1); // Fehler
| 5 | if (mode>1) BYP_SCO1_LAT =1; // kein Fehler
| 6 | else BYP_SCO1_LAT =0;
| 7 | sei(); // Interrupts freigeben, muss an PIC angepasst werden
|
Siehe Interrupt.
Dirk F. schrieb:
>> auf andere Bits im selben
>> Byteregister haben.
>
> Könnte sein. Beide liegen im selben Port:
Da hast du dein Problem.
https://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff
Falk B. schrieb:
> Wie sieht denn der Fehler aus?
Normal wird jede zweite Halbwelle eingeschaltet.
Im Fehler fehlt manchmal eine Halbwelle oder es werden zwei
Halbwellen ohne Pause nacheinander ausgegeben.
Hast du schon versucht den mode Update auf den Sequenz Start zu
Synchronisieren? (Die read-modify-write Probleme sind historisch, als
die PICs zum lesen und schreiben nur ein Port Register hatten, und der
externe Portzustand beim RmW in das Latch leckte. Neuere Modelle haben
separate port und latch Register)
Johann K. schrieb:
> Neuere Modelle haben
> separate port und latch Register)
Der PIC18F46Q71 ist ein neues Modell.
Es geht hier aber nur ums schreiben ins LATCH.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|