1 | #include <avr/interrupt.h>
|
2 | #include <EEPROM.h>
|
3 |
|
4 |
|
5 | //Deklaration der Variablen
|
6 | volatile unsigned int timer4_ovl_counter;
|
7 | volatile unsigned int timer4_value;
|
8 | volatile float high_time;
|
9 | volatile float low_time;
|
10 | volatile float period;
|
11 | volatile float frequency;
|
12 | volatile float prescale;
|
13 | volatile unsigned long timestamp;
|
14 | volatile unsigned long test1;
|
15 | volatile unsigned long test2;
|
16 |
|
17 |
|
18 | // Deklaration der Funktionen
|
19 | void timer4_config (byte, int, byte, byte, byte); //Prototyp Timer 4 Konfiguration
|
20 | void initialize_ir(void); //Prototyp Interrupt initialisieren
|
21 | void get_PWM(int); //PWM Messung starten, Übergabeparameter Zeit in ms
|
22 |
|
23 |
|
24 | void setup(){
|
25 |
|
26 | digitalWrite(13, LOW);
|
27 | // EEPROM zu Null setzen
|
28 | for (int i = 0; i < 512; i++)
|
29 | EEPROM.write(i, 0);
|
30 | // LED anschalten wenn fertig
|
31 | digitalWrite(13, HIGH);
|
32 |
|
33 | Serial.begin(9600); //Kommunikation PC-Schnittstelle aktivieren
|
34 |
|
35 | initialize_ir(); //Interrupts aktivieren
|
36 |
|
37 | timer4_ovl_counter = 0;
|
38 | timer4_value = 0;
|
39 | high_time = 0.0;
|
40 | low_time = 0.0;
|
41 | period = 0.0;
|
42 | frequency = 0.0;
|
43 | prescale = 0;
|
44 | timestamp = 0;
|
45 | test1 = 0;
|
46 | test2 = 0;
|
47 | timer4_config(0,8,0,0,1); //Modus 0 = normal; Prescaler auf 8; Capture Compare Modus = 0; Start mit steigender Flanke
|
48 |
|
49 | Serial.println("Function Setup is done");
|
50 |
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 | void loop(){
|
56 |
|
57 | Serial.println("High Time [s]: ");
|
58 | Serial.println(high_time,DEC);
|
59 | Serial.println("\t");
|
60 |
|
61 | Serial.println("Low Time [s]: ");
|
62 | Serial.println(low_time,DEC);
|
63 | Serial.println("\t");
|
64 |
|
65 | Serial.println("Periodendauer [s]: ");
|
66 | Serial.println(period,DEC);
|
67 | Serial.println("\t");
|
68 |
|
69 | Serial.println("Frequenz [Hz]: ");
|
70 | Serial.println(frequency,DEC);
|
71 | Serial.println("\t");
|
72 |
|
73 | Serial.println(timer4_value);
|
74 | Serial.println("\t");
|
75 |
|
76 | Serial.println(timer4_ovl_counter);
|
77 | Serial.println("\t");
|
78 |
|
79 | Serial.println(prescale);
|
80 | Serial.println("\t");
|
81 |
|
82 | Serial.print(test1);
|
83 | Serial.print("\t");
|
84 | Serial.print(test2);
|
85 | Serial.println("\t");
|
86 |
|
87 |
|
88 | TIMSK4 |= (1 << ICIE4);
|
89 |
|
90 | timestamp = millis();
|
91 | while((timestamp + 200) >= millis()){}
|
92 |
|
93 | TIMSK4 &=~ (1 << ICIE4);
|
94 |
|
95 | timestamp = millis();
|
96 | while((timestamp + 2000) >= millis()){}
|
97 | // delay(2000);
|
98 |
|
99 |
|
100 | }
|
101 |
|
102 |
|
103 | ISR(__vector_default)
|
104 | {
|
105 | Serial.println("Bad ISR");
|
106 | }
|
107 |
|
108 |
|
109 | void initialize_ir(void){
|
110 | sei(); //globale Interrupt Freigabe
|
111 | TIMSK4 |= (1 << TOIE4); //Overflow Timer 4 Interrupt aktiviert
|
112 | TIMSK4 &=~ (1 << ICIE4); // TIMSK4 |= (1 << ICIE4); //Capture Event Interrupt aktiviert
|
113 | }
|
114 |
|
115 | // Overflow Interrupt: hochzaehlen Overflowvariable, beruecksichtigen beim Zaehlwert Interrupt Name: TIMER4_OVF_vect
|
116 | ISR(TIMER4_OVF_vect){
|
117 | cli(); //Interrupts deaktivieren
|
118 | test1 = test1 + 1;
|
119 | timer4_ovl_counter = timer4_ovl_counter + 1;
|
120 | TIFR4 &=~ (1 << TOV4); //Interrupt Flag fuer Overflow zuruecksetzen
|
121 | sei();
|
122 | }
|
123 |
|
124 | //Capture Event Interrupt: bei erkannter Flanke muss der Zaehlwert des Timers ausgelesen werden
|
125 | ISR(TIMER4_CAPT_vect){
|
126 | cli();
|
127 | test2 += 1;
|
128 | while((ASSR & 0x4) == 0x4){} //Pause: Maskierung um gesetztes drittes Bit zu erkennen: TCN2UB ist gesetzt solange TCNT4 beschrieben wird
|
129 | digitalWrite(13, HIGH);
|
130 | TCCR4A &=~( (1 << CS42) | (1 << CS41) | (1 << CS40)); //Timer anhalten
|
131 |
|
132 | timer4_value = ICR4L; // ICR4L 8 Bit Low Zaehlwert auslesen
|
133 | timer4_value |= (ICR4H << 8); // ICR4H 8 Bit High Zaehlwert auslesen
|
134 |
|
135 | //Wenn auf positive Flanke getriggert wird, ist die gemessene Zeit zuvor low_time (Bit ist ICES4)
|
136 | if((TCCR4B & 0x40) == 0x40){
|
137 | low_time = ( float(timer4_value) + float(65535 * timer4_ovl_counter) ) * (prescale / 16000000); //beruecksichtigt Zaehler Ueberlauf, und Prescalefaktor
|
138 | timer4_ovl_counter = 0;
|
139 | TCCR4B &=~ (1 << ICES4); //wenn auf Positiv getriggert wurde, wird nun auf negative Flanke umgestellt
|
140 | }
|
141 |
|
142 | //Wenn auf negative Flanke getriggert wird, ist die gemessene Zeit zuvor high_time (Bit ist ICES4)
|
143 | else if((TCCR4B & 0x40) == 0x0){
|
144 | high_time = ( float(timer4_value) + float(65535 * timer4_ovl_counter) ) * (prescale / 16000000);
|
145 | timer4_ovl_counter = 0;
|
146 | TCCR4B |= (1 << ICES4); //wenn auf Negativ getriggert wurde, wird nun auf positive Flanke umgestellt
|
147 | }
|
148 |
|
149 | //Zaehlerstand zuruecksetzten, High-Byte zuerst, dann Low-Byte
|
150 | TCNT4H = 0x0;
|
151 | TCNT4L = 0x0;
|
152 | digitalWrite(13, LOW);
|
153 |
|
154 | period = high_time + low_time; //Berechnung der Periodendauer und Frequenz
|
155 | frequency = 1 / period;
|
156 |
|
157 |
|
158 | TIFR4 &=~ (1 << ICF4); //Interrupt Flag fuer Capture Event zuruecksetzen
|
159 | sei();
|
160 | }
|
161 |
|
162 |
|
163 | void timer4_config (byte modus, int prescaler, byte COM4A1_COM4A0, byte COM4B1_COM4B0, byte ICNC4_ICES4)
|
164 | {
|
165 | //Bitweise Maskierung
|
166 | modus &= 15;
|
167 | COM4A1_COM4A0 &= 3;
|
168 | COM4B1_COM4B0 &= 3;
|
169 | ICNC4_ICES4 &= 3;
|
170 | prescale = float(prescaler);
|
171 |
|
172 | byte takt = 0 ;
|
173 | switch (prescaler)
|
174 | {
|
175 | case -99: takt = 6; break;
|
176 | case -89: takt = 7; break;
|
177 | case 0: takt = 0; break;
|
178 | case 1: takt = 1; break;
|
179 | case 8: takt = 2; break;
|
180 | case 64: takt = 3; break;
|
181 | case 256: takt = 4; break;
|
182 | case 1024: takt = 5; break;
|
183 | default:
|
184 | takt = 1;
|
185 | }
|
186 |
|
187 | TCCR4A = (COM4A1_COM4A0 << 6) | (COM4B1_COM4B0 << 4) | (modus & 3);
|
188 | TCCR4B = (ICNC4_ICES4 << 6) | ((modus & 0xC) << 1) | takt;
|
189 |
|
190 | while((ASSR & 0x1) == 0x1){} //Maskierung um gesetztes erstes Bit zu erkennen: TCR2UB ist gesetzt solange TCCR4 beschrieben wird
|
191 | }
|