Na ja, so schwer ist das wirklich nicht.
Da gibt es viele Strategien, die man einsetzen kann.
Kommt auch darauf wann, wozu das gut sein soll, bzw.
wie dein Signal konkret aussieht.
Eine Möglichkeit ist zb.:
Das schwierigste ist es wohl, 1 Sekunde abzumessen.
Dazu benutzt du einen Timer, der zb. alle 10ms einen
Interrupt (Overflow oder einen CTC Interrupt) auslöst.
In der ISR passiert dann erstaunlich wenig:
Einen Zähler erhöhen. Dieser Zähler wird im Hauptprogramm
ständig abgefragt, ob er schon 100 erreicht hat. Da die ISR
alle 10ms aufgerufen wird, ist 1 Sekunde vergangen wenn der
Zähler 100 erreicht hat. Dadurch geht es dann im Hauptprogramm
weiter.
Das Hauptprogramm wartet in einer Schleife, bis der Zähler
die 100 erreicht hat. Gleichzeitig überprüft sie innerhalb
der Schleife ständig, ob der Eingangspin noch immer 1 ist.
Ist er das nicht -> dann hat das Signal gewechselt.
Das wird dann vermerkt und der Timer kann wieder angehalten
werden.
Konnte aber die Schleife den Zähler bis 100 durchlaufen
lassen (sprich: Ist 1 Sekunde vergangen) und es wurde keine
0 am Eingang gesehen, dann wahr wohl das Signal die ganze Zeit
auf 1
In Pseudocode
1 | volatile uint8_t TimeCounter;
|
2 |
|
3 | ISR( .... )
|
4 | {
|
5 | TimeCounter++;
|
6 | }
|
7 |
|
8 | uint8_t CheckInput()
|
9 | {
|
10 | uint8_t InputDown;
|
11 |
|
12 | TimeCounter = 0;
|
13 |
|
14 | // hier kommt die Timer Initialisierung
|
15 | // so dass der Timer mit der richtigen Frequenz zählt
|
16 | // und regelmässig einen Interrupt auslöst
|
17 |
|
18 | ...
|
19 |
|
20 |
|
21 | InputDown = 0;
|
22 | while( TimeCounter < 100 ) {
|
23 | if( PINxx & ( 1 << Pxx ) == 0 ) {
|
24 | InputDown = 1;
|
25 | break;
|
26 | }
|
27 | }
|
28 |
|
29 | // Timer wieder stoppen
|
30 |
|
31 | ...
|
32 |
|
33 | // das wars
|
34 | return InputDown;
|
35 | }
|