Seltsame Probleme die sporadisch auftreten

OP #7897428
Lesenswert?

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
Beitrag #7897433 wurde von einem Moderator gelöscht.
#7897460
Lesenswert?

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.

#7897741
Lesenswert?

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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren