Forum: Mikrocontroller und Digitale Elektronik Steigende Flanke Attiny2313


von Karl (Gast)


Lesenswert?

Hallo,
ich möchte gerne eine Flankenerkennung am Attiny2313 machen. Leider habe 
ich nicht allzuviel Ahnung. Deswegen möchte ich zunächst einfach am Pin 
5 (PA0) die Steigende Flanke erkennen und am Pin 12 (PB0) eine LED zum 
leuchten bringen. Diese soll dann mit delay für 5 sekunden leuchten und 
dann wieder ausgehen.
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
// ******************************************
8
// Hauptprogramm
9
// ******************************************
10
int main (void){
11
  programm();
12
    return 0;
13
} // Ende Hauptprogramm (Main)
14
15
void programm()
16
{
17
 //********************************************
18
  // Initialisierung von Variablen und Ausgängen
19
  //********************************************
20
  DDRA = 0x00; // PortA als Eingang deklarieren
21
  PORTA=0x00; //Ports auf LOW schalten
22
  DDRB = 0xff; // PortB als Ausgang deklarieren
23
  PORTB = 0x00; // Ports auf LOW schalten
24
25
  while(1){
26
    if (PINA & ( 1 << PA0 )){
27
    PORTB = 0b00000001;
28
    _delay_ms(5000);
29
  }
30
  else{
31
    PORTB = 0b00000000;
32
  }
33
  }
34
}

also das mit dem leuchten funktioniert nur zum teil.
Auch wenn ich an Pin 5 Kein Signal anlege, geht die LED an.
Aber überhaupt nicht berücksichtig ist die Steigende Flanke, da ich 
absolut keine Ahnung habe, wie ich das machen soll.

Kann mir da jemand einen Hinweis geben? Auch dazu, warum die LED sonst 
immer angeht, obwohl kein Signal anlieg?

Karl

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Karl schrieb:
> Aber überhaupt nicht berücksichtig ist die Steigende Flanke, da ich
> absolut keine Ahnung habe, wie ich das machen soll.

eine steigende Flanke tritt auf, wenn ein Portpin vom vorherigen Zustand 
"low" auf den neuen Zustand "high" wechselt. Das läßt sich bestimmt auch 
irgendwie algorithmisch formulieren ....

von Karl (Gast)


Lesenswert?

Das habe ich ja schon gemacht, indem ich abgefragt habe, ob der Pin High 
ist. aber wenn ihc den Pin High lassen würde, würde der Ausgang ja auch 
wieder auf ein neues auf High gehen, ohne das der Eingangspin vorher auf 
low gegangen ist.

von Julian R. (tuefftler)


Lesenswert?

Eine Flanke ist eine Änderung von Zuständen, was du gemacht hast prüft 
das nicht!
Tipp: Bei einer Änderung, merkst du dir den alten Zustand und 
vergleichst ihn mit dem neuen, wenn sie unterschiedlich sind hast du ne 
Flanke!

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Habe es jetzt so versucht, dass ich eine Variable benutze, und diese 
beim Eingang bei der if-Abfrage mit abgefragt wird
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
// ******************************************
8
// Hauptprogramm
9
// ******************************************
10
int main (void){
11
  programm();
12
    return 0;
13
} // Ende Hauptprogramm (Main)
14
15
void programm()
16
{
17
 //********************************************
18
  // Initialisierung von Variablen und Ausgängen
19
  //********************************************
20
  DDRA = 0x00; // PortA als Eingang deklarieren
21
  PORTA=0x00; //Ports auf LOW schalten
22
  DDRB = 0xff; // PortB als Ausgang deklarieren
23
  PORTB = 0x00; // Ports auf LOW schalten
24
  int x;
25
26
  x = 1;
27
  while(1){
28
    if (PINA&(1<<PA0) && x==1){
29
    x = 0;
30
    PORTB = 0b00000001;
31
    _delay_ms(5000);
32
  }
33
  else{
34
    PORTB = 0b00000000;
35
  }
36
  }
37
}

das sehe ich aber als nicht sinnig, da ich x ja wieder irgendwann auf 1 
setzen muss. Mache ihc das direkt bei der else, macht das alles ja 
wieder keinen Sinn.
Auch ist immer noch das Problem, dass die LED einfach so leuchtet, 
obwohl an PIN 5 kein Signal anliegt.

