Forum: Mikrocontroller und Digitale Elektronik SW-PWM: Kurzer heller Flash beim Uebergang von 0 auf 1


von Lara (Gast)


Lesenswert?

Hallo zusammen!
Ich moechte eine LED mittels SW-PWM (habe nicht genug Timer fuer nur
HW-PWMs dimmen. Mittels Tastern kann man den Vergleichswert
vergroessern oder verkleinern, was bedeutet, dass die LED heller oder
dunkler wird. Das ganze funktioniert auch recht schoen, nur ist das
Problem, dass die LED auch vollkommen ausgeschaltet werden soll. Wenn
der Vergleichswert Null wird setze ich SREG auf Null, (damit die
globalen Interrupts nicht aktiviert sind) und gleichzeitig den Pin auch
auf Null. Bei Erhoehen des Vergleichswertes mit Tastendruck aktivierte
ich die Interrupts wieder und die LED leuchtet schwach. Allerdings
kommt jedesmal erst ein kurzer heller Flash, als ob kurzzeitig das
Tastverhaeltinis bei 255 liegt.
Kann mir das vielleicht irgendjemand erklaeren? Bitte!
Zur Info: ich verwende einen ATMega128 mit einem externen 8MHz
Oszillor, Timer3 ist ein 16-Bit-Timer
Das Programm ist wie folgt:

/* SW-PWM mit Timer3: Ausgang C.4 */

#include<mega128.h>
#include<stdio.h>
#include<delay.h>

//---------------------------------------------------------------------- 
------------------------------------
interrupt [30] void t3_overflow(void)       //bei Überlauf von T3
Ausgang C.4  = high
{
 PORTC.4=1;
}
//---------------------------------------------------------------------- 
------------------------------------
interrupt [27] void t3_compareA(void)   //wenn Vergleichswert erreicht,
Ausgang, C.4 = low
{
 PORTC.4=0;
}

/*** HAUPTPROGRAMM
******************************************************************/

void main(void)
{

  unsigned char a=10;                                          //
Vergleichswerte zu Beginn

  DDRC=0x10;                                                    //C.4
als Ausgang definiert, Rest ist Eingang
  PORTF=0xFF;                                                   //PORTF
als Eingang, Pull-up aktiviert

  TCCR3B=0x01;
//Timer3 clk/1
  ETIMSK=0x14;
//Overflow und VergleichswertA T3
  SREG=0x80;
//globaler Interrupt enable

        while(1)
        {
                if ((PINF.5==0)&&(a<255))                        //
Vergleichswert +/-
                {
                        a++;
                        delay_ms(50);
                }
                if ((PINF.4==0)&&(a>=1))
                {
                        a--;
                        delay_ms(50);
                }
                OCR3AH=a;                                         //
Übergabe Vergleichswert an Vergleichsregister
                OCR3AL=a;

                else
            {
                    PORTC.4=0;
                    SREG=0x00;

                    if(PINF.5==0)
                    {
                            a++;
                            delay_ms(50);
                            SREG=0x80;
                         }
            }

        }
   }


Vielen herzlichen Dank!
LARA

von johnny.m (Gast)


Lesenswert?

> SREG=0x80;

Pfui, am SREG fummelt man nicht rum, jedenfalls nicht so! Mach es bitte
mit Inline-Assembler. Ich geh mal davon aus, dass das CodeVision ist
(solltest Du demnächst vielleicht direkt dazuschreiben, es gibt nämlich
ne ganze Reihe Compiler, die alle Unterschiede haben und nur bedingt bis
gar nicht portierbar sind), dann geht die Interrupt-Freigabe mit
#asm("sei")
und das globale Sperren mit
#asm("cli")

von Lara (Gast)


Lesenswert?

Ja, es ist CodeVision, sorry fuers nichts dazuschreiben. Aber woher hast
Du das denn gewußt?????
Warum darf ich nicht am SREG rumfummeln???
Kann daher der "Blitz" kommen?
Ich werd's gleich mal mit "sei" und "cli" versuchen.
Danke schoen
LARA

von Lara (Gast)


Lesenswert?

Ich hab's probiert, das "blitzt" immer noch!!! Heul
LARA

von Feadi (Gast)


Lesenswert?

Hi,

Ich denke Du musst beim Überlauf prüfen ob der Pin eingeschaltet werden
muss.

interrupt [30] void t3_overflow(void)       //bei Überlauf von T3
Ausgang C.4  = high
{
  if ( <einschaltbedingung> ) PORTC.4=1;
}

Gruß, Feadi

von Lara (Gast)


Lesenswert?

Guten Morgen Faedi!
Vielen Dank fuer Deinen Tipp! ich habe es folgendermaßen versucht.

nterrupt [30] void t3_overflow(void)       //bei Überlauf von T3
Ausgang C.4  = low
{
        if((OCR3AL!=1)&&(OCR3AH!=1))
        {
        PORTC.4=1;
        }
}
Das gute ist, dass es nicht mehr blitzt. Das bloede, dass die LED nun
erst wieder beim Vergleichswert 2 angeht (wir ja auch so in der
Einschaltbedingung gefordert)
Aber ich weiss nicht so recht, wie ich die Bedingung sonst gestalten
soll, wenn ichs mit
 if((OCR3AL!=0)&&(OCR3AH!=0))
klappts ja auch nicht, da der Interrupt ja gar nicht ausgelöst werden
kann...
Vielleicht hat ja jemand noch ne Idee???

Vielen Dank im voraus!
LARA

P.S.: Warum ist es denn nun eigentlich besser den Inline-Assembler
("sei" und "cli" zu verwenden anstatt SREG zu setzten?

von Lara (Gast)


Lesenswert?

Hallo nochmals!
Habe es nun hin bekommen!
Ich aktiviere und deaktiviere einfach den Interrupt nicht mehr, sondern
regel alles ueber eine Einschaltbedingung!
Vielen Dank Feadi fuer den Hinweis!

Aber den sei-/cli und SREG unterschied habe ich dennoch nicht
verstanden??
Scheonen Tag
LARA

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.