Forum: Compiler & IDEs wie kann ich Flanken detektieren


von Andre Fischer (Gast)


Lesenswert?

Hi,

ich moechte folgendes erreichen:

Wenn an einem Port eine steigende UND eine fallende Flanke erkannt
wurde (also ein wechsel von 0 zu 1 und zurueck stattgefunden hat) soll
ein anderer Port auf High gehen (zum Beispiel eine LED anschalten)

Das ganze soll mit 7 Ports geschehen. Wie koennte ich das moeglichst
einfach realisieren?

von johnny.m (Gast)


Lesenswert?

1.: Port != Portpin
2.: Welcher µC, welche Sprache?
3.: Datenblatt und Tutorial schon gelesen?

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Andre,

die simplen Möglichkeiten, den Port mit den Sensoren periodisch
abzutasten und an den PED-Port schneller zu kopieren, als das Auge
gucken kann, das wirst Du schon verworfen haben.

Wenn's also schnell gehen soll, dann nimm einen Prozessor wie den
Atmega48, Atmega88, Atmega168 und benutze die "Pin Change
Interrupt"s.

Ciao
Wolfgang Horn

von Karl heinz B. (kbucheg)


Lesenswert?

Wie schnell sind die Signale an den Pins?

von Rolf (Gast)


Lesenswert?

Wenn Atmega (alle), dann "logic change" Interrupt aktivieren.
Funktioniert aber nur an INT0 und INT1 Pins.

>Das ganze soll mit 7 Ports geschehen.
Du meinst sicherlich 7 PINs.

Wenn du das softwäremäßig lösen willst:

Beispiel für Port B Pin 0 (8 Abfragen) und PORT C (8 LED):
#include <avr/io.h>

int main(void)
{
PORTB = 0;
DDRB  = 0;

PORTC = 0;
DDRC  = 0xFF;

unsigned char temp;
unsigned int i;
while (1)
{
temp = PINB;

//do somethin else
//...
//

if (temp != PINB) //wenn Änderung
 {
 for (i = 0x01; i <= 0x80; i = i << 1)
   {
   if ((temp & i) ^ (PINB & i))  //wenn Unterschied
    {
    if(PINB & i)    //wenn H-Input
     PORTC |= i;    //dann H-Output
    else
     PORTC &= ~i;    //L-Output
    }
   }
 }

}
return 0;
}

von Peter D. (peda)


Lesenswert?

Dazu gibts ne schnuckelige Lösung in der Codesammlung:

http://www.mikrocontroller.net/forum/read-4-310276.html#new


Peter

von Andre Fischer (Gast)


Lesenswert?

Hi,

ich hab nicht immer Zugang zum Netz deswegen kann ich jetzt erst
schreiben.

Also:

Ich hatte an einen ATMEGA8 gedacht.

Programmieren wuerde ich das ganze gern in c mit gcc und dem AVR
Studio.

Das Signal ist einige 100 (200 - 400 schaetze ich jetzt mal) kHz
schnell. (ich will eigentlich nichts anderes als testen ob das clock
pin [und diverse andere pins] wirklich etwas "rausbringen", das board
was ich testen will, also funktioniert. Mit dem µC will ich mir es
sparen immer erst einen oszi oder logic analyser anzuschliessen, da es
in dem Fall nicht darum geht zu sehen WAS raus kommt sondern nur OB
etwas rauskommt [wenn ja geh ich dann davon aus das es das richtige
ist.] Und da dachte ich eben ich versuche [eine] fallende und steigende
Flanke(n) zu erkennen)

Danke erstmal fuer die Antworten ich werde bei der naechsten
Gelegenheit anfangen rumzuprobieren.

von Karl heinz B. (kbucheg)


Lesenswert?

Würde ich so machen:

Ich benutze den externen Interrupt Eingang und konfiguriere
den auf steigende Flanke.

Wann immer ein Interrupt auftritt wird eine LED eingeschaltet.

Dann kommt da noch ein Timer ins Spiel, der in
regelmäßigen Intervallen die LED einfach wieder ausschaltet.

Fertig.
Ein kleiner 8-pin Tiny kann das wunderbar machen.
Je nach Typ, müsste man den eventuell in Assembler
programmieren. Ist aber kein Beinbruch, da die vorgeschlagene
Vorgehensweise in einem Programm mit deutlich weniger als
30 Anweisungen resultiert (da gehen je nach Typ mehr als die
Hälfte für den Aufbau der Interrupttabelle drauf).

von johnny.m (Gast)


Lesenswert?

Naja, Andre schreibt ja ganz oben was von '7 Ports', wobei ich davon
ausgehe (was ich oben ja auch schon zum Ausdruck gebracht habe), dass
Andre Ports und Portpins durcheinanderbringt. Also vermutlich 7
Portpins. Und da wirds mit nem 8-Pin-Tiny eng... Eher nen Tiny2313
(oder eben nen Mega8, an den Andre ja nach eigenem Bekunden auch schon
gedacht hat) und mit den Pin Change Interrupts rumspielen. Dann klappts
auch mit den 7 Signalen... Und ansonsten wie von Karl Heinz beschrieben:
Pin Change Interrupt schaltet ne LED ein und nach einer bestimmten Zeit
(lange genug, um durch das Auge wahrgenommen zu werden) wird sie wieder
ausgeschaltet.

von Karl heinz B. (kbucheg)


Lesenswert?

> '7 Ports'