von Julian R. (tuefftler)


Lesenswert?

Wie wärs damit:
1
while(1) {
2
  if( PINA&(1<<PA0) ){
3
    if( x==0 ) {
4
      portb = 0x01;
5
    }
6
    x=1;
7
  } else {
8
    x=0;
9
    portb=0x00;
10
}

von Karl (Gast)


Lesenswert?

Habe es so ausprobiert (Klingt auch logisch und macht meiner Meinung 
auch sinn), allerdings wenn Pin5 High bleibt, bleibt die LED auch am 
leuchten (obwohl sie (jetzt auf 2sec runtergesetzt) ausgehen sollte).
Karl

von Rolf Magnus (Gast)


Lesenswert?

Karl schrieb:
> Kann mir da jemand einen Hinweis geben? Auch dazu, warum die LED sonst
> immer angeht, obwohl kein Signal anlieg?

Was meinst du mit "kein Signal"? Wirklich, daß der Pin einfach offen 
ist? Dann "floatet" er, d.h. hat irgendeinen mehr oder weniger 
zufälligen Pegel. Wenn der Pin nicht high sein soll, mußt du ihn aktiv 
auf low ziehen, also auf 0V.

von Thomas (kosmos)


Lesenswert?

Beim Tiny26 gibt's dafür einen Interupts man kann einstellen ob dieser 
bei einer steigenden, fallenden oder jeder Flanke ausgelöst wird. Wird 
beim 2313 nicht anderst sein.

von Thomas (kosmos)


Lesenswert?

Ach ja eine häufige Fehlerquelle sind die aktivierten Pullups.

von Julian R. (tuefftler)


Lesenswert?

Karl schrieb:
> Habe es so ausprobiert (Klingt auch logisch und macht meiner
> Meinung
> auch sinn), allerdings wenn Pin5 High bleibt, bleibt die LED auch am
> leuchten (obwohl sie (jetzt auf 2sec runtergesetzt) ausgehen sollte).
> Karl

Dann musst du da wo x=1 gestzt wird deine Led wieder ausschalten!
Und du musst noch deine Wartezeit einbauen!

Thomas O. schrieb:
> Beim Tiny26 gibt's dafür einen Interupts man kann einstellen ob
> dieser
> bei einer steigenden, fallenden oder jeder Flanke ausgelöst wird. Wird
> beim 2313 nicht anderst sein.

Das würde ich dir ebenfalls raten! Nimm einen Controller, der Pin change 
Interrupts hat und du brauchst beim auslösen nur prüfen, was sich 
verändert hat.

Julian

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Karl schrieb:
> int x;

C erlaubt (im Gegensatz zu alten Basic Dialekten ;-) durchaus auch 
Variablennamen mit mehr als einem Buchstaben. Anstelle "x" kann man eine 
Varialble auch "sprechend", zum Beispiel "alter_zustand" nennen. Das ist 
direkt "flüssig" im Programm zu lesen, man weiß sofort was gemeint ist.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl schrieb:

> das sehe ich aber als nicht sinnig,

Die Sache mit der Hilfsvariablen ist an und für sich ok. Nur setzt du 
sie IMHO ungeschickt ein.

Springender Punkt, wie schon erwähnt, bei einer Flankenerkennung ist es, 
dass man die Veränderung des Pin-Zustands feststellt. Dazu musst du dir 
aber diesen Pinzustand merken, um ihn mit dem Zustand im nächsten 
Durchlauf durch die While Schleife vergleichen zu können. Zb so
1
uint8_t pinZustandAlt;
2
uint8_t pinZustandNeu;
3
4
int main()
5
{
6
....
7
8
  pinZustandAlt = ( PINA & ( 1 << PA0 ) );
9
10
  while( 1 )
11
  {
12
13
    pinZustandNeu = ( PINA & ( 1 << PA0 ) );
14
15
    if( pinZustandAlt != pinZustandNeu )
16
    {
17
      pinZustandAlt = pinZustandNeu;
18
19
      // Es gab eine Veränderung am Pin
20
      ...
21
22
    }
23
  }
24
}

Jetzt willst du aber nicht irgendeine Veränderung (es gibt ja 2 
derartige Möglichkeiten), sondern eine bestimmte. Du willst den Wechsel 
von Low auf High. Wenn dieser Wechsel vorliegt, dann muss daher der neue 
Pin Zustand auf High lauten. Oder was gleichwertig ist, der alte muss 
auf Low lauten. Daher
1
uint8_t pinZustandAlt;
2
uint8_t pinZustandNeu;
3
4
int main()
5
{
6
....
7
8
  pinZustandAlt = ( PINA & ( 1 << PA0 ) );
9
10
  while( 1 )
11
  {
12
13
    pinZustandNeu = ( PINA & ( 1 << PA0 ) );
14
15
    if( pinZustandAlt != pinZustandNeu )
16
    {
17
      pinZustandAlt = pinZustandNeu;
18
19
      // Es gab eine Veränderung am Pin
20
      // welche war es denn?
21
      if( pinZustandNeu )
22
      {
23
        // Es war ein Wechsel von Low auf High
24
         ...
25
      }
26
    }
27
  }
28
}


In der Praxis wird man noch 1 Variable einsparen und keine 5 Sekunden 
delays in einem Rutsch machen. Ich hab sie nur angeführt, um das Prinzip 
sauberer formulieren zu können.

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

Habe es erst mal so gemacht
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
5
#include <util/delay.h>
6
7
8
// ******************************************
9
// Hauptprogramm
10
// ******************************************
11
int main (void){
12
  programm();
13
    return 0;
14
} // Ende Hauptprogramm (Main)
15
16
void programm(){
17
  //********************************************
18
  // Initialisierung von Variablen und Ausgängen
19
  //********************************************
20
  DDRA = 0x00; // PortA als Eingang deklarieren
21
  PORTA=0x00; //Ports auf LOW schalten
22
  DDRB = 0xff; // PortB als Ausgang deklarieren
23
  PORTB = 0x00; // Ports auf LOW schalten
24
  int x=0;
25
26
27
  while(1){
28
    if (PINA&(1<<PA0)){
29
    if(x==0){
30
        PORTB = 0x01;
31
        _delay_ms(2000);
32
    }
33
    x=1;
34
    PORTB = 0x00;
35
    }
36
    else{
37
      PORTB = 0x00;
38
    x = 0;
39
    }
40
  }
41
}

komisch war, dass die LED auch zwischendurch einfach so anging, obwohl 
ich ncihts gemacht habe. Daher habe ihc einen 10K Widerstand zwischen 
Pin5 und GND gesetzt. Jetzt funktioniert es fast. Aber wenn ich Pin5 
länger auf High lasse und dann wieder auf Low setze, geht die LED auch 
an.

Werde mir aber wohl doch mal die sache mit den Interrupts ansehen. Das 
was ich bisher gesehen habe, war aber so mega kompliziert.
schonmal recht dank an alle

Karl

von Dietrich L. (dietrichl)


Lesenswert?

@Karl:
Woher kommt denn Dein Signal? Wenn das ein mechanischer Taster oder 
Schalter ist, hast Du Prellungen, d.h. beim Einschalten kommen mehrere 
schnelle Änderungen. Die müssen per HW oder SW unterdrückt werden, sonst 
wird das nichts.

Gruß Dietrich

von Karl (Gast)


Lesenswert?

Ahso,
habe das ganze zum Testen immer auf ein STeckbrett. Da habe ich ein 
Kabel vom VCC nach Pin 5 reingesteckt.
das ist natürlich sehr gut möglich, dass ich beim rausziehen wieder am 
kontakt rangekommen bin. Ziehe ich das KAbel ganz schnell raus, passiert 
auch nichts.
Also werde ich mir das mit den Interrupts angucken und bei einer 
fallenden Flanke eine verzögerung einsetzen, sodass das nicht mehr 
vorkommen dürfte.

von Karl (Gast)


Lesenswert?

Also im prinzip so
1
  while(1){
2
    if (PINA&(1<<PA0)){
3
    if(x==0){
4
        PORTB = 0x01;
5
        _delay_ms(2000);
6
    }
7
    x=1;
8
    PORTB = 0x00;
9
    }
10
    else{
11
      PORTB = 0x00;
12
    _delay_ms(50);
13
    x = 0;
14
    }
15
  }

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.