Forum: Mikrocontroller und Digitale Elektronik Caputre ICP bei bacom


von Dirk M. (avr-nix)


Lesenswert?

So ich wollte ein Frequenzzähler bauen :-) und einen ATmega32 16Mhz
benutzen ( Probiere es jetzt mit einen Atmega16L mit 3,3V aus, weil ein
Nokia display dranhängt).

Da ich unter Bascom arbeite habe ich mal unter rowalt.de den Sourcecode
ausprobiert:

'0014.BAS:  InputCapture mit Timer1 (2) (Frequenzzähler)
'Hardware:  MAX232 an PD0/PD1
'           Nullmodemkabel zum PC
'           Pin ICP/PD6 an RTS
'--------------------------------------
$Regfile = "2313def.dat"
$Crystal = 3686400  '3,6864MHz-Quarz
$Baud    = 115200   'Hohe Baudrate

Dim lCount As Word At &H60
Dim wCountLo As Word At &H60 Overlay
Dim wCountHi As Word At &H62 Overlay

On ICP1 OnCapture   'Interrupt-Routine
On OVF1 OnOverflow  'Interrupt-Routine

Config Timer1=Timer,Prescale=1,Capture Edge=Rising

Enable ICP1         'Capture-Interrupt
Enable OVF1         'Overflow-Interrupt
Enable Interrupts   'Interrupts global

Main:               'Hauptschleife
Goto Main
'--------------------------------------
OnCapture:          'Timer1-Capture
  wCountLo = Timer1 'Erst Wert sichern
  Timer1 = 0        'Sofort Timer-Reset
  Print lCount;" ";
  wCountHi = 0
Return
'--------------------------------------
OnOverflow:
  Incr wCountHi    'lCount=lCount+65536
Return


Der Code sollte mir die Zeit in ms zurück geben über den Hyberterm.

Jetzt habe ich über ein Atmega 8Mhz ein Frwquenzteiler gebaut der die
Frequenz durch 2 4 8 etc Teilt.

