Software PWM

OP #1332030
Lesenswert?
• ▲
▼
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
#1332034
Lesenswert?
• ▲
▼
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);
#1332047
Lesenswert?
• ▲
▼
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.
#1332060
Lesenswert?
• ▲
▼
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

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