PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 255 PWM´s hintereinander ==>> LÄUFT!!



The Man
12.01.2009, 21:16
Hallo da,

Ich habe hier eine Schaltung, mit einem Mega 8, an dem RGB LED´s über die PINs B1, B2 und B3 verteilt sind. Schalte ich PB0 HIGH, werden die anderen übersteuert und bleiben LOW.

Ich habe in Assembler schon etwas programmiert, wo ich die beiden Standalone PWM A und B von Timer1 und den einen PWM von Timer2 alle in 8 BIT Auflösung laufen lasse. Vom Timer2 wird ein Overflowinterrupt ausgeführt. In der ISR zählt eine 8 Bit variable hoch. Diese wird mit einem Dimmwert verglichen. Ist sie mind. gleich, geht PB0 HIGH, sonst LOW.

Im Endeffekt habe ich also 255x8Bit PWM hintereinander. Macht dann 16 Bit.

Jetzt versuche ich das in C zu programmieren.
-ADC einlesen geht (8Bit, weil left adjusted) (getestet)
-die PWM´s laufen.(getestet)

Was nicht geht ist die Schachtelung. Die Lampen blinken in einer konstanten Geschwindigkeit. Wie gesagt, hat das in ASM schon geklappt.

Hat jemans eine Idee?


#include <avr/io.h>
#include <avr/interrupt.h>

int zyklus;
int helligkeit;


SIGNAL (SIG_OVERFLOW2){
zyklus++;
if (zyklus >= helligkeit) PORTB |= (1<<PB0);
else PORTB &= (0<<PB0);
}

void init(){
DDRB = 0b00001111;

TIMSK = 0b01000000;

TCNT1 = 254;
OCR1A = 43;
OCR1B = 90;
ICR1 = 255;

OCR2 = 139;
TCCR1A |= (1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11);
TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
TCCR2 |= (1<<WGM20)|(1<<COM21)|(1<<COM20)|(1<<WGM21)|(1<<CS20);

zyklus = 0;

ADMUX = 0b00100000;
ADCSRA = 0b11110101;

sei();
}


int main(void)
{
int schleife;
init();
main2:

for (schleife=0;schleife==250;schleife++){

}

helligkeit = ADCH;
goto main2;
return 0;
}


mfg,
The Man

Besserwessi
12.01.2009, 22:29
Die Variablen in der ISR muß man als Volatile deklarieren, sonst werden die Werte am ende der ISR wahrscheinlich verworfen weil nie aus den Registern ins RAM kopiert.

Die Warteschleifen werden auch nur ohne optimierung funktionieren. Mit optimierung werden die einfach weggelassen. Da gibt es in C extra delay routinen.
Endlossschleifen lacht man in C nicht mit GOTO, sondern mit while(1){...}.

The Man
13.01.2009, 07:04
Danke für die schnelle Antwort!
Gerade weil sie spät kam (23:29)^^

Läuft jetzt alles. Hab mir bei der Gelegenheit auch gleich angewöhnt, für Zahlen <= 255 CHAR zu nehmen.

Hier mal der Rumpf:


#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned char zyklus;
volatile unsigned char helligkeit; //stellt ein gemeinsames Vielfaches für die
//jew. Anteile da


SIGNAL (SIG_OVERFLOW2){
zyklus++;
if (zyklus >= helligkeit) PORTB |= (1<<PB0);
else PORTB &= (0<<PB0);

}

void init(){
DDRB = 0b00001111;

TIMSK = 0b01000000;

TCNT1 = 254;// vorladen von TCNT1, damit T1 und T2 nacher synchron laufen
ICR1 = 255;
//***********************
// Anteile der Farben
OCR1A = 255;
OCR1B = 255;
OCR2 = 255;
//************************


TCCR1A |= (1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11);
TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
TCCR2 |= (1<<WGM20)|(1<<COM21)|(1<<COM20)|(1<<WGM21)|(1<<CS20);


sei();
}


int main(void)
{
int schleife;
init();
main2:

for (schleife=0;schleife==250;schleife++){

}

goto main2;
return 0;
}

sternst
13.01.2009, 09:08
Die Variablen in der ISR muß man als Volatile deklarieren, sonst werden die Werte am ende der ISR wahrscheinlich verworfen weil nie aus den Registern ins RAM kopiert.

Sorry, aber das ist Blödsinn.
Das sind globale Variablen und werden daher selbstverständlich spätestens am Ende der Funktion ins RAM zurückgeschrieben.

sternst
13.01.2009, 09:15
for (schleife=0;schleife==250;schleife++){
Diese Schleife wird genau 0-mal durchlaufen.
Du meintest wohl eher "<=".

The Man
13.01.2009, 11:55
ach ja stimmt. In C wird etwas gemacht solange eine Bedingung 1 ist und nicht bis eine Bedingung 1 ist...

thewulf00
13.01.2009, 12:01
Die Variablen in der ISR muß man als Volatile deklarieren, sonst werden die Werte am ende der ISR wahrscheinlich verworfen weil nie aus den Registern ins RAM kopiert.

Sorry, aber das ist Blödsinn.
Das sind globale Variablen und werden daher selbstverständlich spätestens am Ende der Funktion ins RAM zurückgeschrieben.

Er hats komisch beschrieben, aber der Grundgedanke ist korrekt.
Wird eine Variable von zwei verschiedenen Stellen (ISR und Hauptprogramm) benutzt, so muss sie volatile sein, sonst wird sie beim Benutzen der Optimierung wegen nicht erneut aus dem RAM ausgelesen (da sie sich in dem aktuellen Ablaufstrang ja nicht geändert haben kann).

sternst
13.01.2009, 12:30
ach ja stimmt. In C wird etwas gemacht solange eine Bedingung 1 ist und nicht bis eine Bedingung 1 ist...
Auch nicht 100%ig richtig. ;-)
Solange die Bedingung wahr ist, und "wahr" ist nicht gleich 1 sondern ungleich 0. 42 ist auch "wahr".

