Hardware PWM auf ATmega8

OP #2833052
Lesenswert?

Hallo,
ich bin in dem Gebiet der µCs noch Neueinsteiger und versuche mich zZ an 
einer Hardware PWM. Verwendet wird ein Atmega8 mit 8MHz.
Als Vorlage habe ich diese Seite genommen: 
http://extremeelectronics.co.in/avr-tutorials/pwm-signal-generation-by-using-avr-timers-part-ii/

Ich hab den Code soweit auf mein Atmega8 angepasst
1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
void InitPWM()
5
{
6
   /*
7
   TCCR0 - Timer Counter Control Register (TIMER0)
8
   -----------------------------------------------
9
   BITS DESCRIPTION
10
   
11

12
   NO:   NAME   DESCRIPTION
13
   --------------------------
14
   BIT 7 : FOC0   Force Output Compare [Not used in this example]
15
   BIT 6 : WGM00  Wave form generartion mode [SET to 1]
16
   BIT 5 : COM01  Compare Output Mode        [SET to 1]
17
   BIT 4 : COM00  Compare Output Mode        [SET to 0]
18

19
   BIT 3 : WGM01  Wave form generation mode [SET to 1]
20
   BIT 2 : CS02   Clock Select               [SET to 0]
21
   BIT 1 : CS01   Clock Select               [SET to 0]
22
   BIT 0 : CS00   Clock Select               [SET to 1]
23

24
   The above settings are for
25
   --------------------------
26

27
   Timer Clock = CPU Clock (No Prescalling)
28
   Mode        = Fast PWM
29
   PWM Output  = Non Inverted
30

31
   */
32

33
   //Set OC2 PIN as output. It is  PB3 on ATmega16 ATmega32/Atmega8; PortD6 Kontrolle
34
   DDRD  =  0b01000000;
35
   DDRB  =  0b00001000;
36
   //TCCR0|=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
37
  TCCR2=01101001;
38

39
}
40

41
/******************************************************************
42
Sets the duty cycle of output. 
43

44
Arguments
45
---------
46
duty: Between 0 - 255
47

48
0= 0%
49

50
255= 100%
51

52
The Function sets the duty cycle of pwm output generated on OC0 PIN
53
The average voltage on this output pin will be
54

55
         duty
56
 Vout=  ------ x 5v
57
         255 
58

59
This can be used to control the brightness of LED or Speed of Motor.
60
*********************************************************************/
61

62
void SetPWMOutput(uint8_t duty)
63
{
64
   OCR2=duty;
65
}
66

67
/******************************************************************** 
68

69
Simple Wait Loop
70

71
*********************************************************************/
72

73
void Wait()
74
{
75
 _delay_loop_2(62000);
76
}
77

78
void main()
79
{
80
   uint8_t brightness=0;
81

82
   //Initialize PWM Channel 0
83
   InitPWM();
84

85
   //Do this forever
86

87
   while(1)
88
   {
89
      //Now Loop with increasing brightness
90

91
      for(brightness=0;brightness<255;brightness++)
92
      {
93
         //Now Set The Brighness using PWM
94

95
         SetPWMOutput(brightness);
96
     
97
     //Kontrolllampe
98
    PORTD^=0b01000000;
99
         //Now Wait For Some Time
100
         Wait();
101
      }
102

103
      //Now Loop with decreasing brightness
104

105
      for(brightness=255;brightness>0;brightness--)
106
      {
107
         //Now Set The Brighness using PWM
108

109
         SetPWMOutput(brightness);
110

111
         //Now Wait For Some Time
112
         Wait();
113
      }
114
   }
115
}

Leider kann ich am PortB3 kein oszillieren messen. Vielleicht könnt ihr 
ja einen Fehler finden...
Achja am PortD6 hängt ne LED, die mir bestätigt das beide For 
Anweisungen durchlaufen werden...

Bin für jede Antwort Dankbar!
#2833089
Lesenswert?

Eric Weiß schrieb:

> Leider kann ich am PortB3 kein oszillieren messen. Vielleicht könnt ihr
> ja einen Fehler finden...

Dein Hauptfehler besteht darin, dass du auf bescheuerter Syntax 
bestehst.

Das hier
1
  TCCR2=01101001;

tut nicht das, was du denkst das es tun sollte.
01101001
ist keine Binärzahl sondern eine Oktalzahl.

Und darf man erfahren, warum du diese Schreibweise, der einfach zu 
lesenderen, einfacher zu analysierenden und zumindest in dieser Hinsicht 
WESENTLICH weniger fehleranfälligen Schreibweise
1
   TCCR2 |= (1<<WGM20) | (1<<WGM21) |    // Fast PWM
2
            (1<<COM21) |                 // Clear when Up, Set when down
3
            (1<<CS20);                   // Prescaler 1
vorziehst?
Da sieht man auf einen Blick, welche Bits gesetzt werden und kann mit 
den Bitnamen im Datenblatt vergleichen. Schreibst du das binär, muss man 
erst mal die Bits auseinander dröseln, ehe man feststellen kann, was du 
da überhaupt alles einschaltest.
Benutze die Bitnamen aus dem Datenblatt! Dazu wurden die Header Files 
entsprechend gepimpt, damit du das machen kannst!


Hier
   DDRB  =  0b00001000;
ist es zwar prinzipiell richtig, aber von der Schreibweise genau das 
gleiche:
Wenn du Bit 3 (PB3) auf 1 setzen willst, dann schreib das auch so:
   DDRB |= ( 1 << PB3 );

Jetzt kann der Blindenhund eines Blinden auf 15 Meter Entfernung 
erkennen, dass das Bit für PB3 auf 1 gesetzt wird. Kein Mensch muss dazu 
irgendwelche Bits zählen (und sich 3 mal verzählen) oder irgendwelche 
Prefixe für Binärzahlen benutzen (und manchmal darauf vergessen).
OP #2833111
Lesenswert?

Vielen Dank für deine sehr belustigende Antwort ;-).
Grund warum ich es so schreibe steht vermutlich gleich in der ersten 
Zeile meines Beitrages oben.
Ich habe auch erst seit heute deine Schreibweise kennengelernt, werde 
mich aber nun darrauf umstellen (versprochen!).

Die PWM läuft nun auch, Vielen Dank!

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