Forum: Mikrocontroller und Digitale Elektronik Software PWM Problem


von Johannes G. (Gast)


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:
1
#define F_CPU 11059000L
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
6
7
uint8_t red = 0;
8
uint8_t green = 0;
9
uint8_t blue = 0;
10
11
uint8_t counter = 0;
12
13
int main(void)
14
{
15
  red = 255;
16
  green = 128;
17
  blue = 10;
18
19
  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
20
  PORTB &= ~((1 << PB0) | (1 << PB1) | (1 << PB2));
21
22
  TCCR1B |= (1 << CS10);
23
  TIMSK |= (1 << TOIE1);
24
  
25
  sei();
26
27
  while(1)
28
  {
29
  }
30
31
  return 0;
32
}
33
34
ISR(TIMER1_OVF_vect)
35
{
36
  if(red >= counter)
37
  {
38
    PORTB |= (1 << PB0);
39
  }
40
  else
41
  {
42
    PORTB &= ~(1 << PB0);
43
  }
44
45
  if(green >= counter)
46
  {
47
    PORTB |= (1 << PB1);
48
  }
49
  else
50
  {
51
    PORTB &= ~(1 << PB1);
52
  }
53
54
  if(blue >= counter)
55
  {
56
    PORTB |= (1 << PB2);
57
  }
58
  else
59
  {
60
    PORTB &= ~(1 << PB2);
61
  }
62
63
64
65
  if(counter == 255)
66
  {
67
    counter = 0;
68
  }
69
  else
70
  {
71
    counter++;
72
  }
73
}

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?

von Uhu U. (uhu)


Lesenswert?


von Johannes G. (Gast)


Lesenswert?

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

von Werner (Gast)


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...

von Karl H. (kbuchegg)


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.

von Johannes G. (Gast)


Angehängte Dateien:

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?

von Johannes G. (Gast)


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:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
5
uint8_t red = 255;
6
uint8_t green = 128;
7
uint8_t blue = 10;
8
9
uint8_t counter = 0;
10
11
void pwm_init(void);
12
13
int main(void)
14
{
15
  pwm_init();
16
  
17
  sei();
18
19
  while(1)
20
  {
21
  }
22
23
  return 0;
24
}
25
26
27
void pwm_init(void)
28
{
29
  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
30
  PORTB &= ~((1 << PB0) | (1 << PB1) | (1 << PB2));
31
32
  TCCR1B |= (1 << WGM12) | (1 << CS10);
33
  OCR1A = 500;
34
  TIMSK |= (1 << OCIE1A);
35
}
36
37
ISR(TIMER1_COMPA_vect)
38
{
39
  if(red >= counter)
40
  {
41
    PORTB |= (1 << PB0);
42
  }
43
  else
44
  {
45
    PORTB &= ~(1 << PB0);
46
  }
47
48
  if(green >= counter)
49
  {
50
    PORTB |= (1 << PB1);
51
  }
52
  else
53
  {
54
    PORTB &= ~(1 << PB1);
55
  }
56
57
  if(blue >= counter)
58
  {
59
    PORTB |= (1 << PB2);
60
  }
61
  else
62
  {
63
    PORTB &= ~(1 << PB2);
64
  }
65
66
67
68
  if(counter == 255)
69
  {
70
    counter = 0;
71
  }
72
  else
73
  {
74
    counter++;
75
  }
76
}

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.