Forum: Mikrocontroller und Digitale Elektronik ISR Verständniss Problem


von Michi M. (mutzmutz)


Lesenswert?

Hallo zusammen,
ich versuche mich momentan mit dem Soft PWM aus dem Tutorial.
Mein Ziel ist es, eine LED Matrix mit "beliebiger" grösse (vorerst mal 
8x8 Matrix) mit Soft PWM anzusteuern. Es sollen zufällige LEDs 
abwechslungsweise langsam ein- und ausgeschaltet werden.
Auf der Basis des Beispielprogrammes unten habe ich ein fading alles 
LEDs hinbekommen.
Jetzt wollte ich die dauer des fading sowie die maximale helligkeit 
variieren können. Ich habe einiges probiert und musste feststellen, dass 
ich wohl die ISR nicht ganz verstehe... kann mir jemand auf die sprünge 
helfen?
was ich auch nicht verstehe, warum in der ISR die variable pwm_cnt auf 0 
gesetzt wird, wenn (PWM_STEPS-1) erreicht wird
1
if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
2
        pwm_cnt=0;
3
    else
4
        pwm_cnt++;

was für ein sinn macht das ?
ebenfalls wird am anfang der ISR  pwm_cnt=0; gesetzt, somit wird doch 
obige abfrage immer auf das "else" ausweichen ?! Oder was verstehe ich 
hier nicht richtig ?

danke schon im voraus !
1
// Defines an den Controller und die Anwendung anpassen
2
 
3
#define F_CPU 8000000L                  // Systemtakt in Hz
4
#define F_PWM 100                       // PWM-Frequenz in Hz
5
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
6
#define PWM_PORT PORTD                  // Port für PWM
7
#define PWM_DDR DDRD                    // Datenrichtungsregister für PWM
8
 
9
// ab hier nichts ändern, wird alles berechnet
10
 
11
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
12
 
13
#if (T_PWM<(93+5))
14
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
15
#endif
16
 
17
// includes
18
 
19
#include <stdint.h>
20
#include <string.h>
21
#include <avr/io.h>
22
#include <avr/interrupt.h>
23
 
24
// globale Variablen
25
 
26
volatile uint8_t pwm_setting[8]; 
27
28
// Timer 1 Output COMPARE A Interrupt
29
 
30
ISR(TIMER1_COMPA_vect) {
31
    static uint8_t pwm_cnt=0;
32
    uint8_t tmp=0;
33
 
34
    OCR1A += (uint16_t)T_PWM;
35
        
36
    if (pwm_setting[0] > pwm_cnt) tmp |= (1<<0);
37
    if (pwm_setting[1] > pwm_cnt) tmp |= (1<<1);
38
    if (pwm_setting[2] > pwm_cnt) tmp |= (1<<2);
39
    if (pwm_setting[3] > pwm_cnt) tmp |= (1<<3);
40
    if (pwm_setting[4] > pwm_cnt) tmp |= (1<<4);
41
    if (pwm_setting[5] > pwm_cnt) tmp |= (1<<5);
42
    if (pwm_setting[6] > pwm_cnt) tmp |= (1<<6);
43
    if (pwm_setting[7] > pwm_cnt) tmp |= (1<<7);
44
    PWM_PORT = tmp;                         // PWMs aktualisieren
45
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
46
        pwm_cnt=0;
47
    else
48
        pwm_cnt++;
49
}
50
int main(void) {
51
    // PWM einstellen
52
    PWM_DDR = 0xFF;         // Port als Ausgang
53
    // Timer 1 OCRA1, als variablem Timer nutzen
54
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
55
    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten
56
    sei();                  // Interrupts gloabl einschalten
57
    return 0;
58
}

von Klaus W. (mfgkw)


Lesenswert?

Michi M. schrieb:
> was ich auch nicht verstehe, warum in der ISR die variable pwm_cnt auf 0
> gesetzt wird, wenn (PWM_STEPS-1) erreicht wird

