Forum: Compiler & IDEs SW PWM Geschwindigkeit


von Norbert S. (norton)


Lesenswert?

Hallo,

ich habe folgendes bei meiner SW PWM festgestellt:

wenn ich direkt über das Port (8 us) schalte funktioniert das wesentlich 
schneller als wenn ich das Port mittels übergabe über eine Variable (20 
us) schalte. Ich brauche die Geschwindigkeit und möchte aber trotzdem 
per Übergabe des Ports und Pins schalten.
Gibt es da ein Lösung für das Problem?
1
volatile  uint8_t     *m_x_toggle_port;
2
volatile  uint8_t     m_x_toggle_bit;
3
4
5
ISR( TIMER3_COMPB_vect )                      
6
{
7
// Auf Low setzen 
8
//  *m_x_toggle_port &= ~(1<<m_x_toggle_bit);   // langsam
9
  PORTE &= ~ (1<<MV1aufM);   //schneller
10
}
11
12
13
ISR( TIMER3_OVF_vect )
14
{
15
// Auf High setzen 
16
//  *m_x_toggle_port |= (1<<m_x_toggle_bit);   //langsam
17
  PORTE |= (1<<MV1aufM);    //schneller
18
}
19
20
.
21
.
22
.
23
24
m_x_toggle_port  = &PORTE;
25
m_x_toggle_bit  = MV1aufM;
26
27
.
28
.
29
.
30
31
start_timer();

Danke schon mal für eure Vorschläge.

von Stefan E. (sternst)


Lesenswert?

> (1<<m_x_toggle_bit)

Sowas ist langsam, weil der AVR keinen Befehl für mehrfaches Schieben 
hat. Der Compiler muss also eine Schleife erzeugen, in der 
m_x_toggle_bit mal um 1 geschoben wird. Speichere in m_x_toggle_bit 
nicht die Bitnummer, sondern gleich die fertige Maske:
1
m_x_toggle_bit  = (1<<MV1aufM);
2
3
*m_x_toggle_port &= ~m_x_toggle_bit;
4
5
*m_x_toggle_port |= m_x_toggle_bit;

Trotzdem erzeugt das natürlich deutlich mehr Code, z.B. muss ja auch 
erstmal der Inhalt der Variablen aus dem Speicher geholt werden. Und bei 
der ISR kommt noch hinzu, dass bei der Variablen-Variante zusätzliche 
Pushs und Pops erzeugt werden müssen.

1
ISR ( TIMER1_OVF_vect ) {
2
    *m_x_toggle_port &= ~m_x_toggle_bit;
3
}
->
1
  5e:  1f 92         push  r1
2
  60:  0f 92         push  r0
3
  62:  0f b6         in  r0, 0x3f  ; 63
4
  64:  0f 92         push  r0
5
  66:  11 24         eor  r1, r1
6
  68:  8f 93         push  r24
7
  6a:  9f 93         push  r25
8
  6c:  ef 93         push  r30
9
  6e:  ff 93         push  r31
10
  70:  e0 91 60 00   lds  r30, 0x0060
11
  74:  f0 91 61 00   lds  r31, 0x0061
12
  78:  90 81         ld  r25, Z
13
  7a:  80 91 62 00   lds  r24, 0x0062
14
  7e:  80 95         com  r24
15
  80:  89 23         and  r24, r25
16
  82:  80 83         st  Z, r24
17
  84:  ff 91         pop  r31
18
  86:  ef 91         pop  r30
19
  88:  9f 91         pop  r25
20
  8a:  8f 91         pop  r24
21
  8c:  0f 90         pop  r0
22
  8e:  0f be         out  0x3f, r0  ; 63
23
  90:  0f 90         pop  r0
24
  92:  1f 90         pop  r1
25
  94:  18 95         reti

1
ISR ( TIMER1_OVF_vect ) {
2
    PORTB &= ~(1<<MV1aufM);
3
}
->
1
  5e:  1f 92         push  r1
2
  60:  0f 92         push  r0
3
  62:  0f b6         in  r0, 0x3f  ; 63
4
  64:  0f 92         push  r0
5
  66:  11 24         eor  r1, r1
6
  68:  c5 98         cbi  0x18, 5  ; 24
7
  6a:  0f 90         pop  r0
8
  6c:  0f be         out  0x3f, r0  ; 63
9
  6e:  0f 90         pop  r0
10
  70:  1f 90         pop  r1
11
  72:  18 95         reti

Die 2. Variante ließe sich sogar noch deutlich reduzieren:
1
ISR ( TIMER1_OVF_vect, ISR_NAKED ) {
2
    PORTB &= ~ (1<<MV1aufM);
3
    reti();
4
}
->
1
  5e:  c5 98         cbi  0x18, 5  ; 24
2
  60:  18 95         reti


> möchte aber trotzdem per Übergabe des Ports und Pins schalten.

Wenn du erklärst warum, könnte dir vielleicht besser geholfen werden.

von Norbert S. (norton)


Lesenswert?

@Stefan Ernst
Danke erstmal, das macht die Sache schon mal klarer.

>> möchte aber trotzdem per Übergabe des Ports und Pins schalten.
>
> Wenn du erklärst warum, könnte dir vielleicht besser geholfen werden.

Ich muss 3 bistabile Magnetventile ansteuern wobei jedes mal das selbe 
passieren soll, jedoch an anderen Ports u. Pins.
Ich möchte eigentlich keinen Code doppelt haben. Also wenn ich eine 
Änderung vornehmen muss soll das gleich auf alle 3 Magnetventile wirken.
Ich denke im notfall werde ich mir Makros schreiben, dann habe ich die 
Wartbarkeit die ich haben will (Code nur einmal) und das mit der 
Geschwinidgkeit sollte ich dann auch hinbekommen.

Wenn es andere Lösungen gibt bin ich auf jeden Fall interessiert.

von Falk B. (falk)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.