www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ISR Verständniss Problem


Autor: Michi M. (mutzmutz)
Datum:

Bewertung
0 lesenswert
nicht 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
if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
        pwm_cnt=0;
    else
        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 !
// Defines an den Controller und die Anwendung anpassen
 
#define F_CPU 8000000L                  // Systemtakt in Hz
#define F_PWM 100                       // PWM-Frequenz in Hz
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
#define PWM_PORT PORTD                  // Port für PWM
#define PWM_DDR DDRD                    // Datenrichtungsregister für PWM
 
// ab hier nichts ändern, wird alles berechnet
 
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
 
#if (T_PWM<(93+5))
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
#endif
 
// includes
 
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
// globale Variablen
 
volatile uint8_t pwm_setting[8]; 

// Timer 1 Output COMPARE A Interrupt
 
ISR(TIMER1_COMPA_vect) {
    static uint8_t pwm_cnt=0;
    uint8_t tmp=0;
 
    OCR1A += (uint16_t)T_PWM;
        
    if (pwm_setting[0] > pwm_cnt) tmp |= (1<<0);
    if (pwm_setting[1] > pwm_cnt) tmp |= (1<<1);
    if (pwm_setting[2] > pwm_cnt) tmp |= (1<<2);
    if (pwm_setting[3] > pwm_cnt) tmp |= (1<<3);
    if (pwm_setting[4] > pwm_cnt) tmp |= (1<<4);
    if (pwm_setting[5] > pwm_cnt) tmp |= (1<<5);
    if (pwm_setting[6] > pwm_cnt) tmp |= (1<<6);
    if (pwm_setting[7] > pwm_cnt) tmp |= (1<<7);
    PWM_PORT = tmp;                         // PWMs aktualisieren
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
        pwm_cnt=0;
    else
        pwm_cnt++;
}
int main(void) {
    // PWM einstellen
    PWM_DDR = 0xFF;         // Port als Ausgang
    // Timer 1 OCRA1, als variablem Timer nutzen
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten
    sei();                  // Interrupts gloabl einschalten
    return 0;
}

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michi M. (mutzmutz)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.