Forum: Mikrocontroller und Digitale Elektronik ICP Caputre Unit mit wechselnder Flanke


von Martin Neumann (Gast)


Lesenswert?

Hallo zusammen,

ich bin dabei, mit einer Capture Unit ein Frequenz zu messen. die 
Frequenz ist recht gering und spielt zwischen 0 und ca. 250Hz.
Verwendet wird dabei ein Atmega 8. Ein Optokoppler schaltet dabei bei 
jedem Signal Masse an den ICP Pin durch. Sonst liegt der ICP Pin durch 
den internen pullup auf "high". Eine LED hängt an PB1 auf active low 
(zur Frequenzdarstellung).
Das Hauptprogramm soll später einmal die Frequenz dann aus den Timer 
werten berechnen, aber das Einlesen klappt im Moment noch nicht ganz.
Gedacht ist, zunächst bei fallender Flanke einzulesen, Wert sichern eine 
LED einschalten, die Flanke wechseln, darin dann die LED ausschalten, 
nächste fallende einlesen, Endwert sichern, LED wieder anschalten, 
wieder auf steigende Flanke wechseln und darin die LED ausschalten.
Durch den Start und Endwert kann ich dann später meine Frequenz 
errechnen.

Nur das Problem ist, die LED müsste mit steigender Frequenz immer 
kräftiger erscheinen, bis sie für das Auge ab ca. 30-40 Hz in 
"Dauerleuchten" übergeht. Leider "hängt" die LED manchmal zwischendrin, 
als ob sie nicht ausgeschaltet wird.
Die Singale sind vom OK logischerweise prellfrei, daher vermute ich das 
Problem im Code:
1
/****************************************************************************/
2
/*                                      */
3
/*            Input Capture Funktion Atmega8            */
4
/*                                      */
5
/****************************************************************************/
6
7
// ----------------------------------------------------------------------------
8
// INCLUDES
9
// ----------------------------------------------------------------------------
10
11
#include <stdint.h>
12
#include <avr/io.h>
13
#include <avr/interrupt.h>
14
#include <util/delay.h>
15
#include <inttypes.h>
16
17
// ----------------------------------------------------------------------------
18
// DEFINES
19
// ----------------------------------------------------------------------------
20
#ifndef F_CPU
21
#define F_CPU           8000000UL                   // processor clock frequency 8Mhz
22
#endif
23
24
25
#define Input    PB0    //Pin des Input Captures PB0=ICP
26
#define LED      PB1    //Pin der LED die leuchtet im Takt der Frequenz
27
28
29
#ifndef TRUE
30
#define TRUE 1
31
#define FALSE 0
32
#endif
33
34
35
// ----------------------------------------------------------------------------
36
// Funktionsdeklarationen
37
// ----------------------------------------------------------------------------
38
void init(void);
39
40
// ----------------------------------------------------------------------------
41
// globale Variablen die durch Interrupts verändert werden
42
// ----------------------------------------------------------------------------
43
volatile unsigned char NrOverflowsTC1 = 0;    //gibt die Anzahl der Overflows des 16-bit Timers an
44
                        //pro Sekunde läuft der 16-bit Timer knapp 2mal über-->NROverflow läuft nach ca. 134s über
