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 | }
|