Software PWM Problem

Gast #704165
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?
#704382
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.
Gast #707839
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren