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++; }
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?
>> so sieht mein erster Versuch:
1 | if(PIND&(1<<PIND1) zustand|=(1<<PIND1); |
2 | |
3 | if(!(PIND&(1<<PIND1)) zustand|=(1<<PIND1); |
4 | :
|
5 | :
|
6 | if(PIND&(1<<PIND1) zustand|=(1<<PIND1); |
7 | |
8 | 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:
1 | zustand|=(1<<PIND1); |
Ich verstehe deine Logik nicht:
1 | while(bitmuster==PIND) timer_start(); |
2 | :
|
3 | :
|
4 | 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...
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-Tutorial#Programmieren_mit_Interrupts 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.
@ 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...
> 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.
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.
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.
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.
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.
Das hat wenig mit Kompetenz zu tun. Aber was willst du jemandem sagen, der das hier schreibt
1 | while(bitmuster==PIND) timer_start(); /* Timer startet für |
2 | 50ms ,beim Überlauf wird start=0 und die Schleife wird
|
3 | 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.
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-Tutorial#Zugriff_auf_IO-Ports 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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.