45
volatile unsigned int StartTime = 0;      //TCNT1-Wert bei der 1.Low-Flanke speichern
46
volatile unsigned int EndTime = 0;        //TCNT1-Wert bei der 2.Low-Flanke speichern
47
volatile unsigned char Messung_vollstaendig = 0;//JobFlag, das Timer Interrupt 2x vollständig richtig durchlaufen wurde, hat die Variable den Wert 2, erst dann wird im Hauptprogramm die Drehzahl berechnet werden
48
volatile unsigned char ErsteFlanke = TRUE;    //Zu Beginn soll die erste Flanke eingelesen werden, FALSE wäre die 2. Flanke
49
50
// ----------------------------------------------------------------------------
51
// globale Variablen des Programms
52
// ----------------------------------------------------------------------------
53
54
55
56
57
//Timer1 (16-Bit) Capture Interrupt Service Routine
58
59
ISR( TIMER1_CAPT_vect ){
60
    if ( !(TCCR1B & (1<<ICES1) )){        //Interrupt Caputre reagiert fallende Flanke
61
      if ( ErsteFlanke ){            //Ist es die erste Flanke oder Wurde schon eine Flanke eingelesen? 
62
        StartTime = ICR1;          //Start Wert sichern
63
        TCCR1B |= ( 1 << ICES1 );      //Schreibt bit für steigende Flanke
64
        TIFR |= ( 1 << ICF1 );        /*Nachdem ein Flankenwechsel gesetzt wird, muss das Interrupt Flag von der Software gelöscht werden
65
                            dies geschieht durch Schreiben einer logischen 1 in das ICF1 Register*/
66
        PORTB &= ~( 1 << LED );      //LED an PB1 einschalten  
67
        NrOverflowsTC1 = 0;          //Setzt die Overflows des Timer1 (16-bit) zurück
68
        ErsteFlanke = FALSE;             //Die naechste Flanke ist das Ende der Messung
69
      }
70
    
71
      else{                  //es wurde bereits eine 1. Flanke eingelesen, dies ist ist folgich die 2. Flanke
72
        EndTime = ICR1;            //End Wert sicehrn
73
        TCCR1B |= ( 1 << ICES1 );      //Schreibt bit für steigende Flanke
74
        TIFR |= ( 1 << ICF1 );        /*Nachdem ein Flankenwechsel gesetzt wird, muss das Interrupt Flag von der Software gelöscht werden
75
                            dies geschieht durch Schreiben einer logischen 1 in das ICF1 Register*/
76
        PORTB &= ~( 1 << LED );      //LED an PB1 einschalten  
77
      }
78
    }
79
    else{                    //sonst Interrupt bei fallender Flanke
80
      TCCR1B &= ~( 1 << ICES1 );        //Löscht bit für steigende Flanke --> Capture Interrupt reagiert nun wieder auf fallende Flanke
81
      TIFR |= ( 1 << ICF1 );          /*Nachdem ein Flankenwechsel gesetzt wird, muss das Interrupt Flag von der Software gelöscht werden
82
                            dies geschieht durch Schreiben einer logischen 1 in das ICF1 Register*/
83
      PORTB |= ( 1 << LED);          //schaltet die LED an PB1 wieder aus
84
      Messung_vollstaendig++;          //Wenn diese Anweisung 2x durchlaufen wird, hat die Variable Messung_vollstaendig den Wert 2 und es kann eine neue Messung begonnen werden
85
      if (Messung_vollstaendig == 2){      //Liegt eine vollständige Messung vor? Wenn 2 Durchgänge durchlaufen sind, ja
86
        ErsteFlanke = TRUE;               
87
        Messung_vollstaendig = 0;
88
      }
89
    }  
90
}
91
92
93
//Timer1 (16-Bit) Overflow Interrupt Service Routine
94
95
ISR (TIMER1_OVF_vect){
96
NrOverflowsTC1++;
97
98
}
99
100
//Hauptprogramm
101
int main()
102
{
103
104
  init();                              //Initialisieren der Ports über die Funktion init()
105
  
106
  while(1){
107
  // hier soll dann die Frequenz ausgewertet werden
108
  }
109
  
110
}
111
112
113
// ----------------------------------------------------------------------------
114
// Funktionen
115
// ----------------------------------------------------------------------------
116
117
/*Funktion zum Initialisierein des µC*/
118
119
void init(void) {
120
  
121
  DDRB = 0x00;                    //Datenrichtungsregister zunächst alle Eingang 
122
  DDRB |= (1 << DDB1);         //PB1 als Ausgang schalten für LED, PB2 ebenfalls
123
  PORTB |= (1 << Input) | (1 << LED);  //interner Pullup am Input Capture Eingang, LED am Anfang ausschalten
124
  
125
  // ========================================================================
126
  // 16-bit Timer1 initialisieren (dient zum zählen der Flankendauer)
127
  // ========================================================================
128
    
129
  //Timer für die Input Capture Funktion, zählt dies Zeiten zwischen zwei steigenden Flanken, Prescaler
130
  TCCR1B = (1 << CS00) | (1 << CS01);          // Prescaler 64
131
  TCCR1B &= ~(1<<ICES1);                  // Interrupt Capture wird zunächst auf fallende Flanke eingestellt
132
  TIMSK = (1<<TICIE1) | (1<<TOIE1);             // Aktiviert Input Capture Interrupt und Timer1 Overflow Interrupt
133
  
134
  //=========================================================================
135
  // Sonstiges
136
  //=========================================================================
137
  sei();                  //setzt globales Interrupt enable
138
  
139
  return;
140
}

Jemand eine Idee, wo ein Fehler sich eingeschlichen hat?

: Verschoben durch Admin
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.