Forum: Mikrocontroller und Digitale Elektronik AT89C2051 Frequenzmessung


von Jankey (Gast)


Lesenswert?

Guten morgen,

Arbeite gerade seit einigen Stunden an einer Frequenzmessung mit dem
AT89C2051 herum, Messfrequenz von 20 bis 400Hz mit einer Auflösung von
0.1Hz. Eingang: Externer Interrupt EX0 @ P3.2
der EX0 Aktiviert mit den Timer1 und lässt ihn hochzählen bis zum 2.ten
Puls der den T1 dann wieder Deaktiviert. Damit die Software diesen wert
dann zu passender zeit mal wieder abholen kann.

Krieg schöne Rechtecke daher aber ab ca. 45Hz flattert mir die Anzeige
davon. Auch die Ausgabe des eigentlichen Eingangssignals auf einem
Sepatatem Ausgang is alles andere als schön, am Oszi sieht man schön
wie die "Antwort" des externen Interrupts hin und her schwankt.

Ideen? Sources? Plan? bei mir herrscht nur noch Blanke verzweiflung,
naja so schlimm is ned aber viel fehlt nimma.

lg Jan

von crazy horse (Gast)


Lesenswert?

tja, bei deiner knappen Beschreibung (um es mal vornehm auszudrücken)
kann man nur raten.

von Jankey (Gast)


Lesenswert?

void INTEX0(void) interrupt 0 using 2
{
  RED = ~RED;

  if(new_messure == 0)            // Keine Neue Messung Aktiv!
  {
    TR1 = ~TR1;                  // Timer1 EIN/AUS

    if (TR1 == 0)                // Wurde gerade wieder DeAktiviert!  = 
MESSUNG
FERTIG!!!
    {
      EX0 = 0;                // Externen Interrupt ausschalten!
      pw_high = TH1;
      pw_low = TL1;

      TH1 = 0;
      TL1 = 0;

      new_messure = 1;
    }
  }
  else
    EX0 = 0;                  // ausschalten!
}

void INTTIM1(void) interrupt 3 using 2
{
  TF1 = 0;

  overlap++;
  if (overlap>1)    // Motor Aus!
  {
    INTEX0();
  }
}

void INTTIM0(void) interrupt 1 using 2  // Ausgelöster Interrupt 1 ->
1ms
{
  TF0 = 0;
  TH0 = 0xF8;      // 1ms Reload bei 24 MHz
  TL0 = 0x27;

  if(flag==0)
    flag = 1;

}

void init()
{
// Timer 0 & Timer 1 Aus!
  TCON = 0x00;
// Timer 0 16 Bit Zähler / Timer 1 16 Bit Zähler!
  TMOD = 0x11;
// Timer 0 : 1ms Reload bei 12 MHz
  TH0 = 0xFC;
  TL0 = 0x0F;

// Timer0 Interrupt Enable
  ET0 = 1;
  ET1 = 1;        // Timer1 Interrupt Enable

  TF0 = 0;



  EX0 = 0;        // Enable External Interrupt 1
  IT0 = 1;        // Flankengesteuert!

  IP0 |= 0x01;      // Zeitmessung Maximale Priorität!!! INTERRUPT
genauigkeit verbessern!
  IP1 |= 0x01;

  EAL = 1;        // Enable all Interrupts
}

von Jankey (Gast)


Lesenswert?

void timer_start()
{
  TR0 = 1;        // Timer0 Einschalten!!
}



void run()
{
if( new_messure == 1 )
{
new_messure = 0;
freq = 40000000/(unsigned long)(65536*overlap+pw_high*256+pw_low);
}
    // EX0 Aktivieren für Nächsten Pulse!
    if(new_messure==0 && EX0 == 0)
      EX0 = 1;
}

void main()
{
  init();
  overlap = 0;
  flag = 0;

  IP0 = 1;
  timer_start();      // Timer Starten und auf ins vergnügen!!

    while(1)
    {
      if( flag==1 )
      {
        run();
        flag = 0;
      }
    }

}




so mehr Beschreibung?

von crazy horse (Gast)


Lesenswert?

jo, besser.
Schau ich mir morgen an, wenn nicht inzwischen einer was findet.

von Jankey (Gast)


Lesenswert?

gut ich warte

von Brooks (Gast)


Lesenswert?

Periodenmessungsfehler durch die Interrupts?

von Jankey (Gast)


Lesenswert?

Weiss ich noch nicht,

der AT89C2051 nimmt die Interrupts nicht immer sofort an, vl arbeitet
er im Hintergrund an einem Anderen Interrupt, tatsache ist das 2
verschiedene Interrupts permanent angesprochen werden, 1. der Interrupt
des 1ms Timers ( T0 ), 2.tens der Externe Interrupt der eigentlich ERST
freigegeben wird wenn Timer0 Gerade fertig geworden ist damit keine
Collisions entstehen. Zumindest so das konzept, aber der Ritt auf
Interrupts is wie der Ritt auf einer 10m Welle, wenn man ganz rauf will
fällt man auch schnell mal ganz runter.