Der Zähler soll immer von 0 bis zum Höchstwert laufen, und dann
wieder bei 0 anfangen etc..

Das wird genau damit erreicht, weil die ISR periodisch aufgerufen
wird.

von Klaus W. (mfgkw)


Lesenswert?

Michi M. schrieb:
> ebenfalls wird am anfang der ISR  pwm_cnt=0; gesetzt, somit wird doch
> obige abfrage immer auf das "else" ausweichen ?!

Das ist eine static-Variable.
Deren Initialisierung wird nur einmal bei Programmstart gemacht,
und nicht bei jedem Aufruf der Funktion bzw. ISR.

von Falk B. (falk)


Lesenswert?

@  Michi M. (mutzmutz)

>ich versuche mich momentan mit dem Soft PWM aus dem Tutorial.
>Mein Ziel ist es, eine LED Matrix mit "beliebiger" grösse (vorerst mal
>8x8 Matrix) mit Soft PWM anzusteuern. Es sollen zufällige LEDs
>abwechslungsweise langsam ein- und ausgeschaltet werden.

Tja, dann hast du wohl nicht genau gelesen. Soft-PWM geht nicht wirklich 
mit einer LED-Matrix zusammen, weil die PWM-Frequenz um den 
Multiplexfaktor höher sein muss. Bei dir also min. 8x100Hz. Das geht 
nicht mehr in Software, bzw. nur mit geringer Auflösung von vielleicht 6 
Bit oder so.

>was ich auch nicht verstehe, warum in der ISR die variable pwm_cnt auf 0
>gesetzt wird, wenn (PWM_STEPS-1) erreicht wird
>was für ein sinn macht das ?

Dann ist der PWM-Zyklus beendet und beginnt neu.

MfG
Falk

von Michi M. (mutzmutz)


Lesenswert?

ok, jetzt wird mir so einiges klar. hab nicht realisiert / gewusst dass 
die static variable nur bei start initiiert wird, danke.
wie kann ich denn die fading dauer verlängern, indem ich PWM_STEPS 
erhöhe ? habe ich versucht, doch klappt nicht ?!


@Falk
entweder verstehe ich dein argument nicht ganz, oder ich habe mich 
falsch ausgedrückt : auch wenn ich eine 8x8 matrix habe, will ich nicht 
jede LED gleichtzeitig faden, sondern beispielsweise immer nur etwa 4 
oder 5 gleichzeitig einmal aufleuchten und abklingen lassen, dann andere 
4 oder 5 leds... so geht das schon, oder ?

von Karl H. (kbuchegg)


Lesenswert?

Michi M. schrieb:
> ok, jetzt wird mir so einiges klar. hab nicht realisiert / gewusst dass
> die static variable nur bei start initiiert wird, danke.
> wie kann ich denn die fading dauer verlängern, indem ich PWM_STEPS
> erhöhe ? habe ich versucht, doch klappt nicht ?!

PWM_STEPS ist fix.
Im Beispiel bestimmen die pwm_setting Werte die Helligkeit der LED


> jede LED gleichtzeitig faden, sondern beispielsweise immer nur etwa 4
> oder 5 gleichzeitig einmal aufleuchten und abklingen lassen, dann andere
> 4 oder 5 leds... so geht das schon, oder ?

Nicht wirklich.
Du bist immer noch dem Gedanken verhaftet, jede LED irgendwie einzeln 
anzusteuern. Das funktioniert aber nicht.
Du hast zuallererst eine Matrix. Damit da jede Spalte (oder Zeile) der 
Matrix einmal abgearbeitet wird, braucht man Multiplex. Dabei spielt es 
keine Rolle ob in der jeweiligen Spalte (Zeile) auch tatsächlich eine 
LED brennt oder nicht. Das Multiplexing ist davon völlig unabhängig und 
läuft immer gleich durch.

Und über dieses Multiplexing muss man dann noch eine PWM drüberlegen.

Und dann wird es eng mit dem Timing.

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.