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


von Hannes (Gast)


Angehängte Dateien:

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


von johnny.m (Gast)


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.

von kranker Jan (Gast)


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

von Hannes (Gast)


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

von Hannes (Gast)


Lesenswert?

Hallo Jan,

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

von johnny.m (Gast)


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.

von Rahul, der Trollige (Gast)


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.

von Peter D. (peda)


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

von Hannes (Gast)


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.

von johnny.m (Gast)


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.

von Rahul, der Trollige (Gast)


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!

von johnny.m (Gast)


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!

von Hannes (Gast)


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



von Hannes (Gast)


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.

von johnny.m (Gast)


Lesenswert?

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

von Rahul, der Trollige (Gast)


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.

von johnny.m (Gast)


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.

von Hannes (Gast)


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.

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

hab er sich nicht so
73
Christoph

von Rahul, der Trollige (Gast)


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?

von Hannes (Gast)


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

von johnny.m (Gast)


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...

von johnny.m (Gast)


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...

von Hannes (Gast)


Lesenswert?

Schon gut Mann,

und danke nochmal.

von Rahul, der Trollige (Gast)


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...

von Karl H. (kbuchegg)


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.

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


Lesenswert?

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

von Blaubär (Gast)


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ö



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.