Forum: Mikrocontroller und Digitale Elektronik Flankenauswertung


von Tobi T. (freitagvormittag)


Lesenswert?

Hallo zusammen,

ich möchte in einem Atmega16 die Flanken an mehreren Input Pins 
auswerten (sowohl positive Flanke als auch negative Flanke). Entprellen 
möchte ich erst mal nicht betrachten. Laufzeit spielt auch kein Problem. 
Das Programm ist relativ simpel
1
 
2
DDRA  = 0;    // alles Eingänge
3
PORTA = 0;
4
bla 
5
bla
6
while(1)
7
{
8
PINA_akt = PINA;       // aktueller Portzustand
9
PosFlankePinA0 = ((PINA_akt & (1<<PINA0)) ==0) && ((PINA_Backup & (1<<PINA0)) !=0);   // PosFlanke des PinA1
10
NegFlankePinA0 = ((PINA_akt & (1<<PINA0)) !=0) && ((PINA_Backup & (1<<PINA0)) ==0);   // NegFlanke des PinA1
11
PINA_Backup = PINA_akt;       // Portzustand im letzten Zyklus
12
bla
13
bla
14
bla
15
}
Soweit, so gut. Funktion ist ok.
Nur sieht das alles nicht besonders schön aus. Und wenn ich mir das 
Disassembly ansehe, klappen sich mir die Fußnägel hoch.

Mein nächster Versuch war:
1
while(1)
2
{
3
PINA_akt = PINA;
4
PosFlankenPortA = (!PINA_akt & PINA_Backup);   // PosFlanke aller PortA Pins
5
NegFlankenPortA = (PINA_akt & !PINA_Backup);   // NegFlanke aller PortA Pins
6
PINA_Backup = PINA_akt;
7
bla

Dummerweise geht das gar nicht.
Woran liegt das? Wo ist mein Denkfehler?
Und gibt es noch eine andere Möglichkeit, das Ganze in ein bis zwei 
Zeilen abzufertigen?

Danke, Tobi

von Karl H. (kbuchegg)


Lesenswert?

Tobi Tobi schrieb:

> Dummerweise geht das gar nicht.

Logisch geht das nicht.

Du musst zwischen logischen Operationen (TRUE FALSE) und binären 
Operationen unterscheiden lernen und wann welche angebracht ist.

> PosFlankenPortA = (!PINA_akt & PINA_Backup);   // PosFlanke aller PortA Pins

PINA_Backup wir zwar binär genommen, aber PINA_akt wird durch das ! zu 
einem boolschen Wert degradiert (TRUE FALSE). Und schon sind die 
Einzelbits futsch

> Und gibt es noch eine andere Möglichkeit, das Ganze in ein bis zwei
> Zeilen abzufertigen?

Nimm einfach das XOR zwischen PINA_akt und PINA_Backup

   Changes = PINA_akt ^ PINA_Backup;

jedes 1 Bit in Changes sagt dir, das sich die beiden Originale an genau 
dieser Bitposition unterscheiden.
Triffst du bei der Auswertung auf das 1 Bit, dann siehst du nach, ob in 
PINA_akt an dieser Bitposition eine 0 oder eine 1 drinnen steht. Wenn es 
einen UNterschied zwischen PINA_Backup und PINA_akt an der Bitposition n 
gibt UND PINA_akt jetzt 1 ist, dann muss logischerweise in PINA_Backup 
an dieser Bitposition eine 0 gewesen sein. D.h. der Pin hat einen 0->1 
Übergang gemacht. Steht aber in PINA_akt ein 0 Bit an dieser POsition, 
dann kann das nur ein 1->0 Übergang gewesen sein.
D.h. Changes sagt dir, ob sich was geändert hat. Und PINA_akt sagt dir, 
wie es sich verändert.

>
> Danke, Tobi

von nix und n. (nixundnul)


Angehängte Dateien:

Lesenswert?

in der angehängten .c ist was drin. Dann sieht das so aus:
if(flm(test(PINB,4),&mrkr)) // mrkr ist ein Byte als Flankenmerker; 7Bit 
verschwendet, ist halt so.
Es sind auch gleich ein paar Zeitgeber mit dabei, ein Teil davon wird 
zyklisch aufgerufen und gibt die Zeit, der andere Teil ist Start und 
Ende derselben. Ich habe mal ein paar Jahre SPS programmiert, und da 
brauche ich auch auf gcc die quasiparallele Verarbeitung von 
Bit-Merkern. Lizenz: Wenn Du mein Programm verstanden hast, dann darfst 
Du es verwenden. 8-)

von nix und n. (nixundnul)


Lesenswert?

sorry, in meinem plc.c kommt noch ein "test" vor. Naja für mich ist es 
logischer zu schreiben { set(PORTB,2); } als wie das, was man sonst so 
in Beispielen sieht.

#define set(a,b) (a |= (1<<b))
#define clear(a,b) (a &= ~(1 << b))
#define test(a,b) (a & (1 << b))
#define testn(a,b) (~a & (1 << b))

von Peter D. (peda)


Lesenswert?

1
PosFlankePinA0 = PINA_akt & ~PINA_Backup & 1<<PINA0;   // PosFlanke des PinA1
2
NegFlankePinA0 = ~PINA_akt & PINA_Backup & 1<<PINA0;   // NegFlanke des PinA1

Peter

von Tobi T. (freitagvormittag)


Lesenswert?

Hallo Peter, hallo nix und nul,

vielen Dank für eure Antworten.

! --> binäres nicht
~ --> bitweises nicht

Dann ist mir auch klar, warum
1
PosFlankenPortA = (!PINA_akt & PINA_Backup)
nicht funktionieren kann.

Ich habe es jetzt so gelöst
1
PINA_akt = PINA;
2
u8PosFlanken = ~PINA_akt & PINA_Backup;
3
u8NegFlanken = PINA_akt & ~PINA_Backup;
4
PINA_Backup = PINA_akt;

Wieder was gelernt.

Danke für eure Hilfe
Gruß Tobi

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.