PWM-Werte messen

OP #1105290
Servus,

ich muss 8 Kanaele von PWMs mit einem ATmega128 messen, wobei die 
PWM-Periode 20ms ist und der PWM-Schritt 100us betraegt.

Eine Timer1-ISR gibt die 100us-Zeitbasis und aktualisiert die 
Eingangswerte.
Die Methode pwm_processing() macht die Verarbeitungen und aktualisiert 
das Zielarray pwm_input[].
Eine Anstiegsflanke deutet auf den Anfang eines PWM-Zykluses.

Die Frage ist, ob es moeglich ist, diesen Vorgang
1
if (tmp != 0){} else {}
zu optimieren, damit es schneller laeuft?
Ist es besser mit
1
if ((tmp & 0x01) != 0)
statt
1
if ((tmp & 0x01) == 0x01)
?

Code unten:
1
ISR(TIMER1_COMPA_vect) {
2
  // andere Bearbeitungen  
3
  pwm_value = PWM_INPUT_PIN;
4
}
5

6
void pwm_processing(void)
7
{
8
  uint8_t tmp;
9
  uint8_t pwm_counter[8];
10
  tmp = (~pwm_value_old & pwm_value);
11
  
12
  if (tmp != 0)  // Anstiegsflanken ankommen
13
  {
14
    if ((tmp & 0x01) == 0x01)
15
    {
16
      pwm_input[0] = pwm_counter[0];  // entsprechende Messwerte gueltig machen
17
      pwm_counter[0] = 0;
18
    }
19
    if ((tmp & 0x02) == 0x02)
20
    {
21
      pwm_input[1] = pwm_counter[1];
22
      pwm_counter[1] = 0;
23
    }
24
    if ((tmp & 0x04) == 0x04)
25
    {
26
      pwm_input[2] = pwm_counter[2];
27
      pwm_counter[2] = 0;
28
    }
29
    if ((tmp & 0x08) == 0x08)
30
    {
31
      pwm_input[3] = pwm_counter[3];
32
      pwm_counter[3] = 0;
33
    }
34
    if ((tmp & 0x10) == 0x10)
35
    {
36
      pwm_input[4] = pwm_counter[4];
37
      pwm_counter[4] = 0;
38
    }
39
    if ((tmp & 0x20) == 0x20)
40
    {
41
      pwm_input[5] = pwm_counter[5];
42
      pwm_counter[5] = 0;
43
    }
44
    if ((tmp & 0x40) == 0x40)
45
    {
46
      pwm_input[6] = pwm_counter[6];
47
      pwm_counter[6] = 0;
48
    }
49
    if ((tmp & 0x80) == 0x80)
50
    {
51
      pwm_input[7] = pwm_counter[7];
52
      pwm_counter[7] = 0;
53
    }
54
  }
55
  else
56
  {
57
    if ((pwm_value & 0x01) == 0x01)
58
      pwm_counter[0]++;  // Zaehler erhoehen wenn Eingang HIGH ist
59
    if ((pwm_value & 0x02) == 0x02)
60
      pwm_counter[1]++;
61
    if ((pwm_value & 0x04) == 0x04)
62
      pwm_counter[2]++;
63
    if ((pwm_value & 0x08) == 0x08)
64
      pwm_counter[3]++;
65
    if ((pwm_value & 0x10) == 0x10)
66
      pwm_counter[4]++;
67
    if ((pwm_value & 0x20) == 0x20)
68
      pwm_counter[5]++;
69
    if ((pwm_value & 0x40) == 0x40)
70
      pwm_counter[6]++;
71
    if ((pwm_value & 0x80) == 0x80)
72
      pwm_counter[7]++;
73
  }
74
  pwm_value_old = pwm_value;  // Messwerte als Referenz fuer naechste Bearbeitung
75
}
Besten Dank im Vorraus
Senmeis
Gast #1105337
>wobei die PWM-Periode 20ms ist und der PWM-Schritt 100us betraegt.

Klingt nach Modellbau.

Die Impule werden danei immer nacheinander übertragen.
Man muß also nur gucken, ob sich der aktuelle Zustand zum vorherigen 
geändert hat.
Hat sich nichts geändert, und ist der entsprechende Eingang noch High, 
dann zählt man die zugehörige Variable hoch.
Ist der Eingang auf low gegangen, dann muß man das Ergebnis 
weiterverarbeiten.

Wenn es wirklich um Modellbau-Impulse geht, dann sind deine 
100µs-Abtastrate etwas sehr grob. Du kämst auf Werte zwischen 10 und 
20...
Gast #1105340
Also,

erstmal ist
1
(value & maske) == maske
schon ein Ausdruck zuviel. Denn value & maske kann nur entweder 0 oder 
maske sein, und dann kann man auch nur auf 0 bzw != 0 testen.

Dann sollte man noch wissen, dass if in c implizit auf != 0 testet, d.h.
man schreibt in einem solchen Fall
1
 if (value & maske) {

Wenn ich Deinen Code richtig verstehe, dann möchtest Du die maximal 
verbrauchte Zeit minimieren, so dass der Code IMMER in weniger als 100us 
abläuft. Also ist solch ein Konstrukt wie if (tmp != 0) am Anfang, das 
nur zur Beschleunigung im nicht-worst-case Fall dient, überflüssig und 
verschlechtert nur den worst-case Fall.

Dann fällt auf, dass Du pwm_counter entweder als static deklarieren 
solltest oder außerhalb der Funktion. Sonst gehen die Werte darin 
verloren zwischen 2 Funktionsaufrufen.

Außerdem denke ich, das erste if() in Deinem Code kann eigentlich so 
nicht stimmen, denn Du möchtest bestimmt den else- Zweig für jedes Bit 
durchlaufen, wo keine Flanke gekommen ist.

Ich versuche jetzt mal einen anderen Entwurf:
1
if (tmp & 0x01) {
2
  pwm_input[0] = *pwm_counter[0];
3
  pwm_counter[0] = 0;
4
} else if (pwm_value & 0x01) {
5
  pwm_counter[0]++;
6
}
Und das einfach 8 mal hintereinander.
Weitere Optimierungen sind sehr davon abhängig, welchen Assemblercode 
Dein Compiler aus diesem Stück macht!
OP #1107794
vielen Dank fuer die Antworten.

Eines habe ich fast vergessen. Die Eingaenge duerfen nur gemessen werden 
wenn richtige Zeitpunkte
ankommen.
Also:
1
ISR(TIMER1_COMPA_vect) {
2
// andere Bearbeitungen  
3
  pwm_value = PWM_INPUT_PIN;
4
  pwm_read_enable = 1;
5
}
6

7
void pwm_processing(void){
8
  uint8_t tmp;
9
  uint8_t pwm_counter[8];
10
  if (pwm_read_enable == 1)
11
  {
12
    pwm_read_enable = 0;
13
    tmp = (~pwm_value_old & pwm_value);
14
  
15
    if (tmp & 0x01) 
16
    {
17
        pwm_input[0] = pwm_counter[0];
18
        pwm_counter[0] = 0;
19
    } 
20
    else if (pwm_value & 0x01) 
21
    {
22
        pwm_counter[0]++;
23
    }
24
    ...
25
  }
26
}

Gruss
Senmeis

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.