Den Multiplex in der ISR ist in Ordnung. Der muss dort sein, damit er
sauber und regelmässig läuft. Aber der Rest gehört nicht dorthin.
(Und den Multiplex macht man Codetechnisch auch anders. Ersetzte deine
switch-cases durch Arrayzugriffe, wobei du bereits in der Funktion, die
eine Zahl an den Multiplex übergibst, die Umformung auf die 7-Segment
Codes machst.
Und noch was:
In einer ISR hast du weder cli() noch sei()!
Das ist ganz wichtig, weil du verhindern musst, dass sich ISR Aufrufe
ineinander schachteln. Der sei() in menu() wird wahrscheinlich der Punkt
sein, warum dir alles den Bach runter geht.
Kurz und gut. dein ganzer Programaufbau stimmt nicht.
du brauchst eine ISR die, sagen wir mal 300 mal in der Sekunde
aufgerufen wird. Die genaue Anzahl ist nicht so wichtig. Es darf nur
nicht zu wenig sein, sonst blinkt die Anzeige. Die ISR sieht dann so
aus:
1 | volatile uint8_t SegPattern[3];
|
2 | uint8_t SegIndex;
|
3 |
|
4 | ISR(.....)
|
5 | {
|
6 | PORTD &= ~((1<<PD0) | (1<<PD1) | (1<<PD2) );
|
7 |
|
8 | SegIndex++;
|
9 | if( SegIndex == 3 )
|
10 | SegIndex = 0;
|
11 |
|
12 | PORTC = SegPattern[SegIndex];
|
13 |
|
14 | if( SegPattern == 0 )
|
15 | PORTD |= (1<<PD0);
|
16 | else if( SegPattern == 1 )
|
17 | PORTD |= (1<<PD1);
|
18 | else
|
19 | PORTD |= (1<<PD2);
|
20 | }
|
Das ist deine Multiplexroutine! Solange die ISR von einem Timer
regelmässig aufgerufen wird, zeigt die alles als 3-stelliges 'Muster'
an, was auch immer im Array steht. zb das Leuchtmuster, welches eine
andere Funktion anhand einer Dezimalzahl da reinstellt
1 | uint8_t digitPattern[] =
|
2 | { 0b10010000, // 0
|
3 | 0b11010111, // 1
|
4 | 0b10100010, // 2
|
5 | 0b10000110, // 3
|
6 | 0b11000101, // 4
|
7 | 0b10001100, // 5
|
8 | 0b10001000, // 6
|
9 | 0b11010110, // 7
|
10 | 0b10000000, // 8
|
11 | 0b10000100, // 9
|
12 | };
|
13 |
|
14 | void puti( uint8_t i )
|
15 | {
|
16 | SegPattern[2] = i % 10;
|
17 | i /= 10;
|
18 | SegPattern[1] = i % 10;
|
19 | i /= 10;
|
20 | SegPattern[0] = i;
|
21 | }
|
Wann immer du einen Zahlenwert ausgeben willst, rufst du die Funktion
puti() auf, die dann die Zahl für die Multiplexroutine aufbereitet. Die
Multiplexroutine zeigt die dann an, solange bis mittels puti etwas
anderes ausgegeben wird.
Und das ist alles was in den ISR passiert.
Im Sekundentakt setzt du dir noch ein Flag, welches dann in der
Hauptschleife ausgewertet wird und zb eine Messung anleiert.
1 | volatile uint8_t performMeasurement;
|
2 |
|
3 | ISR(TIMER1_COMPA_vect)
|
4 | {
|
5 | PORTB ^= (1<<PB3);
|
6 | performMeasurement = 1;
|
7 | }
|
8 |
|
9 |
|
10 | int main()
|
11 | {
|
12 | ...
|
13 |
|
14 | puti( 0 );
|
15 |
|
16 | sei();
|
17 |
|
18 | while( 1 ) {
|
19 |
|
20 | if( performMeasurement )
|
21 | {
|
22 | performMeasurement = 0;
|
23 |
|
24 | // ADC abfragen
|
25 | }
|
26 |
|
27 | // Menüsteuerung
|
28 | // und Auswahl des Wertes, der angezeigt werden soll
|
29 | // der jeweilige Wert wird mittels puti an die Anzeige
|
30 | // gegeben.
|
31 | }
|
32 | }
|
Edit: puti müsste man noch erweitern, damit die den Kommapunkt an der
jeweilige Stelle mit einkodiert wird.