Ooops. Diese Anforderung hatte ich schon verdrängt.
Dann wirds natürlich nichts mit nem 8-pinner.

von Andre Fischer (Gast)


Lesenswert?

Also erstmal JA ich meine 7 Portpins nicht Ports (sorry fuer dei
Verwechslung).

Das mit dem Pin change interrupts klingt auch ziemlich gut aber kann
ich das mit dem Mega8 macehn? (ich find im Datenblatt von dem kein
pcint). Also wenn ich mich nicht zu dumm anstelle (was ja aber gut sein
kann) dann bietet der Mega8 das nicht an.

Welcher AVR bietet ungefaehr das gleiche wie der Mega8 aber zusaetzlich
mindestens 7 Pins mit pin change interrupt?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Das mit dem Pin change interrupts klingt auch ziemlich gut aber
> kann ich das mit dem Mega8 macehn?

Nein, du brauchst seinen Nachfolger ATmega88 bzw. dessen Derivate
ATmega48 oder ATmega168.

von Andre Fischer (Gast)


Lesenswert?

Ich hab mir die Datenblaetter/das Datenblatt mal angesehn und da ist mir
aufgefallen das es nur 3 PCINT gibt, man kann zwar pin 0..7 zum beispiel
dem PCINT0 zuordnen aber dann wird der Interrupt ausgeloest wenn einer
der Pins ne Flanke hatte.

Wie kann ich aber an 7 Pins ueberpruefen ob es eine Flanke gab oder
nicht? (So wie es aussieht seh ich ja nur ab es an irgend einem Pin
zwischen 0..7 zum Beispiel eine Flanke gab, da weiss ich ja aber noch
nicht, an welchem und ob auch an mehreren oder nur einem...)

von johnny.m (Gast)


Lesenswert?

Dann musst Du in der ISR die entsprechenden Pins einlesen und abfragen,
welcher es war. Wichtig ist (bei den von Dir genannten
Signalfrequenzen), dass diese Abfrage direkt am Anfang der ISR
stattfindet, damit der tatsächliche Ist-Zustand wiedergegeben wird. Die
Taktfrequenz des µCs sollte möglichst hoch gewählt werden, damit der
Interrupt schnellstmöglich bearbeitet wird (dran denken: Vom Auftreten
eines Interrupt-Ereignisses bis zur Ausführung der ISR vergehen
mindestens 4 Taktzyklen!). Nach dem Einlesen der betreffenden Pins
einen Vergleich mit dem letzten Stand durchführen (es kann ja auch
passieren, dass mehrere Pins sich quasi zeitgleich ändern) und dann die
entsprechenden LEDs setzen. Am besten alles in Assembler programmieren,
da hast Du am ehesten den Überblick über die zeitkritischen Vorgänge.

von Andre Fischer (Gast)


Lesenswert?

Hi,

momentan hab ich nicht viel Zeit rumzuprobieren aber fuer den Fall das
ich wieder dazu komme...

Wo kann ich mehr Informationen ueber das Timing finden (ich meine woher
weiss ich das es mindestens 4 Taktzyklen sind bis die ISR abgearbeitet
wird)

Wenn ich also 8 Pins abfrage am Anfang der ISR nach wieviel Taktzyklen
habe ich auch den letzten Port abgefragt? (4 Taktzyklen bis zum starten
der ISR dann brauch ja jedes Abfragen der Pins x Taktzyklen, also sind
wir bei 4+x+x+x+x+x+x+x Taktzyklen bevor der letzte [also achte] Pin
abgefragt wird)

Wenn ich also weiss welcher Vorgang wieviel Taktzyklen braucht kann ich
mir ausrechnen mit Welchem Quartz ich das ganze bei welchen Frequenzen
betreiben kann.

Waere super wenn mir jemand etwas dazu sagen koennte oder einen Link
geben wo ich das ganze genauer nachlesen kann.

Danke

Andre

von johnny.m (Gast)


Lesenswert?

> Wo kann ich mehr Informationen ueber das Timing finden ...

Steht alles im Datenblatt.

> Wenn ich also 8 Pins abfrage am Anfang der ISR nach wieviel
> Taktzyklen habe ich auch den letzten Port abgefragt?

Da die abzufragenden Pins sinnvollerweise alle an einem Port sein
sollten, geht das Einlesen in einem einzigen Taktzyklus. Dann einfach
ein Vergleich mit dem vorherigen Zustand (bei der letzten Abfrage) und
an allen Pins, an denen sich was geändert hat, die entsprechende LED
einschalten. Im Hintergrund könntest Du einen Timer laufen lassen, der
z.B. alle 10ms einen Überlauf oder ein Compare Match macht. Wenn Du
dann jeder LED ein Zählregister zuordnest, kannst Du es jeweils bei
einem Wechsel am dazugehörigen Pin auf einen bestimmten Wert setzen
(bei den 10 ms oben würde z.B. eine 50 eine Leuchtdauer von 500ms
bedeuten) und bei jedem Timer-Ereignis werden alle Register um eins
dekrementiert. Erreicht ein Register den Wert '0' (d.h. es ist in den
letzten 500 ms kein Wechsel am Pin aufgetreten), wird die entsprechende
LED ausgeschaltet. Das Flag vom Timer sollte vielleicht (anstatt mit
einem Interrupt) im Hauptprogramm im Polling-Verfahren abgefragt
werden, damit kein Interrupt-Ereignis verloren geht.

Das nur als Idee...

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.