www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Flanken-gesteuerte Abtastung


Autor: Grady Napsone (napsone)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin  neu in  die Programmierung von Mikrocontroller.Ich  wollte 
wießen,  wie man eine Flanken-gesteuerte Abastung am PORT machen kann.
Ich  benutze den ATmega128  mit 14,7456 MHz und  die 
Programmierungssprache ist C. Ich will  Wiegand-Signal von 1kHz Frequenz 
nur  bei Änderung des PORT-Zustands aufzeichnen.Bitte  ich brauche 
Hilfe...
Dank


so sieht  mein erster Versuch:

i=0;
start=1;
bitmuster=PIND;

while(start)
{

zustand=0;

 while(bitmuster==PIND)      timer_start();       /*  Timer startet  für 
50ms  ,beim  Überlauf  wird  start=0  und  die Schleife  wird 
verlassen;*/

 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);


 while(bitmuster==PIND)  counter[i]++;/*   warte  solange  keine 
Änderung  am PORT gibt */

 sammlung[i]=zustand;
 bitmuster=0;             //  Bitmuster  wird  initialisiert

 bitmuster=PIND;         // Bitmuster nimmt  den neuen Werte  am Port

 i++;


}

Autor: Ralli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klar, wenn man neu bei den µCs ist, muss man gleich so einen
großen nehmen, von dem die ganze Bandbreite der Möglichkeiten
unübersehbar ist.

Also:
Es gibt viel kleinere und billigere Atmels, die mit jeder
Flanke an eiem Port-Pin einen Interrupt auslösen.
Schaut man sofort nach, was für ein Pegel am Pin anliegt, weiß man,
ob es ein Lo-Hi-, oder ein Hi-Lo-Übergang war....

Lässt man parallel dazu einen schnellen Counter zählen, weiß man,
wenn man bei der Interrupt-Bearbeitung seinen Zählerstand abfragt und
ihn mit dem beim letzten Interrupt vergleicht, wie lange der vorige
Zustand dauerte...