von Peter D. (peda)


Lesenswert?

Hier mal mein Frequenzmesser (0,5Hz ... 125MHz):

http://progshop.com/elektronik/diskussion/messages/4982/fmeter-7381.zip


Peter

von Jankey (Gast)


Lesenswert?

Wie ich sehe benutzt du den Timer Mode 3 falls ich das richtig
geschnallt habe, 2 counter und eine Timebase.

Ich versteh noch nicht ganz wie du "Pulsweiten" mit dem ding messen
kannst, oder misst du da nur die Pulse pro zeiteinheit?

auf jeden fall is es ein Rettungsring an dem man sich mal anklammern
kann, danke =)

lg Jan

von Jankey (Gast)


Lesenswert?

Das programm is ned hilfreich das du auf halben Amplitudenmessung übers
Gate fährst. dh.: du gehst von einer 1:1er Puls Pausen verhältnis aus.
Das is bei mir ned der fall.

von Peter D. (peda)


Lesenswert?

@Jankey,

wen meinst Du ?

Mein Programm mißt nur die Frequenz, keine Impulsdauer.
Das Tastverhältnis ist also völlig egal.

Es erfolgt immer eine Messung über volle Periodendauern von einer
0-1-Flanke bis zur nächsten 0-1-Flanke nach etwa 0,5s.

Dadurch ergibt sich unabhängig von der Frequenz eine gleichbleibend
hohe Auflösung.


Peter

von Jankey (Gast)


Lesenswert?

wie geht das? du gehts ja beim T0 eingang für HF und beim T1 Eingang für
NF, wie kannst du über einen T timer Eingang Perioden messen ohne
Interrupt noch dazu +nedversteh+

von Jankey (Gast)


Lesenswert?

Ich denke ich werde einen anderen Controller nehmen, der halt
Pincompatibel ist.

von Peter D. (peda)


Lesenswert?

"wie geht das?"

ganz einfach.
Schau Dir mal diese Sequenz an:
1
i = TL0;
2
    while( i == TL0 )
3
...

Wenn die nächste Flanke kommt, zählt er eins weiter und damit ist der
Timer ungleich dem vorherigen Wert und die Schleife wird verlassen.


Mein Programm mißt auch ständig weiter, d.h. es wird immer die
Differenz von der jetzigen zur vorherigen Auslesung gebildet.

Das hat den Vorteil, daß man bei 1Hz auch alle 1s eine neue Ablesung
erhält.

Wenn man den Timer stoppen und wieder starten würde, muß man immer noch
eine Flanke warten und würde bei 1Hz nur alle 2s einen neuen Wert
erhalten.

Das Auslesen der Timer im freien Lauf ist natürlich etwas tricky, da ja
genau dabei ein Übertrag kommen kann. Deshalb die nachfolgenden
Überlauftests und Korrekturen.

Den Bereichstest und Umschaltung kannst Du ja weglassen, ist erst ab
über 10MHz nötig.


Ein anderer Prozessor wird Dir nichts nützen.

Höchstens ein LPC2xxx von Philips (ARM7), da der 32Bit ist und auch
32Bit-Timer hat, dann entfallen die Übertragseffekte.


Peter

von Jankey (Gast)


Lesenswert?

mhm, dh.: der Timer wird mit dem Gate aktiviert, klingt nach einer
Coolen Polling methode, hoffe es geht sich mit all meiner
Anzeigekramerei aus. Werd das mal probieren

von Jankey (Gast)


Lesenswert?

aja fast hätt ich es vergessen: ein kleines Bild mit der
Anzeigeeinheit:

http://www.theng.at/html/modules/coppermine/albums/userpics/10003/PICT0024.JPG

von Jankey (Gast)


Lesenswert?

so umgebaut, programmiert, das kann ned funktionieren, das Ding erkennt
zwar flanke, aber bei nächsten Zyklus is das Gate noch immer high und
wird wieder durchlaufen nur halt mit sehr sehr kleinem Zahlenwert, hast
du das ding denn auch Mechanisch aufgebaut und es funktioniert?

von Peter D. (peda)


Lesenswert?

Da ist nichts mit nem Gate drin, beide Zähler laufen ständig durch, der
Zähler der Zeitbasis (interner Quarz) und der Zähler des
Eingangssignals.

Das Auslesen wird nach der gewählten Updatezeit auf die nächste Flanke
des Eingangssignals synchronisiert, damit man immer volle Perioden
hat.

Sonst würde man ja erhebliche Ungenauigkeiten bekommen.


Klar sind alle meine Beispiele funktionsfähig und ausprobiert.


Peter

von Jankey (Gast)


Lesenswert?

Ein Counter?

von Jankey (Gast)


Lesenswert?

wie synchronisierst du auf die nächste flanke? ah ah ah ,,, durch den
Counter, verstehe!

von Jankey (Gast)


Lesenswert?

hm, also 1x counter 1xtimer, bräuchte aber noch einen timer für die
Anzeigt die im 1ms Takt getriggtert wird.

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.