Ich wärme diese Geschichte nochmal auf.
Grund: ich bekam heute eine Frage zu meinem obigen Quelltext, habe
die Mail mit der Frage aber dummerweise vor dem Beantworten
versehentlich gelöscht. Deshalb die Antwort über diesen
Umweg - wenn sich der Frager nochmal meldet, kann ich den Beitrag
gleich wieder löschen (falls nicht noch jemand hier antwortet...).
Die gekürzte Timerroutine sieht etwa so aus:
1 | ISR(TIMER0_OVF_vect)
|
2 | {
|
3 | if( bTSic1Running )
|
4 | {
|
5 | switch( nTimer0TSic1 )
|
6 | {
|
7 | // Anm. zu den Werten in den case-labels: siehe Ausgabe des
|
8 | // Programms calc_nTimer0_fuer_TSic.c
|
9 |
|
10 | case 4: // [ 0] Startbit
|
11 | break;
|
12 | case 12: // [ 1] upper byte bit 7
|
13 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<7);
|
14 | break;
|
15 | case 20: // [ 2] upper byte bit 6
|
16 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<6);
|
17 | break;
|
18 | case 27: // [ 3] upper byte bit 5
|
19 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<5);
|
20 | break;
|
21 | case 35: // [ 4] upper byte bit 4
|
22 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<4);
|
23 | break;
|
24 | case 43: // [ 5] upper byte bit 3
|
25 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<3);
|
26 | break;
|
27 | case 51: // [ 6] upper byte bit 2
|
28 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<2);
|
29 | break;
|
30 | case 59: // [ 7] upper byte bit 1
|
31 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<1);
|
32 | break;
|
33 | case 66: // [ 8] upper byte bit 0
|
34 | hbyteTSic1 |= (((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0)<<0);
|
35 | break;
|
36 | ...
|
37 | }
|
Die verlorene Frage bezog sich jetzt auf die Zuweisung im letzten
gezeigten case, und war sinngemäß etwa so (hoffe ich):
Wieso wird hier nochmal gegen 0 getestet, und dann nochmal
verschoben, anstatt gleich das Bitmuster aus der rechten Seite
für das |= zu verwenden?
Antwort: das liegt daran, daß jeweils ein Bit an der falschen
Stelle entsteht.
Die einzelnen case-Anweisungen beziehen sich auf jeweils den
soundsovielten Aufruf der Interruptroutine; das letzte case also
auf den 66 Aufruf.
Bei jedem dieser case wird genau ein Bit übernommen von einem
Pin, nämlich immer am Port PIN_TSIC1_DATA das Bit
PINNUMMER_TSIC1_DATA.
Ist PIN_TSIC1_DATA z.B. PINA (TSic angeschlossen an Port A)
und ist PINNUMMER_TSIC1_DATA z.B. 4 (angeschlossen an Pin 4 von
Port A), dann liefert PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA)
entweder den Wert 0b00010000, wenn das Bit gesetzt ist, und
0b00000000, wenn nicht - und zwar gleichermaßen in jedem
der case, egal um welchen Durchlauf es sich handelt.
Dementsprechend soll aber ein Bit im Ergebnis nicht immer an
derselben Stelle gesetzt werden, sondern bei case 12 das
höchste Bit 7, bei case 66 das unterste Bit 0, die
anderen entsprechend.
Deshalb bilde ich erst
((PIN_TSIC1_DATA & (1<<PINNUMMER_TSIC1_DATA))!=0),
das liefert statt z.B. 0b00010000 immer eine 0b00000001
(also das Ergebnis ins unterste Bit verschoben, unabhängig
von PINNUMMER_TSIC1_DATA) und mit <<0, <<1, <<2 etc. je
nach Nummer des Durchlaufs und damit je nach aktueller
Stelle im Ergebnis wird dann die 1 wieder entsprechend
weit nach links geschoben.
Beim Bit 0 ist das <<0 natürlich überflüssig, und nur
als Analogie zu den anderen Fällen mit <<1, <<2 etc. dabei.
Ich hoffe, das beantwortet die Frage. Sonst bitte nochmal
mailen; ich werde es nicht gleich wieder löschen :-)