1 | /*#########################################################################################
|
2 |
|
3 | Auswertung des Daewoo-Fernbedienungscodes
|
4 |
|
5 | Achtung! Dies ist nur eine Studienversion, die noch keine weitere Funktionalität hat.
|
6 |
|
7 | Das Programm wurde erstellt von Guido S.
|
8 |
|
9 | ATMega8
|
10 |
|
11 | #########################################################################################*/
|
12 |
|
13 | #include <avr/io.h>
|
14 | #include <avr/interrupt.h>
|
15 |
|
16 | uint8_t FlankenZaehler;
|
17 | uint16_t Adr_OPCode;
|
18 | uint16_t VergZeit;
|
19 |
|
20 |
|
21 | void Ausgabe(uint8_t Wert)
|
22 | {
|
23 | // an PortB2 bis B6 und PortC0 bis C2 sind LEDs angeschlossen
|
24 | // somit kann ein Byte angezeigt werden
|
25 |
|
26 | // Aufbereitung der Daten und Ausgabe an die richtigen Pins
|
27 | // die Bits werden negiert, damit man auf eine richtige Darstellung kommt
|
28 | // => Bit von Wert = "1" - LED an; Bit von Wert = "0" - LED aus
|
29 | PORTB = ~((Wert << 1) & 0b00111110);
|
30 | PORTC = ~(Wert >> 5);
|
31 | }
|
32 |
|
33 |
|
34 | ISR(INT1_vect)
|
35 | {
|
36 | /* Interrupt Code */
|
37 |
|
38 | // hier findet die Zeitmessung statt
|
39 | // Messung beginnt beim Eintreffen des ersten EXT1-Interrupts
|
40 |
|
41 | void Fehlerbehandlung(void)
|
42 | {
|
43 | // Flankenzähler wird auf 0 gestellt - eine neue Sequenz kann beginnen
|
44 | FlankenZaehler = 0;
|
45 | }
|
46 |
|
47 | // Timer auslesen
|
48 | VergZeit = TCNT1; // Read TCNT1 // seit dem Int ist TCNT1 um 43 erhöht
|
49 | TCNT1 = 0; // Timer soll von 0 beginnen; für diesen Befehl werden weitere 6 Takte benötigt
|
50 |
|
51 | #define Tolleranz 8 // Werte zwischen 5 und 15 haben sich als sinnvoll gezeigt
|
52 |
|
53 | #if (F_CPU <= 6553500)
|
54 | // Diese Berechnung geht nur bis 6,5535 MHz
|
55 | #define T10ms (F_CPU/100)
|
56 | #define T8msh (((F_CPU/1000)*8)+((F_CPU/10000)*Tolleranz))
|
57 | #define T8msl (((F_CPU/1000)*8)-((F_CPU/10000)*Tolleranz))
|
58 | #define T4msh (((F_CPU/1000)*4)+((F_CPU/10000)*Tolleranz))
|
59 | #define T4msl (((F_CPU/1000)*4)-((F_CPU/10000)*Tolleranz))
|
60 | #define T055msh (((F_CPU/100000)*55)+((F_CPU/100000)*3*Tolleranz))
|
61 | #define T055msl (((F_CPU/100000)*55)-((F_CPU/100000)*3*Tolleranz))
|
62 | #define T045msh (((F_CPU/100000)*45)+((F_CPU/100000)*3*Tolleranz))
|
63 | #define T045msl (((F_CPU/100000)*45)-((F_CPU/100000)*3*Tolleranz))
|
64 | #define T145msh (((F_CPU/100000)*145)+((F_CPU/100000)*3*Tolleranz))
|
65 | #define T145msl (((F_CPU/100000)*145)-((F_CPU/100000)*3*Tolleranz))
|
66 | #else
|
67 | // Bei F_CPU > 6,5535 MHz wird der Vorteiler auf 8 gestellt und die Zeiten berechnen sich so:
|
68 | #define T10ms (F_CPU/800)
|
69 | #define T8msh (((F_CPU/8000)*8)+((F_CPU/80000)*Tolleranz))
|
70 | #define T8msl (((F_CPU/8000)*8)-((F_CPU/80000)*Tolleranz))
|
71 | #define T4msh (((F_CPU/8000)*4)+((F_CPU/80000)*Tolleranz))
|
72 | #define T4msl (((F_CPU/8000)*4)-((F_CPU/80000)*Tolleranz))
|
73 | #define T055msh (((F_CPU/800000)*55)+((F_CPU/800000)*3*Tolleranz))
|
74 | #define T055msl (((F_CPU/800000)*55)-((F_CPU/800000)*3*Tolleranz))
|
75 | #define T045msh (((F_CPU/800000)*45)+((F_CPU/800000)*3*Tolleranz))
|
76 | #define T045msl (((F_CPU/800000)*45)-((F_CPU/800000)*3*Tolleranz))
|
77 | #define T145msh (((F_CPU/800000)*145)+((F_CPU/800000)*3*Tolleranz))
|
78 | #define T145msl (((F_CPU/800000)*145)-((F_CPU/800000)*3*Tolleranz))
|
79 | #endif
|
80 |
|
81 | // hier beginnt die Abfrage des Flankenzählers
|
82 | if (FlankenZaehler == 0)
|
83 | {
|
84 | // Timer 1 einstellen - Timer wird als CTC genutzt
|
85 | // Mode 4
|
86 | // CLKi/o / 1 oder CLKi/o / 8
|
87 | TCCR1A = 0;
|
88 | #if (F_CPU <= 6553500)
|
89 | TCCR1B = (1 << WGM12) | (1 << CS10);
|
90 | #else
|
91 | TCCR1B = (1 << WGM12) | (1 << CS11);
|
92 | #endif
|
93 | FlankenZaehler++; // Flankenzähler erhöhen und auf neue Flanke warten
|
94 | }
|
95 | else if (FlankenZaehler == 1)
|
96 | { // die erste Periode müssen 8 ms lang sein
|
97 | if ((VergZeit > T8msl) & (VergZeit < T8msh))
|
98 | {
|
99 | FlankenZaehler++; // Flankenzähler erhöhen und auf neue Flanke warten
|
100 | }
|
101 | else
|
102 | {
|
103 | // Flanke ist nicht im erwarteten Zeitraum gekommen
|
104 | Fehlerbehandlung();
|
105 | }
|
106 | }
|
107 | else if ((FlankenZaehler == 2) | (FlankenZaehler == 20))
|
108 | { // diese Perioden müssen 4 ms lang sein
|
109 | if ((VergZeit > T4msl) & (VergZeit < T4msh))
|
110 | {
|
111 | FlankenZaehler++; // Flankenzähler erhöhen und auf neue Flanke warten
|
112 | }
|
113 | else
|
114 | {
|
115 | // Flanke ist nicht im erwarteten Zeitraum gekommen
|
116 | Fehlerbehandlung();
|
117 | }
|
118 | }
|
119 | else if ((FlankenZaehler & 1) == 1)
|
120 | { // wenn Flankenzähler ungerade, dann muss die Zeit 0,55 ms sein
|
121 | if ((VergZeit > T055msl) & (VergZeit < T055msh))
|
122 | {
|
123 | if (FlankenZaehler == 37)
|
124 | { // wenn Flankenzähler 37 ist, dann ist das Stopp-Bit erreicht
|
125 | // hier wird nicht mehr auf die nächste Flanke gewartet,
|
126 | // da das Stopp-Bit nur eine halbe Welle ist
|
127 | // an dieser Stelle wurde der Code komplett empfangen
|
128 | // JUCHU!!!
|
129 | TCCR1A = 0; // CTC abschalten
|
130 | TCCR1B = 0; // CTC abschalten
|
131 | Ausgabe((uint8_t)(Adr_OPCode >> 8)); // Ausgabe des OP-Codes
|
132 | //Ausgabe((uint8_t)(Adr_OPCode)); // das ist die Geräteadresse
|
133 | FlankenZaehler = 0;
|
134 | }
|
135 | else
|
136 | { // bei allen anderen Flanken ist alles OK und der Flankenzähler wird erhöht
|
137 | FlankenZaehler++; // Flankenzähler erhöhen und auf neue Flanke warten
|
138 | }
|
139 | }
|
140 | else
|
141 | {
|
142 | // Flanke ist nicht im erwarteten Zeitraum gekommen
|
143 | Fehlerbehandlung();
|
144 | }
|
145 | }
|
146 | else if ((FlankenZaehler & 1) == 0)
|
147 | { // hier kommt die Auswertung der 2. Halbwelle, die die Information beinhaltet,
|
148 | // ob es eine eine "0" oder "1" ist
|
149 | if ((VergZeit > T045msl) & (VergZeit < T145msh))
|
150 | {
|
151 | FlankenZaehler++; // Flankenzähler erhöhen und auf neue Flanke warten
|
152 | if ((VergZeit > T045msl) & (VergZeit < T045msh))
|
153 | // das erkannte Bit ist eine "0"
|
154 | {
|
155 | Adr_OPCode = (Adr_OPCode >> 1);
|
156 | }
|
157 | else if ((VergZeit > T145msl) & (VergZeit < T145msh))
|
158 | // das erkannte Bit ist eine "1"
|
159 | {
|
160 | Adr_OPCode = (Adr_OPCode >> 1) | (1 << 15);
|
161 | }
|
162 | else
|
163 | {
|
164 | // Flanke ist nicht im erwarteten Zeitraum gekommen
|
165 | Fehlerbehandlung();
|
166 | }
|
167 | }
|
168 | else
|
169 | {
|
170 | // Flanke ist nicht im erwarteten Zeitraum gekommen
|
171 | Fehlerbehandlung();
|
172 | }
|
173 | }
|
174 | }
|
175 |
|
176 |
|
177 | int main(void)
|
178 | {
|
179 | // Variablen initialisieren
|
180 | FlankenZaehler = 0;
|
181 |
|
182 | // Interrupts initialisieren
|
183 | MCUCR |= (1 << ISC10); MCUCR &= ~(1 << ISC11); //EXT1 soll bei jeder Flanke ausgelöst werden
|
184 | GICR |= (1 << INT1); // EXT1 Interrupt erlauben
|
185 | sei(); // global Interrupt erlauben
|
186 |
|
187 | // Ports initialisieren
|
188 | // PB1 bis PB5 als Ausgang; an diesen Ports ist je eine LED mit Vorwiderstand gegen +5V angeschlossen
|
189 | DDRB |= (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5);
|
190 | // PC0 bis PC2 als Ausgang; an diesen Ports ist je eine LED mit Vorwiderstand gegen +5V angeschlossen
|
191 | DDRC |= (1 << PC0) | (1 << PC1) | (1 << PC2);
|
192 |
|
193 | // diese Ausgabe ist nur zum Test und soll mir zeigen, dass die CPU bereit ist
|
194 | Ausgabe(0b10100101);
|
195 |
|
196 | // Das Hauptprogramm ist eine Endlosschleife, es wird durch Interrupts unterbrochen
|
197 | while(1)
|
198 | {
|
199 | }
|
200 | }
|