PWM auslesen Duty-Cycle

Gast #5784370
Lesenswert?
• ▲
▼
Hallo Leute,
Befasse mich jetzt seit geraumer Zeit mit der Programmierung von Atmel 
uC.
Jetzt befasse ich mich gerade mit Timer-Interrupts und versuche den 
Duty-Cycle eines 1khz PWM-Signals auszulesen.

Zum testen wollte ich einfach zu unterschiedlichen Duty-Cycle´n 
verschiedene Ausgänge schalten. Habe mich an einem Code aus einem 
anderen Beitrag orientiert und diesen leicht angepasst. Leider bekomme 
ich keine Ergebnisse und kein Ausgang schaltet. Vielleicht sieht ja 
einer den Fehler oder hat so etwas selber schon einmal gemacht.
Hier mein Code:


/*
 * PWM einlesen Interrupt.c
 *
 * Created: 22.03.2019 08:16:52
 * Author : Benno
 */


/*Beschreibung:

Ich habe den AT90CAN128 auf 16Mhz eingestellt, mit einem Vorteiler von 
64
ergibt das: 0,000004 Sekunden für einen Timerdurchlauf. Das PWM-Signal
hat 1kHz ==> 0.001 Sekunden
Daraus ergibt sich 0.001 / 0,000004 = 250

Der PortB sollen je nach Dutycycle geschaltet.

Nun zum Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 16000000UL
4

5
volatile int flanke=0;
6
volatile int aktuell_pwm_l=0;
7
volatile int aktuell_pwm_h=0;
8

9
ISR(TIMER1_CAPT_vect)
10
{
11

12
  if (flanke==0)
13
  {
14
    TCNT1H = 0;             //Timer auf null zurück
15
    TCNT1L = 0;
16
    TCCR1B&= ~(1<<ICES1);  //ICP-Pin auf fallende Flanke einstellen
17
    flanke=1;
18
  }
19
  else
20
  {
21
    flanke=0;
22
    TCCR1B|=(1<<ICES1);     //ICP auf steigende Flanke wieder aktivieren
23
    aktuell_pwm_l=ICR1L;  //Zählerstand speichern
24
    aktuell_pwm_h=ICR1H;    //zählerstand speichern
25
  }
26
}
27

28
void init_prozedur(void)
29
{
30
  TCCR1B |=  (1<<ICNC1)|(1<<ICES1)|(1<<CS11)|(1<<CS10) ; // Mittelung ON, steigende flanke, vorteiler 64
31
  TIMSK1 |= (1<<ICIE1);//INTERRUPT ON
32

33
  sei();
34
}
35

36
int main (void)
37
{
38
  init_prozedur();
39
  DDRB=0b00001101;
40
  DDRD=0x00;
41
  
42
  while(1) 
43
  {
44
    
45
    if (aktuell_pwm_h >= 50 && aktuell_pwm_h < 100)
46
    {
47
      PORTB|=(1<<PB0);
48
    }
49
    if (aktuell_pwm_h >= 100 && aktuell_pwm_h <250)
50
    {
51
      PORTB|=(1<<PB2);
52
    }
53
    else
54
    {
55
      PORTB |= (0<<PB0)|(0<<PB2);
56
    }
57
  }
58

59
}
Gast #5784453
Lesenswert?
• ▲
▼
Keine Ahnung bzgl des Interrupt-Kodes, aber in main sind zwei Fehler:

1) Die Ports werden nie gelöscht, ein Statement wie "y |= (0<<x)" macht 
nichts.  Wenn das Bit gelöscht werden soll, wäre "y ~= ~(1<<x)" richtig.

2) Du liest aktuell_pwm_h mehrmals aus.  Da sich der Wert durch einen 
Interrupt ändert, können beide if-Bedingungen wahr werden.
1
  while(1) 
2
  {
3
    uint8_t port = PORTB & ~((1<<PB0)|(1<<PB2));
4
    uint8_t pwm = aktuell_pwm_h;
5

6
    if (pwm >= 50 && pwm < 100)
7
       port |= 1<<PB0;
8
    if (pwm >= 100 && pwm < 250)
9
       port |= 1<<PB2;
10

11
    PORTB = port;
12
  }

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

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.