www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Software PWM Problem


Autor: Johannes G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich bastel seit 2 Wochen mit AVRs...
Hardware PWM funktioniert super, aber ich wollte mal etwas mit Software 
PWM versuchen.. Hier der Code:
#define F_CPU 11059000L
#include <avr/io.h>
#include <avr/interrupt.h>



uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;

uint8_t counter = 0;

int main(void)
{
  red = 255;
  green = 128;
  blue = 10;

  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
  PORTB &= ~((1 << PB0) | (1 << PB1) | (1 << PB2));

  TCCR1B |= (1 << CS10);
  TIMSK |= (1 << TOIE1);
  
  sei();

  while(1)
  {
  }

  return 0;
}

ISR(TIMER1_OVF_vect)
{
  if(red >= counter)
  {
    PORTB |= (1 << PB0);
  }
  else
  {
    PORTB &= ~(1 << PB0);
  }

  if(green >= counter)
  {
    PORTB |= (1 << PB1);
  }
  else
  {
    PORTB &= ~(1 << PB1);
  }

  if(blue >= counter)
  {
    PORTB |= (1 << PB2);
  }
  else
  {
    PORTB &= ~(1 << PB2);
  }



  if(counter == 255)
  {
    counter = 0;
  }
  else
  {
    counter++;
  }
}

Soweit geht auch alles, aber das Programm läuft vieeeel zu langsam...
Die grüne LED leutet vllt 20sekunden, dann geht sie aus... Habt ihr eine 
idee was ich falsch mache?

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Johannes G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich am anfang probiert, damit lief es auch zu langsam.. 
Deswegen hab ich es ja selber geschrieben..

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du sicher, dass der Prozessor mit 11 MHz läuft?
Lass doch mal in der isr routine nur einen pin toggeln und mess die 
frequenz.
Dann kannst du überprüfen, was da faul ist...

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

Bewertung
0 lesenswert
nicht lesenswert
Du benutzt den 16 Bit Timer, den Timer 1

Das heist, der Timer muss jedesmal bis 65536 zählen,
bevor ein Überlauf eintritt.

Rechnen wir doch mal nach, wie lange das dauert.
Du betreibst den Prozessor mit 11 Mhz.
Da der Vorteiler des Timers 1 ist, läuft der auch mit 11 Mhz.
Das heist der Timer schafft in 1 Sekunde 11000000 / 65536 ganze
167 Overflows.

Bis dein Counter in der ISR also einmal bis 255 gezählt hat,
vergehen knapp 1.5 Sekunden. Für eine PWM also völlig unbrauchbar.

Nun braucht dein counter aber nicht 1.5 Sekunden für einmal
rundum sondern laut deiner Aussage ca. 20 Sekunden. Das kommt
ungefähr hin, wenn dein Prozessor nicht mit 11Mhz sondern mit
1 Mhz läuft.
Also prüfe mal ob dein Prozessor tatsächlich mit 11Mhz läuft,
oder ob er nicht doch immer noch auf internem RC-Oszillator
mit ca. 1Mhz läuft. Die Frage lautet also: Wie sind die Fuse
Bits gesetzt.

PS: Obige Rechnung hat auch gezeigt, dass ein Umchalten auf
11Mhz nicht reichen wird. Timer 1 braucht viel zu lange um einen
Overflow zu erreichen.

Autor: Johannes G. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
im anhang ist ein bild mit den fuse bits.
eigentlich sollte es so doch passen, oder?
Habt ihr eine Idee was da nicht passt?

Autor: Johannes G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nun weiß ich warum es nicht ging... Das Fuse Bit CKDIV8 ist bei dem 
Tiny2313 standartmäßig gesetzt...
Hier nun der Code der funktioniert:
#include <avr/io.h>
#include <avr/interrupt.h>


uint8_t red = 255;
uint8_t green = 128;
uint8_t blue = 10;

uint8_t counter = 0;

void pwm_init(void);

int main(void)
{
  pwm_init();
  
  sei();

  while(1)
  {
  }

  return 0;
}


void pwm_init(void)
{
  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
  PORTB &= ~((1 << PB0) | (1 << PB1) | (1 << PB2));

  TCCR1B |= (1 << WGM12) | (1 << CS10);
  OCR1A = 500;
  TIMSK |= (1 << OCIE1A);
}

ISR(TIMER1_COMPA_vect)
{
  if(red >= counter)
  {
    PORTB |= (1 << PB0);
  }
  else
  {
    PORTB &= ~(1 << PB0);
  }

  if(green >= counter)
  {
    PORTB |= (1 << PB1);
  }
  else
  {
    PORTB &= ~(1 << PB1);
  }

  if(blue >= counter)
  {
    PORTB |= (1 << PB2);
  }
  else
  {
    PORTB &= ~(1 << PB2);
  }



  if(counter == 255)
  {
    counter = 0;
  }
  else
  {
    counter++;
  }
}

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.