www.mikrocontroller.net

Forum: Compiler & IDEs Sehr langsame Ausführung des Programms


Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define F_CPU 8000000L
 
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#define R_LED     PD2
#define G_LED     PD3
#define B_LED     PD4
#define LED_PORT   PORTD
#define PORT_DIR  DDRD


////////////////////////////////////////////////////////////////////////////////////////////////////

uint8_t    r, g, b;
uint16_t  phase;

////////////////////////////////////////////////////////////////////////////////////////////////////

void set_rgb(uint8_t r_new, uint8_t g_new, uint8_t b_new){
  
  r = r_new;
  g = g_new;
  b = b_new;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int main(void){
  
  phase = 0;

  PORT_DIR |= ((1<<R_LED) | (1<<G_LED) | (1<<B_LED));

  set_rgb(50, 50, 50);

  while(1){
    
    if(phase == r) LED_PORT &= ~(1<<R_LED);
    if(phase == g) LED_PORT &= ~(1<<G_LED);
    if(phase == b) LED_PORT &= ~(1<<B_LED);

    phase++;

    if(phase == 0) LED_PORT |= ((1<<R_LED) | (1<<G_LED) | (1<<B_LED));
  }

  return 0;
}

Der Quellcode ist sehr einfach und bedarf keiner Kommentare. Bei der 
Ausführung auf einem ATmega8 @ 8Mhz blinkt die LED ungefähr in einem 1/2 
Sekunden Takt. Daraus folgere ich, dass die while-Schleife wohl nur 
zweimal in der Sekunde durchläuft. Kann das sein?

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das kommt hin.
Vier Vergleiche a vier Takte, ein inkrementieren 2 Takte, 2 Takte für 
die Schleife. Macht im besten Falle 20 Takte, die 2^16 Mal durchlaufen 
werden - macht 1.3 Millionen, also nicht sehr weit von deinen 
geschätzten 4 Millionen entfernt.

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

Bewertung
0 lesenswert
nicht lesenswert
Maxim wrote:

> Sekunden Takt. Daraus folgere ich, dass die while-Schleife wohl nur
> zweimal in der Sekunde durchläuft.

Die while Schleife wird schon öfter als 2 mal in der Sekunde
durchlaufen. Aber phase muss jedesmal bis 65535 hochgezählt werden,
bis dann durch den Überlauf wieder 0 in phase steht. Wenn das
2 mal pro Sekunde passiert, ist die while Schleife also mehr
in der Größenordnung von 130000 mal durchlaufen worden.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die while Schleife wird schon öfter als 2 mal in der Sekunde
>durchlaufen. Aber phase muss jedesmal bis 65535 hochgezählt werden,
>bis dann durch den Überlauf wieder 0 in phase steht. Wenn das
>2 mal pro Sekunde passiert, ist die while Schleife also mehr
>in der Größenordnung von 130000 mal durchlaufen worden.

Ach stimmt! War gestern zu müde um das zu sehen. Es gibt also keinen Weg 
die PWM-Frequenz zu steigern? Wäre vielleicht ein Timer besser dafür 
geeignet?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim wrote:
> Ach stimmt! War gestern zu müde um das zu sehen. Es gibt also keinen Weg
> die PWM-Frequenz zu steigern? Wäre vielleicht ein Timer besser dafür
> geeignet?
Gibt es einen triftigen Grund für eine 16-Bit-Zählvariable? Entweder ne 
8-Bit-Variable nehmen (Faktor 256 in der Geschwindigkeit) oder sozusagen 
ein "CTC" (Clear Timer on Compare Match) in Software machen, also bei 
Erreichen eines bestimmten Zählwertes den Zähler zurücksetzen. Ich denke 
mal, eine Auflösung von 65536 Schritten ist i.d.R. eh nicht wirklich 
sinnvoll.

BTW:
Ich sehe grad, dass r, g, und b sowieso nur 8 Bit breit sind. Was soll 
dann überhaupt das mit der 16-Bit-Zählvariable? phase sollte 
sinnigerweise auch uint8_t sein, und nicht uint16_t.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Gibt es einen triftigen Grund für eine 16-Bit-Zählvariable? Entweder ne
>8-Bit-Variable nehmen (Faktor 256 in der Geschwindigkeit) oder sozusagen
>ein "CTC" (Clear Timer on Compare Match) in Software machen, also bei
>Erreichen eines bestimmten Zählwertes den Zähler zurücksetzen. Ich denke
>mal, eine Auflösung von 65536 Schritten ist i.d.R. eh nicht wirklich
>sinnvoll.

>BTW:
>Ich sehe grad, dass r, g, und b sowieso nur 8 Bit breit sind. Was soll
>dann überhaupt das mit der 16-Bit-Zählvariable? phase sollte
>sinnigerweise auch uint8_t sein, und nicht uint16_t.

Danke für deine Vorschläge. Die 16-Bit-Auflösung ist nicht sinnlos 
gewählt. Ich braue sie um später ein exponentielles Anwachsen des 
Stromes durch einen linearen Faktor im Programm zu realisieren. Die 
8-Bit Variablen r, g und b werden dann durch eine Tabelle auf einen 
16-bittigen Wert umgerechnet, welcher mit dem Zähler vergliechen wird 
...

Zuerst muss das Programm aber wenigstens so funktionieren. Ich habe den 
Zähler auf Timer1 umgestellt. Die LED blinkt trotzdem etwa zweimal in 
der Sekunde auf. Es kann doch nicht sein, dass der ATMega8 bei 8Mhz 
keine dreifache software-PWM packt?!

Ach ja, CTC passt hier nicht, da ich ja drei unabhängige PWM-Signale 
brauche.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim wrote:
> Danke für deine Vorschläge. Die 16-Bit-Auflösung ist nicht sinnlos
> gewählt. Ich braue sie um später ein exponentielles Anwachsen des
> Stromes durch einen linearen Faktor im Programm zu realisieren. Die
> 8-Bit Variablen r, g und b werden dann durch eine Tabelle auf einen
> 16-bittigen Wert umgerechnet, welcher mit dem Zähler vergliechen wird
> ...
>
> Zuerst muss das Programm aber wenigstens so funktionieren. Ich habe den
> Zähler auf Timer1 umgestellt. Die LED blinkt trotzdem etwa zweimal in
> der Sekunde auf. Es kann doch nicht sein, dass der ATMega8 bei 8Mhz
> keine dreifache software-PWM packt?!
Doch, aber nicht mit der Auflösung. So ist das nunmal in einer 
Hochsprache. Und dann auch noch mit 16-Bit-Zahlenwerten, deren 
Verarbeitung sowieso deutlich länger dauert als bei 8-Bit-Werten.

> Ach ja, CTC passt hier nicht, da ich ja drei unabhängige PWM-Signale
> brauche.
Das eine hat mit dem anderen nichts zu tun. Ich sagte schließlich "in 
Software". Und da kannst Du auch einen Grenzwert setzen, ohne dafür 
andere Ressourcen einzubüßen. Das ist dann nur eine zusätzliche Abfrage, 
die zwar an sich den Durchlauf der Schleife ein wenig verlängert, aber 
insgesamt gesehen das ganze durchaus beschleunigen kann. Wenn Du 
anstelle von 16 Bit auf z.B. 11 Bit runtergehst, hast Du immerhin einen 
Faktor von ungefähr 32 in der Geschwindigkeit gewonnen. Du zählst dann 
eben nicht bis 65535, sondern nur bis 2047. Dementsprechend sind dann 
natürlich auch die Tabellenwerte anzupassen. Da die Größe der Tabelle im 
Mega8 sowieso ziemlich beschränkt sein dürfte (es sei denn, Du legst die 
Werte in einem externen Speicher ab), wirst Du um eine (lineare) 
Interpolation von Stützwerten eh nicht rumkommen. Und da macht es sicher 
keinen sichtbaren Unterschied, ob Du mit 16 oder mit 11 Bit arbeitest.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Maxim (Gast)

>Danke für deine Vorschläge. Die 16-Bit-Auflösung ist nicht sinnlos
>gewählt. Ich braue sie um später ein exponentielles Anwachsen des
>Stromes durch einen linearen Faktor im Programm zu realisieren. Die

AHA.

LED-Fading

>der Sekunde auf. Es kann doch nicht sein, dass der ATMega8 bei 8Mhz
>keine dreifache software-PWM packt?!

Schon mal nachgerechnet? Per 16 Bit Timer und 8 MHz Takt kommst du auf 
~123Hz PWM-Freqeunz. Pech nur dass deine Schleife "etwas" mehr als einen 
Takt braucht.

Ergo.
Mach eine 8-Bit PWM in Software, das reicht. Siehe Artikel.

>Ach ja, CTC passt hier nicht, da ich ja drei unabhängige PWM-Signale
>brauche.

Dann brauchst du einen festen Timer, der den PWM Takt in Software 
nachbildet.
100 Hz, 8 Bit -> 39us.

MfG
Falk

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, da wäre es fast besser, für jede Farbe einen ATTiny zu nehmen.

Ich probiere mal eine geringere Auflösung aus.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim wrote:

> Hm, da wäre es fast besser, für jede Farbe einen ATTiny zu nehmen.

Oder gleich einen AT90PWM3?

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die beste Lösung ist 12-Bit in Software. Die LED flackert fast gar nicht 
und die Auflösung ist ausreichend.

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.