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
tja, bei deiner knappen Beschreibung (um es mal vornehm auszudrücken) kann man nur raten.
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 }
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?
jo, besser. Schau ich mir morgen an, wenn nicht inzwischen einer was findet.
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.
Hier mal mein Frequenzmesser (0,5Hz ... 125MHz): http://progshop.com/elektronik/diskussion/messages/4982/fmeter-7381.zip Peter
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
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.
@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
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+
Ich denke ich werde einen anderen Controller nehmen, der halt Pincompatibel ist.
"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
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
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
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?
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
wie synchronisierst du auf die nächste flanke? ah ah ah ,,, durch den Counter, verstehe!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.