Forum: Mikrocontroller und Digitale Elektronik Input Capture


von Sascha D. (plutoonline)


Lesenswert?

Hallo,
ich lese ein Signal per Input Capture ein.

Bei einem Interrupt steht ja dann in ICR1H und ICR1L die Aktuelle Zeit
zum Zeitpunkt des Interrupts.
Der Wert wird gespeichert und vom nächsten Wert abgezogen, so erhalte
ich die Signallänge.
So weit so gut, wenn aber der neue Wert kleiner ist als der
gespeicherte (Überlauf) kommt ja ein negativer Wert herraus.

Bsp.: 1. 1Wert=1000 2.Wert=2000
      2. 2Wert-1.Wert=1000
      So ist aller O.K

      1. 1Wert=2000 2.Wert=1000
      2. 2Wert-1.Wert=-1000

Ich habe das jetzt so gelöst:

  cp Wert1H,Wert2H
  brge comp2
comp1:
  cp Wert1L,Wert2L
  brge comp2
  rjmp norm
comp2:
  com Wert1H
  com Wert1L
  com Wert2H
  com Wert2L
norm:
  sub Wert2L, Wert1L
  sbc Wert2H, Wert1H

Jetzt zu meiner Frage:
Kann man das einfacher lösen?
Ich hoffe ich habe mich einigermaßen Verständlich ausgedrückt.
Vielen Dank für eure Hilfe!

von Andreas K. (andi_k)


Lesenswert?

BRGE würde ich nicht nehmen, da es das MSB als Vorzeichen (+/-) hernimmt
aber der Timer1 zählt ja von 0 bis 65535 und nicht von -32768 bis
+32767.
Benutze lieber BRSH (Same or higher unsigned) oder BRLO mit umgekehrtem
Vergleich (Lower unsigned).
Das hohe Byte einer 16 Bit-Zahl kann man mit CPC (Compare with Carry)
vergleichen.
Bei dem ersten Vergleich der Low-Bytes wird unter Umständen das
Carry-Bit gesetzt welches bei dem Vergleich der High-Bytes mit CPC
einbezogen wird.
Ansonsten würde ich nur den alten Wert negieren und nicht beide, sonst
kommt es ja wieder auf das selbe (falsche) hinaus.
Eine Negation ist übrigens nicht einfach nur ein Invertieren der Bits
sondern auch noch mit einem Abgleich von +1 verbunden.
So wird aus +1 (00000001) nach dem COM ein -2 (11111110), ein +1 macht
daraus dann -1 (11111111).

Für die Einfachheit:

 cp   Wert2L,Wert1L    ;Ist Wert2 (wahrscheinlich der neue)
 cpc  Wert2H,Wert1H    ;>= Wert1?
 brsh norm             ;Dann nicht negieren.
 com  Wert2H           ;Ansonsten Wert2
 neg  Wert2L           ;negieren.
 sbci Wert2H,-1        ;High-Byte korigieren +(1-Carry).
norm:
 sub  Wert2L,Wert1L
 sbc  Wert2H,Wert1H

MfG
Andi

von Hannes L. (hannes)


Lesenswert?

Warum so umständlich?
Gesucht ist die Differenz (Impulsdauer) seit dem letzten Int.
Da Timer und (2) Register positive Zahlen enthalten
(Interpretationsfrage), genügt eine einfache Subtraktion. Weitere
Vergleiche erübrigen sich, da die Differenz nicht negativ ist.

...

von Andreas K. (andi_k)


Lesenswert?

Hi Hannes!

Stimmt, hast recht.
Wenn man es sich genau überlegt, erfolgt nach einem Überlauf des Timers
bei der Subtraktion des zuvor höheren Wertes vom neuen niedrigeren auch
ein Überlauf oder besser Unterlauf (Borrow) was das dann von selbst
korrigiert.

Beispiel:
Wert1 = 50000 (alt)
Wert2 = 1000  (neu)

Ergebnis muß dann 16536 sein (15536 bis zum Überlauf + 1000).

1000 - 50000 = -49000 (17 Bit), betrachtet ohne Vorzeichen als 16 Bit
ist es dann 16536.

MfG
Andi

von Hannes L. (hannes)


Lesenswert?

'Nabend Andi...

Nunja, sehen wir den Timer soch einfach als eine "fortlaufende Zahl"
(Zeit kann man bekanntlich nicht zurückdrehen), von der wir nur die
letzten beiden Stellen (Bytes) berücksichtigen, die höheren Stellen
aber ignorieren. Somit ist der später eingelesene Wert immer höher als
ein zuvor eingelesener.

Bei der Subtraktion des vorherigen Wertes vom "neuesten" Wert kann
daher nur ein positiver Wert herauskommen. Also werfen wir das Carry
weg und interpretieren den 16-Bit-Wert als unsigned-Integer.

Gute N8...

...

von Sascha D. (plutoonline)


Lesenswert?

Hi, vielen Dank für eure Erklärungen!
Ich bin jetzt aber ein wenig verwirrt, wie verhält sich das jetzt?
Soll ich jetzt einfach die Werte Subtrahieren und alles ist O.K.?

von Hannes L. (hannes)


Lesenswert?

Genau...

 sub neu_low,alt_low     ;Lowbytes subtrahieren
 sbc neu_high,alt_high   ;Highbytes und Übertrag (Carry) subtrahieren

Vorher aber noch den Wert von neu_xxx sichern, damit er nach alt_xxx
kopiert werden kann und für die nächste Subtraktion bereit steht.

Wenn man die Werte im SRAM hält, dann benötigt man 4 temporäre
Register:

- SREG sichern
- benuzte Register freimachen (push)
- alten Wert aus SRAM holen (H und L)
- neuen Wert vom ICP-Register einlesen (H und L)
- neuen Wert als alten Wert ins SRAM (H und L)
- Subtraktion (erst L, dann H mit Carry)
- Ergebnis ins SRAM als Impulsdauer (H und L)
- benutzte Register wiederherstellen (pop)
- SREG wiederherstellen

...

von Sascha D. (plutoonline)


Lesenswert?

Hallo,

ich hatte leider keine Zeit in den letzten Tagen.

Ich werde das mal so austesten wie es Hannes beschrieben hat.
Vielen Dank nochmal an alle!!!!!!

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.