Dateianhang 'multiswitch_encoder_robbe_einfach.c'
Herunterladen 1 /**************************************************************************
2 *Multiswitchmodul auf Basis eines Tiny44
3 *Ausgabe ueber einen Pin mit 33K, sowie eine zweiten Pin fuer das Sync-Signal
4 *
5 *Sync entweder über ein einzelnes Sync-Signal, oder ueber PPM-Summe
6 *
7 *Eingang des PPM-Signals an PB2 (INT0), Ausgabe an PB0 (normal) und PB1 (Sync)
8 *Alle Schalter sind per AD-Eingang angebunden
9 *
10 *
11 *Int0 triggert auf neg. Flanke und startet Timer0. Der laeuft max. 2ms, falls in
12 *der Zeit kein weiterer Int reinkommt, ist das Frame beendet, und der nächste Zustand
13 *wird an den Ausgang gegeben. Falls zur Laufzeit ein Int kommt, wird der Timer resetet
14 *
15 *
16 ***************************************************************************/
17 #include <avr/io.h>
18 #include <avr/interrupt.h>
19
20
21 /*************************************************************
22 *MAKROS und #defines
23 **************************************************************/
24 #define FLAG_VARIABLE GPIOR0
25 //FLAGS
26 #define NEXT_VAL 0
27
28
29
30 //Defines der Ausgangszustaende
31 #define SW_SYNC 0
32 #define SW_HIGH 1
33 #define SW_LOW 2
34 #define SW_MID 3
35
36 //Schalterzuordnung
37 #define AD_S1 0
38 #define AD_S2 1
39 #define AD_S3 3
40 #define AD_S4 2
41 #define AD_S5 4
42 #define AD_S6 5
43 #define AD_S7 6
44 #define AD_S8 7
45
46
47 //MAKROS
48 #define CHECK_FLAG(A) (FLAG_VARIABLE & (1<<A))
49 #define DEL_FLAG(A) (FLAG_VARIABLE &= ~(1<<A))
50 #define SET_FLAG(A) (FLAG_VARIABLE |= (1<<A))
51 //Schaltereingaenge
52
53
54 #define OBERE_SCHRANKE 158
55
56 #define UNTERE_SCHRANKE 78
57
58 #define OUT_PORT PORTB
59 #define OUT_DDR DDRB
60 #define OUT_PIN PB0
61 #define SYNC_PIN PB1
62
63
64 /*************************************************************
65 *ISR
66 **************************************************************/
67 ISR(INT0_vect)
68 {
69 //Timer starten oder zuruecksetzen
70 //Timer-Int-Flag loeschen
71 TIFR0 |= (1<<TOV0);
72 //Zaehlerregister loeschen
73 //alte Version
74 // TCNT0 = 208; //Preset, um Periode von 3ms zu erreichen
75 // TCCR0B |= (1<<CS01) | (1<<CS00); //Prescaler 64, Timer startet
76 //neuere Version -> kleinere Pause
77
78 //Timer reset
79 TCNT0 = 0;
80 TCCR0B |= (1<<CS01); //Prescaler neu setzen
81
82 }
83
84
85 ISR(TIM0_OVF_vect)
86 //Timer anhalten, und neuen Zustand an den Ausgang geben, bzw. das Flag setzen
87 {
88 //Timer anhalten -> Prescaler loeschen
89 TCCR0B &= 0xF8;
90
91 SET_FLAG(NEXT_VAL);
92 }
93
94
95
96
97 /*************************************************************
98 *funktionen
99 **************************************************************/
100
101 void init_ports(void)
102 {
103 //Schalterport als Eingang;
104 DDRA = 0x00;
105
106 DDRB |= (1<<PB0) | (1<<PB1); //die beiden Ausgangspins als Ausgang setzen
107 }
108
109 void set_Ausgang(uint8_t zustand)
110 {
111 switch(zustand)
112 {
113 case SW_SYNC:
114 OUT_PORT &= ~(1<<SYNC_PIN);
115 OUT_DDR |= (1<<SYNC_PIN);
116 break;
117 case SW_LOW:
118 //Sync abschalten
119 OUT_DDR &= ~(1<<SYNC_PIN);
120 OUT_PORT &= ~(1<<SYNC_PIN);
121 //Pin auf Ausgang und low
122 OUT_DDR |= (1<<OUT_PIN);
123 OUT_PORT &= ~(1<<OUT_PIN);
124 break;
125 case SW_MID:
126 //Sync abschalten
127 OUT_DDR &= ~(1<<SYNC_PIN);
128 OUT_PORT &= ~(1<<SYNC_PIN);
129 //Pin auf Eingang und Pullup aus
130 OUT_DDR &= ~(1<<OUT_PIN);
131 OUT_PORT &= ~(1<<OUT_PIN);
132 break;
133 case SW_HIGH:
134 //Sync abschalten
135 OUT_DDR &= ~(1<<SYNC_PIN);
136 OUT_PORT &= ~(1<<SYNC_PIN);
137 //Pin auf Ausgang und high
138 OUT_DDR |= (1<<OUT_PIN);
139 OUT_PORT |= (1<<OUT_PIN);
140 break;
141 default:
142 //Sync abschalten
143 OUT_DDR &= ~(1<<SYNC_PIN);
144 OUT_PORT &= ~(1<<SYNC_PIN);
145 //Pin auf Eingang und Pullup aus
146 OUT_DDR &= ~(1<<OUT_PIN);
147 OUT_PORT &= ~(1<<OUT_PIN);
148 break;
149 }
150 }
151
152
153 void init_int(void)
154 {
155 DDRB &= ~(1<<PB2);
156 // PORTB |= (1<<PB2); //Pullup an ->nicht noetig, da extern vorhanden
157 MCUCR |= (1<<ISC01); //triggern auf fallende Flanke
158 GIMSK |= (1<<INT0); //Int freigeben
159 }
160
161
162 void init_timer0(void)
163 {
164 //Normal-Modus, Prescaler 8, OFV-Int an
165 // TCCR0B |= (1<<CS01); //Prescaler 8, wird erst durch den Int gestartet
166 TIMSK0 |= (1<<TOIE0); //OFV-Int angeschaltet
167 }
168
169
170 void init_ADC(void)
171 {
172 //Digital-Puffer abschalten
173 DIDR0 = 0xFF;
174
175 ADCSRB |= (1<<ADLAR); //AD-Ergebnisse linksbuendig ->fuer ein 8-Bit-Ergebniss nur ADCH noetig
176 ADCSRA |= (1<<ADPS1); //prescaler 4 ->250kHz // | (1<<ADPS0); //Prescaler auf 8 setzen
177 ADCSRA |= (1<<ADEN); //AD-Wandler anwerfen
178
179 //Referenzspannung: VCC
180
181 ADCSRA |= (1<<ADSC); // eine ADC-Wandlung, um den Wandler warmlaufen zu lassen
182 while ( ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten
183
184 }
185
186 /**/
187
188 uint8_t ADCRead(uint8_t mux) //liefert nur 8 Bit zurueck
189 //AD-Wandler-Funktion, bekommt den Kanal übergeben, liefert das Ergebnis zurück
190 {
191 uint8_t result;
192 result = 0;
193 ADMUX = mux; // Kanal waehlen (falls andere Referenz als VCC -> aufpassen, liegt im gleichen register)
194 //Eigentliche Messung
195 ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
196 while ( ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten
197
198 result = ADCH; //die obersten 8 Bit interessant -> nur das High-Byte lesen
199 return result;
200 }
201
202 uint8_t get_schalter_richtung(uint8_t schalter)
203 //Passt die Richtung der Schalter an, da sie durchs routen unterschiedlich an VCC ung GND hängen
204 //-> Schalter nach oben ergibt in jedem Fall "low", Schalter nach unten "high"
205 //-> wie beim Robbe-Orginal
206 {
207 if ((schalter == 1) || (schalter == 2) || (schalter == 3) || (schalter == 4))
208 {return 1;}
209 else
210 {return 0;}
211 }
212
213
214 /*************************************************************
215 *Main
216 **************************************************************/
217 int main(void)
218 {
219 uint8_t frame_counter;
220 uint8_t ad_ergebnis;
221
222 frame_counter = 0;
223 ad_ergebnis = 0;
224
225 FLAG_VARIABLE = 0;
226
227 init_ports();
228 init_ADC();
229 init_int();
230 init_timer0();
231 set_Ausgang(0xff);
232
233 sei();
234
235 for(;;)
236 {
237
238 /**/
239 if(CHECK_FLAG(NEXT_VAL)) //Timer abgelaufen, neues Ergebniss anlegen
240 {
241 DEL_FLAG(NEXT_VAL);
242 frame_counter++;
243 switch (frame_counter)
244 {
245 case 1:
246 ad_ergebnis = ADCRead(AD_S1);
247 break;
248 case 2:
249 ad_ergebnis = ADCRead(AD_S2);
250 break;
251 case 3:
252 ad_ergebnis = ADCRead(AD_S3);
253 break;
254 case 4:
255 ad_ergebnis = ADCRead(AD_S4);
256 break;
257 case 5:
258 ad_ergebnis = ADCRead(AD_S5);
259 break;
260 case 6:
261 ad_ergebnis = ADCRead(AD_S6);
262 break;
263 case 7:
264 ad_ergebnis = ADCRead(AD_S7);
265 break;
266 case 8:
267 ad_ergebnis = ADCRead(AD_S8);
268 break;
269 default:
270 frame_counter = 0; //->Sync ausloesen
271 break;
272 }
273 if(frame_counter == 0) //->Sync
274 {set_Ausgang(SW_SYNC);}
275
276 else //kein sync, entsprechend Ausgang setzen
277 {
278 if (ad_ergebnis > OBERE_SCHRANKE)
279 {
280 if (get_schalter_richtung(frame_counter))
281 {set_Ausgang(SW_HIGH);}
282 else
283 {set_Ausgang(SW_LOW);}
284 }
285 else
286 {
287 if (ad_ergebnis < UNTERE_SCHRANKE)
288 if (get_schalter_richtung(frame_counter))
289 {set_Ausgang(SW_LOW);}
290 else
291 {set_Ausgang(SW_HIGH);}
292 else
293 {set_Ausgang(SW_MID);}
294
295 }
296 }
297 } //if(CHECK_FLAG(NEXT_VAL))
298 } //for(;;)
299
300 return 0;
301 }
Gespeicherte Dateianhänge
Um Dateianhänge in eine Seite einzufügen sollte unbedingt eine Angabe wie attachment:dateiname benutzt werden, wie sie auch in der folgenden Liste der Dateien erscheint. Es sollte niemals die URL des Verweises ("laden") kopiert werden, da sich diese jederzeit ändern kann und damit der Verweis auf die Datei brechen würde.Sie dürfen keine Anhänge an diese Seite anhängen!