Was soll den eine 50ms-Schleife für die Erkennung von Signalen
im kHz- also 1 ms- Bereich bewirken?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> so sieht  mein erster Versuch:
 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);
 :
 :
 if(PIND&(1<<PIND1)     zustand|=(1<<PIND1);

 if(!(PIND&(1<<PIND1))  zustand|=(1<<PIND1);
Es lebe Copy-Paste, und alle Fehler, die es mit sich bringt...

Was da steht heißt nur, dass egal welcher Pegel am PIND ist, auf jeden 
Fall das Bit 1 in zustand gesetzt werden soll. Diese ganze Litanei 
ließe sich ohne signifikante Funktionseinschränkungen so abkürzen:
 zustand|=(1<<PIND1);

Ich verstehe deine Logik nicht:
 while(bitmuster==PIND)  timer_start();   
 :
 :
 while(bitmuster==PIND)  counter[i]++;
Mal wartest du solange keine Änderung da ist, und mal startest du die 
(seltsame) Auswertung...


> Es gibt viel kleinere und billigere Atmels, die mit jeder
> Flanke an eiem Port-Pin einen Interrupt auslösen.
> Schaut man sofort nach, was für ein Pegel am Pin anliegt, weiß man,
> ob es ein Lo-Hi-, oder ein Hi-Lo-Übergang war....
Das ist eine etwas gewagte Methode...

Autor: Michael B. (planlessmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe leider mit dem 128erm noch nicht gearbeitet, aber wenn ich sein 
Datenblatt anschaue, dann steht auf Seite 92:
>When an edge or logic change on the INT7:0 pin triggers an interrupt
>request, INTF7:0 becomes set (one).

Da Du immer mit PIND1 arbeitest, nehme ich an, dass Dein Signal auf PD1 
(INT1) angeschlossen ist....

Wenn ich die Aussage vom Datenblatt richtig verstanden habe, kann der 
einen Interrupt bei jeder Änderung (=steigende und fallende Flanke) 
auslösen. Schau Dir das hier mal kurz an:
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
Das könnte Dir weiterhelden. Dort stehen zwar andere Registernamen, aber 
wenn Du Dir das Datenblatt vom Mega8 und vom Mega128 gleichzeitig 
anschaust, kannst Du gut übersetzen, wie die beim 128er heißen. 
Vielleicht sind sogar viele gleich.

Autor: Ralli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Lothar Miller

> Das ist eine etwas gewagte Methode...

Wahnsinnig gewagt, NEIN: LEICHTSINNIGST bei 1 ms - Signalen!
Besonders, da man mit dem sowieso nötigen Timer-Abgleich
ÜBERHAUPT keine Möglichkeit hat, Glitches zu erkennen! ;-)

Wie schlau machst du es denn?

Übrigens:
Der Fragesteller hat schon das Interesse verloren...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie schlau machst du es denn?
Das allein reicht nicht aus:
>> Schaut man sofort nach, was für ein Pegel am Pin anliegt, weiß man,
>> ob es ein Lo-Hi-, oder ein Hi-Lo-Übergang war....
Es gibt kein sofort. Es wird immmer mehr oder weniger Zeit vergehen. 
Ich merke mir deshalb, was vorher da war. Erst dann kann ich erkennen, 
ob ich tatsächlich eine Flanke habe (oder ob das z.B. nur ein Spike 
war). Insgesamt sollte das Signal angemessen (bezogen auf die 1ms) 
entprellt werden...
(du könntest allerdings mit Timerabgleich ebenfalls eine Entprellung 
gemeint haben)

> Übrigens:
> Der Fragesteller hat schon das Interesse verloren...
Ja, hat er. Sei's drum.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:

>> Der Fragesteller hat schon das Interesse verloren...
> Ja, hat er. Sei's drum.

Wenn ihr mich fragt:
Der Fragesteller übernimmt sich momentan.
Das was er da präsentiert hat, ist noch nicht einmal ansatzweise auch 
nur in der Nähe von irgendetwas Sinnvollem.

Ich tippe auf (in der Reihenfolge)
  Aufgabenstellung unterschätz
  Grundlagen lernen ist mega out
  "LED blinken lassen, Taster abfragen" ist was für Weicheier

Von daher halte ich den Ansatz über Interrupts zu gehen auch für gewagt. 
Nicht weil die Methode an sich problematisch ist, sondern weil du es dem 
Fragesteller nicht verklickert bekommst. Einem 8-jährigen der gerade das 
kleine Einmal-Eins büffelt, kannst du nun mal nicht quadratische 
Gleichungen erklären, egal wie sehr du dich ins Zeug legst.

Autor: Grady Napsone (napsone)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich  habe  nicht  die Interesse verloren.Meine  Frage  habe ich   nicht 
richtig gestellt,dafür möchte ich entschuldigen.Die Kommentar  von 
einigen Leute ,machen  die Anfänger  in die 
Mikrocontroller-programmierung  nicht einfach.

Bei  meinem Problem ,geht  es  um  die Abfrage  eines  PORTs , bei  der 
Änderung des Portszustands  wird  den neuen Wert  und  die vergehende 
Zeit    abgespeichert.

Ich habe mich  so  überlegt,dass  ich  in einer Schleife immer PORT 
abfragen  und  wenn etwas sich  ändert,  speichere ich  diesen Wert und 
die von der Zähler(TCNT).Vielleicht  ist  die Frage blöd aber
ich  wollte  wiessen ,wie man so eine Abtastung mit Timer realisieren 
kann.Ich  will  meinen Signal  mit 20us abtastet  für  eine gesamte Zeit 
von 50ms.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grady Napsone schrieb:

> Ich habe mich  so  überlegt,dass  ich  in einer Schleife immer PORT
> abfragen  und  wenn etwas sich  ändert,  speichere ich  diesen Wert und
> die von der Zähler(TCNT).

Fang erst mal damit an, eine Flanke zu erkennen.
Dein Programm wartet auf eine Flanke und wenn es die erkennt, geht eine 
LED an.

> Vielleicht  ist  die Frage blöd aber
> ich  wollte  wiessen ,wie man so eine Abtastung mit Timer realisieren
> kann.Ich  will  meinen Signal  mit 20us abtastet  für  eine gesamte Zeit
> von 50ms.

Das Problem ist:
Deine Gedankengänge sind ja grundsätzlich nicht so schlecht. Aber dir 
fehlt einfach unheimlich viel an Grundlagen um diese Gedanken in die Tat 
umzusetzen.

Autor: Michael Haberler (mah)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Grady,

ich würde Dir empfehlen mit Peter Danegger's Tasten-Entprellung zu 
beginnen, die hat nämlich einen 0->1 Flanken-Detektor; wenn Du den Code 
von Beitrag "Re: Universelle Tastenabfrage" dazunimmst, auch 
den von 1->0. Die Timer-Interrupts mitzählen und schon hast Du Dein 
timing.

Den Code für Repeat brauchst Du nicht; die Entprellung ist auch optional 
- ich weiss nicht ob Du die brauchst.

Beitrag "Universelle Tastenabfrage"

bzw Komfortroutine (C für AVR) :

http://www.mikrocontroller.net/articles/Entprellung

Michael

ps: Ihr Gescheiterln macht es hier für Anfänger unnötig schwer - bei 
jeder Gelegenheit die eigene Kompetenz raushängen zu lassen finde ich 
unnötig.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hat wenig mit Kompetenz zu tun.
Aber was willst du jemandem sagen, der das hier schreibt
 while(bitmuster==PIND)      timer_start();       /*  Timer startet  für
50ms  ,beim  Überlauf  wird  start=0  und  die Schleife  wird
verlassen;*/


PS: Bin schon neugierig, wie du ihn im Schnellsiederkurs durch die 
Portabfragen, Timer Konfiguration, ISR Vereinbarung (was ist überhaupt 
eine ISR) durchsprichst. Ach ja: die Zeit, die hätte ich jetzt komplett 
vergessen. Oder hast du im Originalcode auch nur ansatzweise erkennen 
können, was mit einem Messwert gemacht werden soll? Nicht, das er etwas 
gehabt hätte, was der Definition von Messwert auch nur annähernd nahe 
gekommen wäre.

Autor: Michael B. (planlessmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Grady,
Kopf hoch; nach ein paar Wochen / Monaten bekommst Du automatisch ein 
"dickeres" Fell und ignorierst einfach unpassende Antworten. Es ist halt 
so, dass viele Leute nicht zum tausendsten Mal ein Thema erklären wollen 
und dabei vielleicht auch mal übersehen, dass es für den Fragesteller 
erst das erste Mal ist. Ganz typisch sind ja auch diese "enorm 
hilfreichen" Tipps wie "google doch mal" oder noch hochnäsiger: "Die 
Lösung findest Du unter z.B. www.gidf.de".
Leider findet Google heute viel mehr Fragen als Antworten und da macht 
die Suche nach einer Zeit auch keinen Spaß mehr... Also: Einfach fragen 
und freche / bösartige Antworten einfach überlesen.

Zu Deinem Problem:
Wenn ich Deine zweite Erklärung jetzt richtig verstanden habe, dann 
bezeichnest Du mit Flanke einfach eine Pegeländerung in einer sehr 
kurzen Zeitspanne (20µs). Das ist dann so aber nicht ganz richtig. Durch 
dieses Polling (= andauerndes Abfragen) bekommst Du nur mit, dass sich 
irgendwann mal was in diesen 20µs geändert hat; aber die echte Flanke 
(also wirklich den EXAKTEN Zeitpunkt), kannst Du so nicht ermitteln.
Wenn Dir die 20µs Auflösung aber reichen, kannst Du sogar wirklich 
andauernd den Port abfragen.
Die Portabfrage hast Du Dir schon mal genauer angesehen?
Wenn nicht: --> 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
Jetzt könntest Du also in einer (Endlos-)Schleife andauernd den Pin 
abfragen und wenn sich was geändert hat, sich die aktuelle Zeit merken 
(das passiert mit Timer; dazu später mehr).
Das Problem: Der MC (Microcontroller) ist die ganze Zeit nur damit 
beschäftigt, den Pin abzufragen. Sollte der Code dann irgenwann mal 
erweitert werden, werden auch die 20µs-Intervalle größer. Das ist also 
nicht ganz so schön. Für den Anfang vielleicht ausreichend, aber 
unschön.

Es gibt aber auch die Alternative mit den "Interrupts". Hier musst Du am 
Anfang nur etwas konfigurieren (den Link hatte ich Dir ja schon oben in 
meiner ersten Antwort geschrieben) und kannst den Pin erstmal 
"vergessen". Das Schöne an dieser Art ist, dass sich die Hardware dann 
selbständig meldet und eine Funktion bei Dir im Code aufruft (die 
"Interrupt Service Routine, kurz ISR) und Dein Hauptcode in der Zeit 
unterbrochen wird. Und DAS passiert wirklich exakt zu dem Zeitpunkt, wo 
sich der Zustand des Pins ändert; es also wirklich eine Flankenänderung 
gibt.

So; so kannst Du also den Augenblick des Änderns feststellen. Entweder 
ganz genau mit Interrupts, oder ziemlich genau mit extrem schneller 
Abfrage (Polling).
Aber was dann? Dann hast Du ja nach wie vor keine Zeitinfo...

Dafür gibt es die Timer.
Die arbeiten so ungefähr wie die Interrupts bei den Eingängen. Nur ist 
hier der Grund für den Aufruf einer ISR nicht eine Änderung außerhalb 
des Chips dafür verantwortlich, sondern eine interne Hardwareschaltung 
(eben der Timer). Diesen kann man so konfigurieren, dass z.B. jede 
Millisekunde ein Interrupt ausgelöst wird (das ist jetzt aber ein 
anderer als der, der bei Änderung des Pin-Pegels ausgelöst wird).
In dieser Timer-ISR musst Du jetzt nur brav und langweilig eine globale 
Variable hochzählen. Evtl. auch mehrere miteinander verschachtelt, wenn 
Du längere Zeiten brauchst, da eine Variable nicht von 0 bis z.B. 
6457327894562317894523789623 zählen kann. Die hat - je nach Typ - nur 
einen sehr kleinen Wertebereich. Du kannst also z.B. noch zusätzlich zu 
einer Variable "Millisekunde", die bei jedem ISR-Aufruf um 1 erhöht 
wird, eine zweite Variable mit dem Namen "Sekunde" verwenden, die Du bei 
jedem 1000sten Aufruf der Timer-ISR hochzählst (die Variable 
"millisekunde" setzt Du zu diesem Zeitpunkt wieder auf 0).
So, und wenn Du jetzt einen Interrupt von Deinem Eingang bekommst, dann 
schaust Du einfach nach, welchen Wert Deine Variablen aus der 
Timer-Routine haben. Und schon hast Du die genau Zeiten zwischen den 
einzelnen Flanken.

Hast Du Dir denn das Tutorial schon mal angeschaut?

Dann noch eins:
Sowohl Dein Name, als auch Deine Texte klingen jetzt nicht so, als ob 
deutsch Deine Muttersprache wäre. Wenn Du Dich z.B. in englisch wohler 
und sicherer fühlst, kannst Du selbstverständlich auch auf englisch 
fragen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was willst Du denn mit den Zeitabständen der Flanken anfangen?

Du schreibst was von nem Wiegand-Signal, das sieht aber ganz anders aus:

The wiegand signaling standard utilizes two data lines to carry card 
data to the controller. They are named data1 and data0. As the names 
impart, the data1 line carries the "1" bits of the data stream to the 
controller, and the data0 line carries the "0" bits.

Du mußt das Protokoll verstehen und dekodieren. Die Flankenzeiten nützen 
dabei garnichts.
Bisher versuchst Du also, nutzlose Informationen zu sammeln.


Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.