sternst
13.01.2009, 12:46
Er hats komisch beschrieben, aber der Grundgedanke ist korrekt.
Der Grundgedanke, warum hier volatile zu verwenden ist, ist weder "komisch" beschrieben, noch korrekt, sondern einfach nur falsch.


Wird eine Variable von zwei verschiedenen Stellen (ISR und Hauptprogramm) benutzt, so muss sie volatile sein,
Auch das ist eigentlich eine falsche Verallgemeinerung. Es ist zwar sehr oft so, aber nicht immer. Im konkreten Fall ist das volatile bei zyklus z.B. überflüssig.


sonst wird sie beim Benutzen der Optimierung wegen nicht erneut aus dem RAM ausgelesen
Nur dass das Lesen im konkreten Fall gar nicht der Knackpunkt ist, sondern das Schreiben der Variable helligkeit ins RAM in der main-Schleife.

thewulf00
14.01.2009, 07:32
Er hats komisch beschrieben, aber der Grundgedanke ist korrekt.
Der Grundgedanke, warum hier volatile zu verwenden ist, ist weder "komisch" beschrieben, noch korrekt, sondern einfach nur falsch.
Es ist komisch beschrieben. Aus digitaler Sicht (es gibt nur richtig und falsch) ist Deine Antwort korrekt. Aber es gibt auch Grauzonen. Man muss einfach hinter die Worte blicken, und da ist der Gedankengang schon in Ordnung gewesen.
(z.B. Frauen sprechen gern anders, als sie es meinen :-b )




Wird eine Variable von zwei verschiedenen Stellen (ISR und Hauptprogramm) benutzt, so muss sie volatile sein,
Auch das ist eigentlich eine falsche Verallgemeinerung. Es ist zwar sehr oft so, aber nicht immer. Im konkreten Fall ist das volatile bei zyklus z.B. überflüssig.
Du hast völlig recht. Aber in den meisten Fällen verursacht - vor allem bei Anfängern - ein fehlendes volatile das Problem. Besserwessi wollte sicher nur helfen. Und nur auf den Sonderfällen rumzureiten, damit eine Aussage nicht als allgemeingültig stehen gelassen werden kann, ist gemein.




sonst wird sie beim Benutzen der Optimierung wegen nicht erneut aus dem RAM ausgelesen
Nur dass das Lesen im konkreten Fall gar nicht der Knackpunkt ist, sondern das Schreiben der Variable helligkeit ins RAM in der main-Schleife.
Da hast Du natürlich recht, mein Fehler.

Nichtsdestotrotz kann ich mich mit der Aussage, dass es "einfach nur falsch" sei, nicht anfreunden. Die Ausdrucksweise ist sicher nicht wissenschaftlich korrekt, aber sie passt hier sehr wohl.

sternst
14.01.2009, 09:57
Nichtsdestotrotz kann ich mich mit der Aussage, dass es "einfach nur falsch" sei, nicht anfreunden. Die Ausdrucksweise ist sicher nicht wissenschaftlich korrekt, aber sie passt hier sehr wohl.
Bitte lese dir meine Antwort auf den Post von Besserwessi nochmal durch.
Es geht nicht darum, dass volatile zu verwenden ist, sondern um das warum.

sonst werden die Werte am ende der ISR wahrscheinlich verworfen weil nie aus den Registern ins RAM kopiert.
Da steht, dass es möglich ist, dass eine veränderte globale Variable in einer Funktion nie (auch nicht am Ende) ins RAM zurück geschrieben wird, und daher die in der Funktion gemachte Veränderung verloren ist. Das ist so grundlegend falsch, dass ich mich beim besten Willen nicht mit "komisch beschrieben" oder "im Grundgedanke richtig" anfreunden kann.



Und nur auf den Sonderfällen rumzureiten, damit eine Aussage nicht als allgemeingültig stehen gelassen werden kann, ist gemein.
Ja, so bin ich, ein fieser kleiner Besserwisser. ;-)
Natürlich kann man die Verallgemeinerung so stehen lassen, schließlich ist ein volatile zuviel bei weitem nicht so problematisch, wie ein volatile zuwenig. Ich wollte nur mal darauf hinweisen, dass es sich um eine vereinfachende Verallgemeinerung handelt, und nicht um eine unumstößliche Grundregel.


Besserwessi wollte sicher nur helfen.
Er hat dem OP ja auch geholfen.
Nur wenn die Hilfe auch grundlegend falsche Aussagen beinhaltet, kann man die nicht einfach so stehen lassen, insbesondere wenn der Post hilfreich war. Beim Fragenden würde sich sonst festsetzen: das mit dem volatile hat geholfen, also stimmt wohl auch die Begründung.