1 | #include <inttypes.h> // uint8_t usw.
|
2 | #include <avr/io.h>
|
3 | #include <avr/interrupt.h> // Interrupts
|
4 | #include <avr/eeprom.h> // EEPROM Zugriffe
|
5 |
|
6 | #define EEPROM __attribute__ ((section (".eeprom"))) // für EEPROM-Zugriffe
|
7 |
|
8 | #ifndef F_CPU
|
9 | #warning "F_CPU war noch nicht definiert, wird nun mit 1000000 definiert"
|
10 | #define F_CPU 1000000UL
|
11 | #endif
|
12 | #include <util/delay.h>
|
13 |
|
14 |
|
15 |
|
16 | // Welcher Port an welchem Segement:
|
17 | #define segm_a PD0
|
18 | #define segm_b PD1
|
19 | #define segm_c PD2
|
20 | #define segm_d PD3
|
21 | #define segm_e PD4
|
22 | #define segm_f PD5
|
23 | #define segm_g PD6
|
24 | #define segm_p PD7
|
25 |
|
26 | // Welcher Port an welcher Digit:
|
27 | #define digit1 PB0 // Einer
|
28 | #define digit2 PB1 // Zehner
|
29 | #define digit3 PB2 // Hunderter
|
30 |
|
31 | // An welchem Port sind Taster
|
32 | #define btn_up PC3
|
33 | #define btn_down PC4
|
34 | #define btn_start PC5
|
35 |
|
36 | // Ports definieren
|
37 | #define port_segment PORTD
|
38 | #define port_digit PORTB
|
39 | #define port_keys PORTC
|
40 | #define dir_segment DDRD
|
41 | #define dir_digit DDRB
|
42 | #define dir_keys DDRC
|
43 | #define pin_keys PINC
|
44 |
|
45 | // Definiert, welche Segmente für die einzelnen Zahlenwerte aufleuchten sollen. LOW-Aktiv
|
46 | #define sign0 (1 << segm_g) | (1 << segm_p)
|
47 | #define sign1 (1 << segm_a) | (1 << segm_d) | (1 << segm_e) | (1 << segm_f) | (1 << segm_g) | (1 << segm_p)
|
48 | #define sign2 (1 << segm_c) | (1 << segm_f) | (1 << segm_p)
|
49 | #define sign3 (1 << segm_e) | (1 << segm_f) | (1 << segm_p)
|
50 | #define sign4 (1 << segm_a) | (1 << segm_d) | (1 << segm_e) | (1 << segm_p)
|
51 | #define sign5 (1 << segm_b) | (1 << segm_e) | (1 << segm_p)
|
52 | #define sign6 (1 << segm_b) | (1 << segm_p)
|
53 | #define sign7 (1 << segm_d) | (1 << segm_e) | (1 << segm_f) | (1 << segm_g) | (1 << segm_p)
|
54 | #define sign8 (1 << segm_p)
|
55 | #define sign9 (1 << segm_e) | (1 << segm_p)
|
56 |
|
57 | uint8_t num[] = { sign0, sign1, sign2, sign3, sign4, sign5, sign6, sign7, sign8, sign9 };
|
58 | uint16_t startwert EEPROM; // Speicherplatz für letzten Startwert im EEPROM
|
59 | volatile uint16_t display_value=0; // Startwert.
|
60 | volatile uint8_t run=0; // =0 Counter Stop; =1 Counter läuft
|
61 | volatile uint8_t key_up=0, // Puffer für Tastendrücke
|
62 | key_down=0,
|
63 | key_start=0;
|
64 |
|
65 |
|
66 | void ausgabe (uint16_t zahl)
|
67 | {
|
68 | uint16_t output = zahl;
|
69 | uint16_t warten = 50; // Enable Zeit für einzelnes Segment. Zeit in der LED leuchten
|
70 |
|
71 |
|
72 | // Hunderter-Dezimalstelle
|
73 | if (zahl >= 100)
|
74 | {
|
75 | port_segment = num[output/100]; // Zahlenwert darstellen
|
76 | port_digit = (1 << digit2) | (1 << digit1); // 3. Digit Ein
|
77 | _delay_ms(warten); // LEDs müssen gewisse Zeit leuchten
|
78 | port_digit = (1 << digit3) | (1 << digit2) | (1 << digit1); // 3. Digit HIGH
|
79 | }
|
80 | output = output % 100;
|
81 |
|
82 |
|
83 | // Zehner-Dezimalstelle
|
84 | if (zahl >= 10)
|
85 | {
|
86 | port_segment = num[output/10]; // Zahlenwert darstellen
|
87 | port_digit = (1 << digit3) | (1 << digit1); // 2. Digit Ein
|
88 | _delay_ms(warten); // LEDs müssen gewisse Zeit leuchten
|
89 | port_digit = (1 << digit3) | (1 << digit2) | (1 << digit1); // 2. Digit HIGH
|
90 | }
|
91 | output = output % 10;
|
92 |
|
93 | // einer Dezimalstelle
|
94 | port_segment = num[output]; // Zahlenwert darstellen
|
95 | port_digit = (1 << digit3) | (1 << digit2); // 1. Digit Ein
|
96 | _delay_ms(warten); // LEDs müssen gewisse Zeit leuchten
|
97 | port_digit = (1 << digit3) | (1 << digit2) | (1 << digit1); // 1. Digit HIGH
|
98 |
|
99 | sei(); // Interrupts zulassen
|
100 | }
|
101 |
|
102 |
|
103 | ISR (TIMER0_OVF_vect)
|
104 | {
|
105 | cli(); // Interrupts nicht zulassen
|
106 | ausgabe (display_value); // Zahl darstellen
|
107 | }
|
108 |
|
109 |
|
110 |
|
111 | ISR (TIMER2_OVF_vect)
|
112 | {
|
113 | cli(); // Interrupts nicht zulassen
|
114 |
|
115 | if (!(pin_keys & (1 << btn_up))) // Up-Taste gedrückt
|
116 | key_up++;
|
117 |
|
118 | if (!(pin_keys & (1 << btn_down))) // Down-Taste gedrückt
|
119 | key_down++;
|
120 |
|
121 | if (!(pin_keys & (1 << btn_start))) // Start-Taste gedrückt
|
122 | key_start++;
|
123 |
|
124 | sei(); // Interrupts zulassen
|
125 | }
|
126 |
|
127 |
|
128 | ISR (TIMER1_COMPA_vect)
|
129 | {
|
130 | cli(); // Interrupts nicht zulassen
|
131 | TCNT1H=0; // Timerstand zurücksetzen
|
132 | TCNT1L=0;
|
133 |
|
134 | //display_value -= run;
|
135 | display_value--;
|
136 | }
|
137 |
|
138 | int main(void)
|
139 | {
|
140 |
|
141 | dir_digit = (1 << digit1) | (1 << digit2) | (1 << digit3); // Ausgänge, für Digits
|
142 | dir_segment = 0xFF; // alles Ausgänge, für Segmente
|
143 | dir_keys &= ~(1 << btn_up) & ~(1 << btn_down) & ~(1 << btn_start);// Eingänge für Tasten
|
144 | port_keys |= (1 << PC3) | (1 << PC4) | (1 << PC5);
|
145 |
|
146 | // Timer für Displayrefresh
|
147 | TCCR0 |= (1<<CS01) | (1<<CS00); //8-Bit Timer, Timer clock = system clock/64
|
148 | TIFR |= (1<<TOV0); //Clear TOV0 Timer/Counter Overflow Flag. clear pending interrupts
|
149 | TIMSK |= (1<<TOIE0); //Enable Timer0 Overflow Interrupt
|
150 |
|
151 | // Timer für Tastenabfrage
|
152 | TCCR2 |= (1<<CS02); //8-Bit Timer, Timer clock = system clock/256
|
153 | TIFR |= (1<<TOV2); //Clear TOV2 Timer/Counter Overflow Flag. clear pending interrupts
|
154 | TIMSK |= (1<<TOIE2); //Enable Timer2 Overflow Interrupt
|
155 |
|
156 | // Timer für Sekundentakt
|
157 | OCR1A = 977; // 16Bit Timer Takt= 1MHz => 1.000.000/1024 = 976,56
|
158 | // Vergleichswert laden: 1 Sekunde
|
159 | TIMSK |= (1<<OCIE1A); // Interrupt wenn Timer Vergleichswert erreicht
|
160 |
|
161 | sei(); // Interrupts zulassen
|
162 |
|
163 | while (1)
|
164 | {
|
165 | if (key_up >= 30) // Up-Taste gedrückt
|
166 | {
|
167 | display_value++; // Wert +1
|
168 | if (display_value > 999) // Wenn Überlauf => Wert=0
|
169 | display_value = 1;
|
170 | key_up = 0; // Tastencounter leeren
|
171 | }
|
172 | if (key_down >= 30) // Down-Taste gedrückt
|
173 | {
|
174 | if (display_value <= 1) // Wenn Unterlauf => Wert=999
|
175 | display_value = 1000;
|
176 | display_value--; // Wert -1
|
177 | key_down = 0; // Tastencounter leeren
|
178 | }
|
179 |
|
180 | if (key_start >= 30) // Start-Taste gedrückt
|
181 | {
|
182 | key_start = 0; // Tastencounter leeren
|
183 | if (display_value == 0) // wenn angezeigter Wert = 0 und Start gedrückt => ermittler zuletzt verwendeten Startwert und setze diesen
|
184 | {
|
185 | display_value = eeprom_read_word(&startwert);
|
186 | }
|
187 | else
|
188 | {
|
189 | run ^= 1; // Wert XOR 1; => Start/Stop
|
190 | if (run) // Wenn Counter gestartet wird
|
191 | {
|
192 | if (display_value != eeprom_read_word(&startwert)) // wenn Start gedrückt und aktueller Startwert != letzter Startwert
|
193 | eeprom_write_word(&startwert, display_value); // dann speichere neuen Startwert
|
194 |
|
195 | TCNT1H=0; // Timerstand zurücksetzen, damit ab jetzt eine Sekunde zählt
|
196 | TCNT1L=0;
|
197 | TCCR1A = (1<<CS10)|(1<<CS12); // Timer mit Div 1024 starten
|
198 |
|
199 | }
|
200 | else // Counter angehalten
|
201 | {
|
202 | TCCR1A = 0; // Timer Stop
|
203 |
|
204 | }
|
205 | }
|
206 | }
|
207 |
|
208 | if (display_value == 0) // Timer abgelaufen
|
209 | {
|
210 | run = 0; // Stop
|
211 | }
|
212 | }
|
213 | }
|