mikrocontroller.net

Forum: Compiler & IDEs Pulslänge mit INT0/1 und T1 messen


Autor: Hannes (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Freaks,

ich versuche, die Impulslänge eines Rechtecksignals zu messen.Dazu habe 
ich den Code im Anhang geschrieben.

Ich verwende WinAVR, ATtiny2313, Quarz 11.059.

Im main wähle ich in GIMSK zunächst INT1 und konfiguriere INT1 und INT0 
für steigende Flanken.

Nach sei() ist also zunächt INT1 scharf. Wenn nun eine steigende Flanke 
vorbeikommt, soll INT1 den Timer1 starten und mit GIMSK=(1<<INT0) sich 
selbst deaktivieren, dafür den Kollegen INT0 augewecken. Der soll nun 
auf die nächste Flanke warten und Timer1 stoppen. Danach deaktiviert er 
sich ebenfalls (GIMSK=0).

In main wird derweilen gewartet, bis beide, INT0 und INT1 ihren Job 
erledigt haben (while(GIMSK);), anschliessend alle Interrupts gesperrt, 
der Inhalt von Timer1 ausgelesen und über eine kleine Routine (dez2ser) 
seriell ausgegeben.

Nun das merkwürdige: Egal, welche Eingangsfrequenz (950 Hz bis 32 kHz 
habe ich getestet) ich an INT0 und INT1 lege (sind parallelgeschaltet), 
ich erhalte immer einen Messwert von 30 (entspricht ca 3us bei 11 MHz).

Es scheint fast, ob INT0 nicht auf die nächste Flanke wartet, sondern 
gleich anspricht.

Wie kann das sein?

Danke für Eure Antworten!

Hannes


Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du müsstest zunächst mal vor der Freigabe des Interrupt das Flag 
löschen. Wenn das noch von einer vorhergehenden Flanke gesetzt ist, wird 
selbstverständlich sofort nach Beendigung der einen ISR die andere 
aufgerufen.

Abgesehen davon ist das, was Du da machst, eine ziemliche Krücke. 
Impulslängen misst man nicht mit externen Interrupts (und erst recht 
nicht mit gleich zweien davon, immerhin sind die Flanken umschaltbar), 
sondern mit der Input Capture Unit. Zu dem Thema gibt es hier (und im 
µC-und-Elektronik-Forum) eine ganze Reihe Threads.

Autor: kranker Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Hannes,

Du solltest das Prinzip ändern:

Eine Eingangssignalflanke kommt: Timerzähler wird nullgesetzt und Timer 
gestartet. Eine nächste Eingangssignalflanke kommt und schaut sich den 
Timerzählerstand an und gibt in aus. Danach das Spielchen von vorne. Ich 
vermute das macht es wesentlich unkomplizierter als deine bisherige 
Lösung.

Jan

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Johnny,

Das habe ich schon ausprobiert (EIFR=0). Gleicher Effekt. Ausserdem 
sollten die Flags nach Verlassen der Routine doch selbstständig gelöscht 
werden?

Dass ich das mit den 2 INT's mache, hat schon seinen Grund. Da kommt 
später noch mehr dazu, wofür ich das so brauche.

73 Hannes

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jan,

klar, das geht einwandfrei. Aber das blockiert halt alles.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> EIFR=0
Damit löschst Du gar nichts! Interrupt-Flags werden gelöscht, indem man 
eine 1 hineinschreibt! Und wenn das Flag vom zweiten Interrupt von einer 
vorhergehenden Flanke noch gesetzt ist (was in Deinem Fall sehr 
wahrscheinlich ist) und der Interrupt freigegeben wird, dann wird die 
ISR sofort nach dem Verlassen der anderen (vom ersten Interrupt) 
ausgeführt. Was Du da gemacht hast, ist eine 
Interrupt-Bearbeitungszeit-Messung.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>konfiguriere INT1 und INT0 für steigende Flanken

Du willst die Pulslänge messen, und konfigurierst beide auf die gleiche 
Flanke? Das ist doch Quatsch.
Du wirst das von JoHnny geschilderte Problem haben: Dein INT1-Flag ist 
schon gesetzt, sobald du den Interrupt im GIMSK freischaltest.
Lösch das Interrupt-Flag und gut müsste sein.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes wrote:

> Es scheint fast, ob INT0 nicht auf die nächste Flanke wartet, sondern
> gleich anspricht.

Nö, er wartet schon auf die nächste Flanke.

Allerdings auf die nächste überhaupt und nicht erst auf die nach 
Interruptfreigabe.

Falls das nicht gewünscht wird, muß man vor der Freigabe das 
Interruptbit löschen (also setzen).


Aber ne Frage, warum benutzt Du nicht einfach den ICP-Eingang ?
Bequemer kann man doch keinen Zeitstempel kriegen.


Peter

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi trolliger Rahul,

sorry, habe mich falsch ausgedrückt: Ich will eigentlich die 
Periodenzeit messen.

@ Johnny:

tiny 2313 Data Sheet Seite 61:

When an edge or logig chage...triggers an IRQ, INTF becomes set (one).
...
The flag is cleared when the ISR is executed.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau, und deshalb wird die ISR ja auch ausgeführt! Ich glaube, Dir 
fehlt da gewaltig Grundverständnis. Es wird nur das zu der ISR gehörende 
Flag gelöscht. wenn also die INT0-ISR ausgeführt wird, dann wird das 
Flag INTF0 gelöscht. Da aber das INTF1 mit großer Wahrscheinlichkeit 
noch gesetzt ist (der Interrupt war ja vorher gesperrt und deshalb das 
Flag natürlich nicht gelöscht), wird eben nach Verlassen der INT0-ISR 
sofort die INT1-ISR ausgeführt. Du kannst mir das ruhig glauben.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>sorry, habe mich falsch ausgedrückt: Ich will eigentlich die
>Periodenzeit messen.

Und dafür braucht man 2 Interrupts?
Ich bräuchte nur einen:
INTx auf steigende Flanke konfigurieren
Bei Eintreten des Interrupts Timer auslesen, Wert vom vorhergehenden 
Interrupt davon abziehen => eine Pulslänge.
Für sowas ist die InputCaptureUnit prädestiniert!

Falls es aus aus Johnny's Post noch nicht hervorgegangen ist:
Das INT1-Interrupt-Flag wird im gleichen Moment gesetzt wie das des 
INT0.
Wenn man dann in der INT0-ISR das INT1IE-Flag setzt, springt der 
Controller sofort in die INT1-ISR, da dessen Interrupt-Flag ja auch 
gesetzt ist.
Also: Erst löschen, dann freigeben!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> GIMSK=(1<<INT0);    //N�chste Flanke soll INT1 ausl�sen
Ich glaub, da ist auch in Deinem Programm generell ein ziemliches 
Durcheinander. In der obigen Zeile stimmt schonmal der Kommentar 
überhaupt nicht mit dem Code überein. Außerdem hauen dadurch bei der 
nächsten positiven Flanke beide Interrupts rein, weil INT1 nirgends 
abgeschaltet wird. Da kann dann alles Mögliche passieren. Aber wie 
gesagt: Mach es mit Input Capture. Dafür ist das schließlich da!

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Johnny,

Du hast recht, ich habe verkehrt herum gedacht. Nun läuft alles wie es 
soll. Vielen Dank!

Danke auch den Anderen.

73 Hannes



Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry für den Kommentar, INT0 muss es natürlich heissen.

INT1 ist aber schon abgeschaltet, weil

GIMSK=(1<<INT0);    nur INT0 freigibt

Danke auch Rahul und Peter.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, hast kein "|" drin. Dann gehts. Hatte ich beim überfliegen nicht 
gesehen.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>OK, hast kein "|" drin. Dann gehts. Hatte ich beim überfliegen nicht
>gesehen.

Da fällt mir ein, dass das Programm noch erweitert werden soll.
Wenn man "GIMSK=(1<<INT0);" schreibt und noch andere Interrupts 
verwenden will, die nichts mit der Periodenmessung zu tun haben, werden 
die durch sowas natürlich "gekillt".
Besser wäre es, zu beginn der jeweiligen ISR "GIMSK &= ~(1<<INTx);" zu 
schreiben (x = 0 oder 1). Dann wird nur die jeweilige Frteigabe 
abgeschaltet.
Eigentlich müsste auch "GIMSK ^= ((1<<INT0) | (1<<INT1));" gehen (Hab 
ich jetzt so aus der Hüfte "konstruiert"...).
Damit würde man sich 2 C-Anweisungen sparen.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, ich hoffe, er hat wenigstens verstanden, dass ein einziger 
Interrupt völlig ausreicht (Wenn er es schon nicht mit Input Capture 
machen will). Dann kann er sich die Umschalterei ja komplett sparen.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Naja, ich hoffe, er hat wenigstens verstanden, dass ..."

Danke, sehr nett von Anderen in der dritten Person zu sprechen.

Andere Interrupts brauch ich nicht, und ich sagte schon, dass es Gründe 
für diese Konstruktion gibt.

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab er sich nicht so
73
Christoph

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Danke, sehr nett von Anderen in der dritten Person zu sprechen.
Es war halt eine Unterhaltung zwischen Johnny und mir (die dich nichts 
angeht ;-)...

>Andere Interrupts brauch ich nicht, und ich sagte schon, dass es Gründe
>für diese Konstruktion gibt.

Die Gründe würde mich schon äusserst interessieren, oder sind die 
geheim?

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Es war halt eine Unterhaltung zwischen Johnny und mir (die dich nichts
angeht ;-)..."

Sehr witzig. Du bist wohl wirklich trollig unterwegs, was?

Ciao

Hannes

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes:
Mein Posting bezog sich (wie von Rahul ganz richtig erkannt) auf seinen 
(Shit, schon wieder dritte Person...) Vorschlag, die Umschalterei mit 
EXOR zu machen. Wenn Du Dich dadurch angepisst fühlst, kann ich da nix 
dran ändern. Sorry, dass ich helfen wollte...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nochmal @Hannes:
BTW: Wie redest Du von anderen? In der vierten Person? Ich glaube, mich 
zu erinnern, dass gerade dafür die dritte Person erfunden wurde...

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon gut Mann,

und danke nochmal.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch einer, der unter Kategorie ";-) <-- das ist ein Smilie!" fällt...
Immer wieder interessant, welche Reaktionen Forennamen bei manchen 
anderen Forenbenutzern sorgen...

Iss mir alles zu drittens...

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

Bewertung
0 lesenswert
nicht lesenswert
> Die Gründe würde mich schon äusserst interessieren,

Mich allerdings auch. Im Moment kann ich mir keinen
vorstellen, der mich davon abhalten würde ein Input
capturing zu machen (*). Das ist sowas von simpel und
sowas von genau. Das einzige worauf man achten muss,
ist das man alle Timer Overflows mitkriegt. Allerdings
hat man selbst beim kleinsten Vorteiler 65536 Takte Zeit
einen Overflow zu registrieren, so dass das in der Praxis
wohl kein Problem ist. Noch banaler als ICP gehts ja wohl
kaum: Alles einstellen, auf den Interrupt warten und in
aller Gemütsruhe das eingefrorene Zählergebnis abholen.
Da gibts keine Race Conditions, nichts ist zeitkritisch
und sogar die BASCOM Leute kriegen das ohne Probleme hin
(wenn sie mal Handbuch lesen würden :-)

(*) OK. Einen gibt es. Wenn der Pin nicht mehr frei ist.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es garantiert ist, dass man maximal einen timer overflow während
des Messintervalls bekommt, muss man den nicht einmal mitbekommen.

Autor: Blaubär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da spricht er wahr, unser Troll-Rahul:

" Immer wieder interessant, welche Reaktionen Forennamen bei manchen
anderen Forenbenutzern sorgen..."

sein alter Forenname "fieser, klugscheissender Rahul" passt doch besser 
zu ihm...

höhöhöhöhö



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.