Software PWM

OP #1332030
Hallo zusammen

Ich wollte mal hier meinen C-Code posten und fragen, was daran falsch 
sein sollte. Es funktioniet nicht wirklich. Ich realisiere mein PWM 
Signal mit einem Counter welcher funktioniert. Jedoch wird in der 
Interrupt Serviceroutine das PWM Signal nicht richtig erzeugt:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include <avr/interrupt.h>
6

7
#define t_Period  1000;
8

9
//pwm_on & pwm_off sind das Tastverhältnis
10
unsigned int pwm_on, pwm_off;
11
unsigned int pwm_on_count, pwm_off_count;
12

13

14
void init_timer()
15
{
16
  TCCR1A = 0b00000000; //Set timer to compare OCR1A register
17
  TCCR1B = 0b00001011; //Set prescaler to 64 and set Timer to compare OCR1A register
18
  TIMSK = 0b00010000; //Enable Timer 1 Compare A Interrupt
19
  OCR1A = 0x20; //Exact number for 2ms interrupts
20

21
  sei();
22
}
23

24

25

26
ISR(TIMER1_COMPA_vect)
27
{
28
  if(pwm_on_count < pwm_on) {
29
    PORTC |= (0 << 0);
30
    pwm_on_count++;  
31
  }
32

33
  else {
34
    if(pwm_off_count < pwm_off) {
35
      PORTC |= (1 << 0);
36
      pwm_off_count++;  
37
    }
38

39
    else {
40
      pwm_on--;
41
      pwm_on_count = 0;
42
      pwm_off = t_Period - pwm_on;
43
      pwm_off_count = 0;
44
    }
45
    
46
  }
47

48
  
49

50
}
51

52

53

54
void initIO(void) 
55
{
56
  DDRC = 0xff;
57
}
58

59
void main()
60
{
61
  //Initialisieren
62
  initIO();
63
  init_timer();
64
  pwm_on = t_Period;
65
  pwm_off = 0;
66
  pwm_on_count = 0;
67
  pwm_off_count = 0;
68

69
  while(1) {
70

71
  }
72

73
}
74

75

76
}

Ich verwende eine Atmega16. Ich danke für die Hilfe.

MFG
Marius Meier schrieb:

> Ich wollte mal hier meinen C-Code posten und fragen, was daran falsch
> sein sollte. Es funktioniet nicht wirklich.

Lass mich raten: Der Pin ist dauerhaft an?

Der Fehler liegt wohl hier:
1
 PORTC |= (0 << 0);

Damit schaltest du den Pin nicht ab, sondern machst garnichts.
So sollte es besser gehen:
1
 PORTC &=~(1 << 0);
Mark Brandis schrieb:

> Warum eigentlich schiebt Ihr Bits um Null Stellen? Ist das besonders
> performant? ;-)

Es macht den Code leichter lesbar.

Wenn man einmal
1
PORTC &=~0;
das nächste mal
1
PORTC &=~(1 << 1);
oder dann auch mal noch
1
PORTC &=~_BV(2);
oder gar
1
cbi(PORTC,3);
schreibt, dann trägt das nicht wirklich zum leichten Verständnis des 
Codes bei.
Man sollte daher eine der 4 Schreibweisen durchgehend im gesamten Code 
verwenden.
und statt literalen sollte man aber auch dann
(1 << PIN0) oder (1 << PINB0) schreiben, wobei ich letzteres schon 
wieder sinnlos finde, da mann, wenn man den Port ändert auch überall 
PINxn in PINynx ändern muss.

Edit:
>Ist das besonders performant? ;-)
der kompiler optimiert das sowiso weg.

Edit Edit:
@benedikt:
du hast die beiden ersten Varianten von Marius vergessen:
1
>  TIMSK = 0b00010000; //Enable Timer 1 Compare A Interrupt
2
>  OCR1A = 0x20; //Exact number for 2ms interrupts

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.