1 | #define F_CPU 8000000UL // 8MHz
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <avr/interrupt.h>
|
5 | #include <util/delay.h>
|
6 | #include <inttypes.h>
|
7 |
|
8 | // ------------------------------------------------------------------------------------------------
|
9 | // DEFINES
|
10 | // ------------------------------------------------------------------------------------------------
|
11 |
|
12 | #define COUNTER_INCS_PER_MILLISECOND_T0 1000 // (8.000.000 / 8) / 1000
|
13 | #define COUNTER_INCS_PER_SECOND_T0 1000000
|
14 |
|
15 | // PIN Definitionen
|
16 | #define Taster PB0 // PIN des Tasters
|
17 | #define LED PB1 // PIN der LED, die blinkt
|
18 |
|
19 | // ------------------------------------------------------------------------------------------
|
20 | // Funktionsdeklarationen
|
21 | // ------------------------------------------------------------------------------------------
|
22 | void init(void); //Funktion zum Initialisieren der Ports
|
23 | void debounce (uint8_t *, uint8_t); //Funktion zum Entprellen
|
24 |
|
25 | // ------------------------------------------------------------------------------------------
|
26 | // globale Variablen, die von Interruptroutinen verändert werden
|
27 | // ------------------------------------------------------------------------------------------
|
28 | volatile unsigned long ulCurrentCounterTimer0G=0; // enthält den aktuellen Wert des laufenden Timers 0 in Datenticks
|
29 | volatile unsigned long ulSecondCounter0G = 0; // enthält (annähernd) die Sekundenanzahl des Timers
|
30 | volatile unsigned char zeitmerker = 0; // Zeitmerker für den Vergleich, ob Zeit schon abgelaufen ist
|
31 |
|
32 | // ------------------------------------------------------------------------------------------
|
33 | // globale Variablen
|
34 | // ------------------------------------------------------------------------------------------
|
35 |
|
36 | /*
|
37 | * Timer 0 Overflow Interrupt
|
38 | */
|
39 | ISR(TIMER0_OVF_vect)
|
40 | {
|
41 | // --------------------------------------------------------------------------------------------
|
42 | // Bei jedem Overflow wird the TimerCounter um 256 (Ticks) inkrementiert.
|
43 | // Nach ca. 1 Sekunde wird der Sekundenzähler erhöht
|
44 | //---------------------------------------------------------------------------------------------
|
45 | ulCurrentCounterTimer0G+=256; //bei jedem overflow wird der Timer um 256 inkrementiert
|
46 |
|
47 | if (ulCurrentCounterTimer0G>=COUNTER_INCS_PER_SECOND_T0)
|
48 | {
|
49 | //es ist eine Sekunde vergangen, Sekundenzähler erhöhen
|
50 | ulSecondCounter0G++;
|
51 | zeitmerker = ulSecondCounter0G;
|
52 |
|
53 | // den Counter und den Tickzähler wieder zurücksetzen
|
54 |
|
55 | TCNT0 = 0; //Counter wird zurückgesetzt, der Preload Wert wird nicht ausgerechnet (Zeit, die der TC zu groß ist)
|
56 | ulCurrentCounterTimer0G = 0; //Tickzähler wird zurückgesetzt
|
57 | }
|
58 | }
|
59 |
|
60 | // Das Hauptprogramm (Einsprungpunkt)
|
61 | int main()
|
62 | {
|
63 | // Ports und Interrupts initialisieren
|
64 | init();
|
65 |
|
66 | while(1)
|
67 | {
|
68 | // ----------------------------------------------------------------------------------------
|
69 | // in der Hauptschleife des Programmes werden die Taster eingelesen
|
70 | // ----------------------------------------------------------------------------------------
|
71 |
|
72 | // den Taster abfragen, Funktion kehrt zurück, wenn der Status stabil ist (Entprellung)
|
73 | debounce( (uint8_t*)&PINB, (1<<Taster) );
|
74 |
|
75 | if ( !(PINB & (1 << Taster)) ) //frägt den Zustand des Tasters ab
|
76 | {
|
77 | PORTB |= (1<< LED ); //PB1 an dem die LED hängt anschalten
|
78 | TCCR0 |= (1<<CS01); //Den Timer starten
|
79 | }
|
80 |
|
81 | if ( PINB & (1 << LED) ) //frägt den Zustand des Ausganges der LED ab
|
82 | {
|
83 | if (zeitmerker>=25)
|
84 |
|
85 | {
|
86 | PORTB &= ~(1<< LED ); //PB1 an dem die LED hängt ausschalten
|
87 |
|
88 | // --------------------------------------------------------------------------------------
|
89 | // Timer stoppen und Rücksetzen
|
90 | // --------------------------------------------------------------------------------------
|
91 | TCCR0 &= ~(1<<CS01); //Den Timer stoppen
|
92 | ulSecondCounter0G = 0;
|
93 | ulCurrentCounterTimer0G=0;
|
94 | zeitmerker=0;
|
95 | TCNT0 = 0;
|
96 | }
|
97 |
|
98 | else
|
99 | {
|
100 | // den Taster abfragen, Funktion kehrt zurück, wenn der Status stabil ist (Entprellung)
|
101 | debounce( (uint8_t*)&PINB, (1<<Taster) );
|
102 |
|
103 | if ( !(PINB & (1 << Taster)) ) //frägt den Zustand des Tasters ab, prüft ob dieser wieder gedrückt wird für Abbruch
|
104 |
|
105 | {
|
106 | PORTB &= ~(1<< LED ); //PB1 an dem die LED hängt ausschalten
|
107 |
|
108 |
|
109 | // --------------------------------------------------------------------------------------
|
110 | // Timer stoppen und Rücksetzen
|
111 | // --------------------------------------------------------------------------------------
|
112 | TCCR0 &= ~(1<<CS01); //Den Timer stoppen
|
113 | ulSecondCounter0G = 0;
|
114 | ulCurrentCounterTimer0G=0;
|
115 | zeitmerker=0;
|
116 | TCNT0 = 0;
|
117 |
|
118 | }
|
119 |
|
120 | }
|
121 | }
|
122 | }
|
123 | }
|
124 |
|
125 | /*
|
126 | * Funktion init(): Initialisierung des µC
|
127 | */
|
128 | void init(void)
|
129 | {
|
130 | // --------------------------------------------------------------------------------------------
|
131 | // PORTB konfigurieren
|
132 | //
|
133 | // B0 --> Eingang für Taster
|
134 | // B1 --> Ausgang für LED
|
135 | // --------------------------------------------------------------------------------------------
|
136 | DDRB = 0x00;
|
137 | DDRB |= (1 << DDB1) ; // B1 (Transistor) (LED) als Ausgang deklarieren, Rest (und damit PB0) Eingänge
|
138 | PORTB |= (1<<PB0); // internen Pull-Up an PB0 aktivieren //
|
139 |
|
140 |
|
141 | // --------------------------------------------------------------------------------------------
|
142 | // Timer 0 (8-Bit)
|
143 | // --------------------------------------------------------------------------------------------
|
144 | TCCR0 &= ~(1<<CS01); //Timer0 zunächst gestoppt, es wird mit einem Prescaler von 8 gearbeitet
|
145 | TCNT0 = 0; // Counter auf 0 initialisieren
|
146 | TIMSK |= (1<<TOIE0); // Bei overflow wird timer interrupt 0 ausgelöst
|
147 |
|
148 | sei(); // setzt globales Interrupt Enable Bit
|
149 | return;
|
150 | }
|
151 |
|
152 | /*
|
153 | * Funktion debounce(): Funktion zum entprellen von Tasten, Schalter, etc
|
154 | * "Warteschleifenvariante mit Maske und Pointer (nach Christian Riggenbach)"
|
155 | * gefunden auf microcontroller.net
|
156 | */
|
157 | void debounce( uint8_t *port, uint8_t maske )
|
158 | {
|
159 | uint8_t port_puffer;
|
160 | uint8_t entprellungs_puffer;
|
161 |
|
162 | for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; )
|
163 | {
|
164 | entprellungs_puffer<<=1;
|
165 | port_puffer = *port;
|
166 | _delay_us(150);
|
167 | if( (*port & maske) == (port_puffer & maske) )
|
168 | {
|
169 | entprellungs_puffer |= 0x01;
|
170 | }
|
171 | }
|
172 | }
|