Ich wollte die Zeit eines Impuls messen, allerdings bekomme ich nur
werte um 24000- 25000 und wenn ich diese den Kehrwert nehme stimmt es
nicht auch nicht ungefähr :-( . Da bei Capturebefahl erst meine 1.
Schritte mache wäre ich doch dankbar, um paar Tips.

also bei 8MHz -> 125ns -> 125ns*65535=8,1ms bis zum Überlauf.
das heisst auch das ich eine *min f=123Hz bis im MHz Bereich messen*
müsste wenn ich mal 1µs über den capture annehme( Verzögerung durch das
Programm).

von Werner J. (werner_j)


Lesenswert?

Hallo,

> Dim lCount As Word At &H60
lCount muß als Long (4 Byte) definiert sein
wCountLo und wCountHi = Overlays auf auf lCount

> $Regfile = "2313def.dat"
passt nicht zum im Text erwähnten Atmega16L

> OnCapture:          'Timer1-Capture
> wCountLo = Timer1 'Erst Wert sichern
Warum in der Capture-Routine Timer0 auslesen. Der Zählerstand von
Timer1 wird bei einem ICP Event automatisch ins Capture-Register
geladen.
Man verzählt sich also nicht um die Takte für den Interrupt-Aufruf.

Anmerkung: Der Bascom Simulator scheint ein Problem mit dem Capture
Register zu haben. Zumindest bei mir.-(. Das Capture Register wird
nicht mit dem Timer Wert geladen. (Bascom 7.4 & 7.7, die neue 7.9 hab
ich noch nicht getestet) Im Studio4 Simulator und in realer Hardware
funktioniert es hingegen korrekt.

Ciao,
Werner

von Dirk M. (avr-nix)


Lesenswert?

> OnCapture:          'Timer1-Capture
> wCountLo = Timer1 'Erst Wert sichern
Warum in der Capture-Routine Timer0 auslesen. Der Zählerstand von
Timer1 wird bei einem ICP Event automatisch ins Capture-Register
geladen.

? das verstehe ich nicht.

Wie kann ich den ICP Register auslesen? Timer0 sollte Timer1 heissen
oder?

Der Code hat ich hier als Orginal gepostet, ist habe entsprechend die
def für Mega16L gesetzt mit 8Mhz.

Bringt mir Noise Cancel noch was?

von Werner J. (werner_j)


Lesenswert?

Hallo

> (Capture-Register)
> das verstehe ich nicht.

Wenn eine Capture Interrupt (ICP) ausgelöst wird, macht der Atmel 2
bzw. 3 verschiedene Sachen.
1. er speichert den Wert des Timers im Register CAPTURE
2. er löscht den Timer, falls in CONFIG TIMER ..., CLEAR TIMER = 1,...
gesetzt ist.
3. er springt in die Interrupt Routine

1 & 2 macht die Hardware unabhängig vom Programm. Falls der Atmel also
z.B. mit einer anderen Interrupt Routine beschäftigt ist, macht das
nichts.
So wie Du das gelöst hast,wird der Timer erst in der Interrupt Routine
ausgelesen und neu gestartet. Normalerweise macht das nichts, wenn der
Atmel aber z.B. gerade mit einem anderen Interrupt beschäftigt ist,
kann einiges an Zeit vergehen, bis der Timer ausgelesen wird. Der Timer
läuft die ganze Zeit weiter, sprich Dein Wert ist dann falsch.




> Wie kann ich den ICP Register auslesen?
wCountLo = CAPTURE1

> Timer0 sollte Timer1 heissen oder?
Si

Ergänzen mußt Du noch das "CLEAR TIMER = 1" in der CONFIG Timer
Zeile

> Bringt mir Noise Cancel noch was?
das hängt davon ab, ob Du Störungen auf dem Signal hast, mit dem Du
Capture auslöst.


Aber das mit dem Capture-Register ist nur eine Frage wie elegant man
das lösen möchte, bzw. wie weit man ausreitzen möchte was der Atmel
hardwaremäßig kann.




Der Grund warum Deine Programm falsche Werte liefert, dürfte in der
Definition von lCount liegen...

Dim lCount As ***LONG*** At &H60     ' 4 Byte Wert (&H60,61,62,63)
Dim wCountLo As Word At &H60 Overlay ' Low Word von lCount (&H60,61)
Dim wCountHi As Word At &H62 Overlay ' HighWord von lCount (&H62,63)


Ciao,
Werner

von Dirk M. (avr-nix)


Lesenswert?

lcount wurde als LONG deklariert, aber keine besserung!
auch nicht mit Config Clear Timer=1 :-(

Arbeite mit Bascom .74

Hat jemand ein Programm was läuft welches mir die Zeit zurück gibt
mittels ICP?

Ich habe andauernt die gleichen Werte bei unterschiedlichen Frequenzen!

von Dirk M. (avr-nix)


Angehängte Dateien:

Lesenswert?

Neues verbessertes programm:
$regfile = "m16def.dat"
$crystal = 8000000
'8MHz-Quarz
$Baud    = 115200   'Hohe Baudrate

Dim Lcount As Long At &H60
Dim wCountLo As Word At &H60 Overlay
Dim wCountHi As Word At &H62 Overlay

On ICP1 OnCapture   'Interrupt-Routine
On OVF1 OnOverflow  'Interrupt-Routine

Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Clear
Timer = 1 , Noise Cancel = 1

Enable ICP1         'Capture-Interrupt
Enable OVF1         'Overflow-Interrupt
Enable Interrupts   'Interrupts global

Main:               'Hauptschleife
Goto Main
'--------------------------------------
OnCapture:          'Timer1-Capture
  wCountLo = Timer1 'Erst Wert sichern
  Timer1 = 0        'Sofort Timer-Reset
  Print lCount;" ";
  wCountHi = 0
Return
'--------------------------------------
OnOverflow:
  Incr wCountHi    'lCount=lCount+65536
Return


Bei dem triit das auch auf , wie im letzetem Beitrag von mir - den
Frequenzteiler als Anhang!

von Werner J. (werner_j)


Lesenswert?

Moin Dirk,

Du hast in Deinem Programm jetzt "CLEAR TIMER = 1" eingefügt, greifst
aber immernoch auf "lCounter = Time1" zurück.

entweder...
Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Noise
Cancel = 1
[...]
OnCapture:          'Timer1-Capture
  wCountLo = Timer1 'Erst Wert sichern
  Timer1 = 0        'Sofort Timer-Reset
  Print lCount;" ";
  wCountHi = 0
Return

oder...

Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Clear
Timer = 1 , Noise Cancel = 1
[...]
OnCapture:           'Timer1-Capture
  wCountLo = Capture 'Erst Wert sichern
  Print lCount;" ";
  wCountHi = 0
Return

Beide Variante mischen geht nicht.

Ich hab Deine Variante gerade mal im BASCOM Simulatur durch gespielt,
da gibt sie korrekte Werte aus. By the way, der CAPTURE BUG im Bascom
Simulator existiert immer noch. Capture1 wird nicht mit dem Timerwert
geladen. :-(

Wie hoch ist eigentlich die Fehlerquote bei 115200 Baud und 8MHz Takt?

Ciao,
Werner

von Dirk M. (avr-nix)


Lesenswert?

Also mit Timer1=0 bekomme ich nur Konstante werte  33200
ohne timer=0 nur 0 :-( bei 19200 und 115200 nur der Wert bei Timer1=0
liegt bei 29600 ca. (115200) . Wenn ich den Draht stecke, kommt mal was
aber nur kurzzeitig.

Gib auch ne andere Lösung um eine Periode zu Messen, da ist doch der
Wurm drin :-(

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.