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
intmain(void){
11
programm();
12
return0;
13
}// Ende Hauptprogramm (Main)
14
15
voidprogramm()
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
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 ....
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.
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!
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
intmain(void){
11
programm();
12
return0;
13
}// Ende Hauptprogramm (Main)
14
15
voidprogramm()
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
intx;
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.
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
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.
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.
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
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.
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_tpinZustandAlt;
2
uint8_tpinZustandNeu;
3
4
intmain()
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_tpinZustandAlt;
2
uint8_tpinZustandNeu;
3
4
intmain()
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.
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
@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
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.